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,
64 isTouch = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
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(){},
125 * Copies all the properties of config to obj if they don't already exist.
126 * @param {Object} obj The receiver of the properties
127 * @param {Object} config The source of the properties
128 * @return {Object} returns obj
130 applyIf : function(o, c){
133 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
140 * Applies event listeners to elements by selectors when the document is ready.
141 * The event name is specified with an @ suffix.
144 // add a listener for click on all anchors in element with id foo
145 '#foo a@click' : function(e, t){
149 // add the same listener to multiple selectors (separated by comma BEFORE the @)
150 '#foo a, #bar span.some-class@mouseover' : function(){
155 * @param {Object} obj The list of behaviors to apply
157 addBehaviors : function(o){
159 Roo.onReady(function(){
164 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
166 var parts = b.split('@');
167 if(parts[1]){ // for Object prototype breakers
170 cache[s] = Roo.select(s);
172 cache[s].on(parts[1], o[b]);
179 * Generates unique ids. If the element already has an id, it is unchanged
180 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
181 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
182 * @return {String} The generated Id.
184 id : function(el, prefix){
185 prefix = prefix || "roo-gen";
187 var id = prefix + (++idSeed);
188 return el ? (el.id ? el.id : (el.id = id)) : id;
193 * Extends one class with another class and optionally overrides members with the passed literal. This class
194 * also adds the function "override()" to the class that can be used to override
195 * members on an instance.
196 * @param {Object} subclass The class inheriting the functionality
197 * @param {Object} superclass The class being extended
198 * @param {Object} overrides (optional) A literal with members
203 var io = function(o){
208 return function(sb, sp, overrides){
209 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
212 sb = function(){sp.apply(this, arguments);};
214 var F = function(){}, sbp, spp = sp.prototype;
216 sbp = sb.prototype = new F();
220 if(spp.constructor == Object.prototype.constructor){
225 sb.override = function(o){
229 Roo.override(sb, overrides);
235 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
237 Roo.override(MyClass, {
238 newMethod1: function(){
241 newMethod2: function(foo){
246 * @param {Object} origclass The class to override
247 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
248 * containing one or more methods.
251 override : function(origclass, overrides){
253 var p = origclass.prototype;
254 for(var method in overrides){
255 p[method] = overrides[method];
260 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
262 Roo.namespace('Company', 'Company.data');
263 Company.Widget = function() { ... }
264 Company.data.CustomStore = function(config) { ... }
266 * @param {String} namespace1
267 * @param {String} namespace2
268 * @param {String} etc
271 namespace : function(){
272 var a=arguments, o=null, i, j, d, rt;
273 for (i=0; i<a.length; ++i) {
277 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
278 for (j=1; j<d.length; ++j) {
279 o[d[j]]=o[d[j]] || {};
285 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
287 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
288 Roo.factory(conf, Roo.data);
290 * @param {String} classname
291 * @param {String} namespace (optional)
295 factory : function(c, ns)
297 // no xtype, no ns or c.xns - or forced off by c.xns
298 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
301 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
304 if (c.constructor == ns[c.xtype]) {// already created...
308 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
309 var ret = new ns[c.xtype](c);
313 c.xns = false; // prevent recursion..
317 * Logs to console if it can.
319 * @param {String|Object} string
324 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
331 * 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.
335 urlEncode : function(o){
341 var ov = o[key], k = Roo.encodeURIComponent(key);
342 var type = typeof ov;
343 if(type == 'undefined'){
345 }else if(type != "function" && type != "object"){
346 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
347 }else if(ov instanceof Array){
349 for(var i = 0, len = ov.length; i < len; i++) {
350 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
361 * Safe version of encodeURIComponent
362 * @param {String} data
366 encodeURIComponent : function (data)
369 return encodeURIComponent(data);
370 } catch(e) {} // should be an uri encode error.
372 if (data == '' || data == null){
375 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
376 function nibble_to_hex(nibble){
377 var chars = '0123456789ABCDEF';
378 return chars.charAt(nibble);
380 data = data.toString();
382 for(var i=0; i<data.length; i++){
383 var c = data.charCodeAt(i);
384 var bs = new Array();
387 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
388 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
389 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
390 bs[3] = 0x80 | (c & 0x3F);
391 }else if (c > 0x800){
393 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
394 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
395 bs[2] = 0x80 | (c & 0x3F);
398 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
399 bs[1] = 0x80 | (c & 0x3F);
404 for(var j=0; j<bs.length; j++){
406 var hex = nibble_to_hex((b & 0xF0) >>> 4)
407 + nibble_to_hex(b &0x0F);
416 * 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]}.
417 * @param {String} string
418 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
419 * @return {Object} A literal with members
421 urlDecode : function(string, overwrite){
422 if(!string || !string.length){
426 var pairs = string.split('&');
427 var pair, name, value;
428 for(var i = 0, len = pairs.length; i < len; i++){
429 pair = pairs[i].split('=');
430 name = decodeURIComponent(pair[0]);
431 value = decodeURIComponent(pair[1]);
432 if(overwrite !== true){
433 if(typeof obj[name] == "undefined"){
435 }else if(typeof obj[name] == "string"){
436 obj[name] = [obj[name]];
437 obj[name].push(value);
439 obj[name].push(value);
449 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
450 * passed array is not really an array, your function is called once with it.
451 * The supplied function is called with (Object item, Number index, Array allItems).
452 * @param {Array/NodeList/Mixed} array
453 * @param {Function} fn
454 * @param {Object} scope
456 each : function(array, fn, scope){
457 if(typeof array.length == "undefined" || typeof array == "string"){
460 for(var i = 0, len = array.length; i < len; i++){
461 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
466 combine : function(){
467 var as = arguments, l = as.length, r = [];
468 for(var i = 0; i < l; i++){
470 if(a instanceof Array){
472 }else if(a.length !== undefined && !a.substr){
473 r = r.concat(Array.prototype.slice.call(a, 0));
482 * Escapes the passed string for use in a regular expression
483 * @param {String} str
486 escapeRe : function(s) {
487 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
491 callback : function(cb, scope, args, delay){
492 if(typeof cb == "function"){
494 cb.defer(delay, scope, args || []);
496 cb.apply(scope, args || []);
502 * Return the dom node for the passed string (id), dom node, or Roo.Element
503 * @param {String/HTMLElement/Roo.Element} el
504 * @return HTMLElement
506 getDom : function(el){
510 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
514 * Shorthand for {@link Roo.ComponentMgr#get}
516 * @return Roo.Component
518 getCmp : function(id){
519 return Roo.ComponentMgr.get(id);
522 num : function(v, defaultValue){
523 if(typeof v != 'number'){
529 destroy : function(){
530 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
534 as.removeAllListeners();
538 if(typeof as.purgeListeners == 'function'){
541 if(typeof as.destroy == 'function'){
548 // inpired by a similar function in mootools library
550 * Returns the type of object that is passed in. If the object passed in is null or undefined it
551 * return false otherwise it returns one of the following values:<ul>
552 * <li><b>string</b>: If the object passed is a string</li>
553 * <li><b>number</b>: If the object passed is a number</li>
554 * <li><b>boolean</b>: If the object passed is a boolean value</li>
555 * <li><b>function</b>: If the object passed is a function reference</li>
556 * <li><b>object</b>: If the object passed is an object</li>
557 * <li><b>array</b>: If the object passed is an array</li>
558 * <li><b>regexp</b>: If the object passed is a regular expression</li>
559 * <li><b>element</b>: If the object passed is a DOM Element</li>
560 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
561 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
562 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
563 * @param {Mixed} object
567 if(o === undefined || o === null){
574 if(t == 'object' && o.nodeName) {
576 case 1: return 'element';
577 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
580 if(t == 'object' || t == 'function') {
581 switch(o.constructor) {
582 case Array: return 'array';
583 case RegExp: return 'regexp';
585 if(typeof o.length == 'number' && typeof o.item == 'function') {
593 * Returns true if the passed value is null, undefined or an empty string (optional).
594 * @param {Mixed} value The value to test
595 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
598 isEmpty : function(v, allowBlank){
599 return v === null || v === undefined || (!allowBlank ? v === '' : false);
613 isBorderBox : isBorderBox,
615 isWindows : isWindows,
624 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
625 * you may want to set this to true.
628 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
633 * Selects a single element as a Roo Element
634 * This is about as close as you can get to jQuery's $('do crazy stuff')
635 * @param {String} selector The selector/xpath query
636 * @param {Node} root (optional) The start of the query (defaults to document).
637 * @return {Roo.Element}
639 selectNode : function(selector, root)
641 var node = Roo.DomQuery.selectNode(selector,root);
642 return node ? Roo.get(node) : new Roo.Element(false);
650 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
651 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
654 * Ext JS Library 1.1.1
655 * Copyright(c) 2006-2007, Ext JS, LLC.
657 * Originally Released Under LGPL - original licence link has changed is not relivant.
660 * <script type="text/javascript">
664 // wrappedn so fnCleanup is not in global scope...
666 function fnCleanUp() {
667 var p = Function.prototype;
668 delete p.createSequence;
670 delete p.createDelegate;
671 delete p.createCallback;
672 delete p.createInterceptor;
674 window.detachEvent("onunload", fnCleanUp);
676 window.attachEvent("onunload", fnCleanUp);
683 * These functions are available on every Function object (any JavaScript function).
685 Roo.apply(Function.prototype, {
687 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
688 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
689 * Will create a function that is bound to those 2 args.
690 * @return {Function} The new function
692 createCallback : function(/*args...*/){
693 // make args available, in function below
694 var args = arguments;
697 return method.apply(window, args);
702 * Creates a delegate (callback) that sets the scope to obj.
703 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
704 * Will create a function that is automatically scoped to this.
705 * @param {Object} obj (optional) The object for which the scope is set
706 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
707 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
708 * if a number the args are inserted at the specified position
709 * @return {Function} The new function
711 createDelegate : function(obj, args, appendArgs){
714 var callArgs = args || arguments;
715 if(appendArgs === true){
716 callArgs = Array.prototype.slice.call(arguments, 0);
717 callArgs = callArgs.concat(args);
718 }else if(typeof appendArgs == "number"){
719 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
720 var applyArgs = [appendArgs, 0].concat(args); // create method call params
721 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
723 return method.apply(obj || window, callArgs);
728 * Calls this function after the number of millseconds specified.
729 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
730 * @param {Object} obj (optional) The object for which the scope is set
731 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
732 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
733 * if a number the args are inserted at the specified position
734 * @return {Number} The timeout id that can be used with clearTimeout
736 defer : function(millis, obj, args, appendArgs){
737 var fn = this.createDelegate(obj, args, appendArgs);
739 return setTimeout(fn, millis);
745 * Create a combined function call sequence of the original function + the passed function.
746 * The resulting function returns the results of the original function.
747 * The passed fcn is called with the parameters of the original function
748 * @param {Function} fcn The function to sequence
749 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
750 * @return {Function} The new function
752 createSequence : function(fcn, scope){
753 if(typeof fcn != "function"){
758 var retval = method.apply(this || window, arguments);
759 fcn.apply(scope || this || window, arguments);
765 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
766 * The resulting function returns the results of the original function.
767 * The passed fcn is called with the parameters of the original function.
769 * @param {Function} fcn The function to call before the original
770 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
771 * @return {Function} The new function
773 createInterceptor : function(fcn, scope){
774 if(typeof fcn != "function"){
781 if(fcn.apply(scope || this || window, arguments) === false){
784 return method.apply(this || window, arguments);
790 * Ext JS Library 1.1.1
791 * Copyright(c) 2006-2007, Ext JS, LLC.
793 * Originally Released Under LGPL - original licence link has changed is not relivant.
796 * <script type="text/javascript">
799 Roo.applyIf(String, {
804 * Escapes the passed string for ' and \
805 * @param {String} string The string to escape
806 * @return {String} The escaped string
809 escape : function(string) {
810 return string.replace(/('|\\)/g, "\\$1");
814 * Pads the left side of a string with a specified character. This is especially useful
815 * for normalizing number and date strings. Example usage:
817 var s = String.leftPad('123', 5, '0');
818 // s now contains the string: '00123'
820 * @param {String} string The original string
821 * @param {Number} size The total length of the output string
822 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
823 * @return {String} The padded string
826 leftPad : function (val, size, ch) {
827 var result = new String(val);
828 if(ch === null || ch === undefined || ch === '') {
831 while (result.length < size) {
832 result = ch + result;
838 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
839 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
841 var cls = 'my-class', text = 'Some text';
842 var s = String.format('<div class="{0}">{1}</div>', cls, text);
843 // s now contains the string: '<div class="my-class">Some text</div>'
845 * @param {String} string The tokenized string to be formatted
846 * @param {String} value1 The value to replace token {0}
847 * @param {String} value2 Etc...
848 * @return {String} The formatted string
851 format : function(format){
852 var args = Array.prototype.slice.call(arguments, 1);
853 return format.replace(/\{(\d+)\}/g, function(m, i){
854 return Roo.util.Format.htmlEncode(args[i]);
860 * Utility function that allows you to easily switch a string between two alternating values. The passed value
861 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
862 * they are already different, the first value passed in is returned. Note that this method returns the new value
863 * but does not change the current string.
865 // alternate sort directions
866 sort = sort.toggle('ASC', 'DESC');
868 // instead of conditional logic:
869 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
871 * @param {String} value The value to compare to the current string
872 * @param {String} other The new value to use if the string already equals the first value passed in
873 * @return {String} The new value
876 String.prototype.toggle = function(value, other){
877 return this == value ? other : value;
880 * Ext JS Library 1.1.1
881 * Copyright(c) 2006-2007, Ext JS, LLC.
883 * Originally Released Under LGPL - original licence link has changed is not relivant.
886 * <script type="text/javascript">
892 Roo.applyIf(Number.prototype, {
894 * Checks whether or not the current number is within a desired range. If the number is already within the
895 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
896 * exceeded. Note that this method returns the constrained value but does not change the current number.
897 * @param {Number} min The minimum number in the range
898 * @param {Number} max The maximum number in the range
899 * @return {Number} The constrained value if outside the range, otherwise the current value
901 constrain : function(min, max){
902 return Math.min(Math.max(this, min), max);
906 * Ext JS Library 1.1.1
907 * Copyright(c) 2006-2007, Ext JS, LLC.
909 * Originally Released Under LGPL - original licence link has changed is not relivant.
912 * <script type="text/javascript">
917 Roo.applyIf(Array.prototype, {
919 * Checks whether or not the specified object exists in the array.
920 * @param {Object} o The object to check for
921 * @return {Number} The index of o in the array (or -1 if it is not found)
923 indexOf : function(o){
924 for (var i = 0, len = this.length; i < len; i++){
925 if(this[i] == o) return i;
931 * Removes the specified object from the array. If the object is not found nothing happens.
932 * @param {Object} o The object to remove
934 remove : function(o){
935 var index = this.indexOf(o);
937 this.splice(index, 1);
941 * Map (JS 1.6 compatibility)
942 * @param {Function} function to call
946 var len = this.length >>> 0;
947 if (typeof fun != "function")
948 throw new TypeError();
950 var res = new Array(len);
951 var thisp = arguments[1];
952 for (var i = 0; i < len; i++)
955 res[i] = fun.call(thisp, this[i], i, this);
966 * Ext JS Library 1.1.1
967 * Copyright(c) 2006-2007, Ext JS, LLC.
969 * Originally Released Under LGPL - original licence link has changed is not relivant.
972 * <script type="text/javascript">
978 * The date parsing and format syntax is a subset of
979 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
980 * supported will provide results equivalent to their PHP versions.
982 * Following is the list of all currently supported formats:
985 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
987 Format Output Description
988 ------ ---------- --------------------------------------------------------------
989 d 10 Day of the month, 2 digits with leading zeros
990 D Wed A textual representation of a day, three letters
991 j 10 Day of the month without leading zeros
992 l Wednesday A full textual representation of the day of the week
993 S th English ordinal day of month suffix, 2 chars (use with j)
994 w 3 Numeric representation of the day of the week
995 z 9 The julian date, or day of the year (0-365)
996 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
997 F January A full textual representation of the month
998 m 01 Numeric representation of a month, with leading zeros
999 M Jan Month name abbreviation, three letters
1000 n 1 Numeric representation of a month, without leading zeros
1001 t 31 Number of days in the given month
1002 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1003 Y 2007 A full numeric representation of a year, 4 digits
1004 y 07 A two digit representation of a year
1005 a pm Lowercase Ante meridiem and Post meridiem
1006 A PM Uppercase Ante meridiem and Post meridiem
1007 g 3 12-hour format of an hour without leading zeros
1008 G 15 24-hour format of an hour without leading zeros
1009 h 03 12-hour format of an hour with leading zeros
1010 H 15 24-hour format of an hour with leading zeros
1011 i 05 Minutes with leading zeros
1012 s 01 Seconds, with leading zeros
1013 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1014 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1015 T CST Timezone setting of the machine running the code
1016 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1019 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1021 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1022 document.write(dt.format('Y-m-d')); //2007-01-10
1023 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1024 document.write(dt.format('l, \\t\\he dS of F Y h:i:s A')); //Wednesday, the 10th of January 2007 03:05:01 PM
1027 * Here are some standard date/time patterns that you might find helpful. They
1028 * are not part of the source of Date.js, but to use them you can simply copy this
1029 * block of code into any script that is included after Date.js and they will also become
1030 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1033 ISO8601Long:"Y-m-d H:i:s",
1034 ISO8601Short:"Y-m-d",
1036 LongDate: "l, F d, Y",
1037 FullDateTime: "l, F d, Y g:i:s A",
1040 LongTime: "g:i:s A",
1041 SortableDateTime: "Y-m-d\\TH:i:s",
1042 UniversalSortableDateTime: "Y-m-d H:i:sO",
1049 var dt = new Date();
1050 document.write(dt.format(Date.patterns.ShortDate));
1055 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1056 * They generate precompiled functions from date formats instead of parsing and
1057 * processing the pattern every time you format a date. These functions are available
1058 * on every Date object (any javascript function).
1060 * The original article and download are here:
1061 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1068 Returns the number of milliseconds between this date and date
1069 @param {Date} date (optional) Defaults to now
1070 @return {Number} The diff in milliseconds
1071 @member Date getElapsed
1073 Date.prototype.getElapsed = function(date) {
1074 return Math.abs((date || new Date()).getTime()-this.getTime());
1076 // was in date file..
1080 Date.parseFunctions = {count:0};
1082 Date.parseRegexes = [];
1084 Date.formatFunctions = {count:0};
1087 Date.prototype.dateFormat = function(format) {
1088 if (Date.formatFunctions[format] == null) {
1089 Date.createNewFormat(format);
1091 var func = Date.formatFunctions[format];
1092 return this[func]();
1097 * Formats a date given the supplied format string
1098 * @param {String} format The format string
1099 * @return {String} The formatted date
1102 Date.prototype.format = Date.prototype.dateFormat;
1105 Date.createNewFormat = function(format) {
1106 var funcName = "format" + Date.formatFunctions.count++;
1107 Date.formatFunctions[format] = funcName;
1108 var code = "Date.prototype." + funcName + " = function(){return ";
1109 var special = false;
1111 for (var i = 0; i < format.length; ++i) {
1112 ch = format.charAt(i);
1113 if (!special && ch == "\\") {
1118 code += "'" + String.escape(ch) + "' + ";
1121 code += Date.getFormatCode(ch);
1124 /** eval:var:zzzzzzzzzzzzz */
1125 eval(code.substring(0, code.length - 3) + ";}");
1129 Date.getFormatCode = function(character) {
1130 switch (character) {
1132 return "String.leftPad(this.getDate(), 2, '0') + ";
1134 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1136 return "this.getDate() + ";
1138 return "Date.dayNames[this.getDay()] + ";
1140 return "this.getSuffix() + ";
1142 return "this.getDay() + ";
1144 return "this.getDayOfYear() + ";
1146 return "this.getWeekOfYear() + ";
1148 return "Date.monthNames[this.getMonth()] + ";
1150 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1152 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1154 return "(this.getMonth() + 1) + ";
1156 return "this.getDaysInMonth() + ";
1158 return "(this.isLeapYear() ? 1 : 0) + ";
1160 return "this.getFullYear() + ";
1162 return "('' + this.getFullYear()).substring(2, 4) + ";
1164 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1166 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1168 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1170 return "this.getHours() + ";
1172 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1174 return "String.leftPad(this.getHours(), 2, '0') + ";
1176 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1178 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1180 return "this.getGMTOffset() + ";
1182 return "this.getGMTColonOffset() + ";
1184 return "this.getTimezone() + ";
1186 return "(this.getTimezoneOffset() * -60) + ";
1188 return "'" + String.escape(character) + "' + ";
1193 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1194 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1195 * the date format that is not specified will default to the current date value for that part. Time parts can also
1196 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1197 * string or the parse operation will fail.
1200 //dt = Fri May 25 2007 (current date)
1201 var dt = new Date();
1203 //dt = Thu May 25 2006 (today's month/day in 2006)
1204 dt = Date.parseDate("2006", "Y");
1206 //dt = Sun Jan 15 2006 (all date parts specified)
1207 dt = Date.parseDate("2006-1-15", "Y-m-d");
1209 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1210 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1212 * @param {String} input The unparsed date as a string
1213 * @param {String} format The format the date is in
1214 * @return {Date} The parsed date
1217 Date.parseDate = function(input, format) {
1218 if (Date.parseFunctions[format] == null) {
1219 Date.createParser(format);
1221 var func = Date.parseFunctions[format];
1222 return Date[func](input);
1227 Date.createParser = function(format) {
1228 var funcName = "parse" + Date.parseFunctions.count++;
1229 var regexNum = Date.parseRegexes.length;
1230 var currentGroup = 1;
1231 Date.parseFunctions[format] = funcName;
1233 var code = "Date." + funcName + " = function(input){\n"
1234 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1235 + "var d = new Date();\n"
1236 + "y = d.getFullYear();\n"
1237 + "m = d.getMonth();\n"
1238 + "d = d.getDate();\n"
1239 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1240 + "if (results && results.length > 0) {";
1243 var special = false;
1245 for (var i = 0; i < format.length; ++i) {
1246 ch = format.charAt(i);
1247 if (!special && ch == "\\") {
1252 regex += String.escape(ch);
1255 var obj = Date.formatCodeToRegex(ch, currentGroup);
1256 currentGroup += obj.g;
1258 if (obj.g && obj.c) {
1264 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1265 + "{v = new Date(y, m, d, h, i, s);}\n"
1266 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1267 + "{v = new Date(y, m, d, h, i);}\n"
1268 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1269 + "{v = new Date(y, m, d, h);}\n"
1270 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1271 + "{v = new Date(y, m, d);}\n"
1272 + "else if (y >= 0 && m >= 0)\n"
1273 + "{v = new Date(y, m);}\n"
1274 + "else if (y >= 0)\n"
1275 + "{v = new Date(y);}\n"
1276 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1277 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1278 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1281 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1282 /** eval:var:zzzzzzzzzzzzz */
1287 Date.formatCodeToRegex = function(character, currentGroup) {
1288 switch (character) {
1292 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1295 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1296 s:"(\\d{1,2})"}; // day of month without leading zeroes
1299 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1300 s:"(\\d{2})"}; // day of month with leading zeroes
1304 s:"(?:" + Date.dayNames.join("|") + ")"};
1308 s:"(?:st|nd|rd|th)"};
1323 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1324 s:"(" + Date.monthNames.join("|") + ")"};
1327 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1328 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1331 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1332 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1335 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1336 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1347 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1351 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1352 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1356 c:"if (results[" + currentGroup + "] == 'am') {\n"
1357 + "if (h == 12) { h = 0; }\n"
1358 + "} else { if (h < 12) { h += 12; }}",
1362 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1363 + "if (h == 12) { h = 0; }\n"
1364 + "} else { if (h < 12) { h += 12; }}",
1369 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1370 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1374 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1375 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1378 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1382 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1387 "o = results[", currentGroup, "];\n",
1388 "var sn = o.substring(0,1);\n", // get + / - sign
1389 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1390 "var mn = o.substring(3,5) % 60;\n", // get minutes
1391 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1392 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1394 s:"([+\-]\\d{2,4})"};
1400 "o = results[", currentGroup, "];\n",
1401 "var sn = o.substring(0,1);\n",
1402 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1403 "var mn = o.substring(4,6) % 60;\n",
1404 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1405 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1411 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1414 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1415 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1416 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1420 s:String.escape(character)};
1425 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1426 * @return {String} The abbreviated timezone name (e.g. 'CST')
1428 Date.prototype.getTimezone = function() {
1429 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1433 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1434 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1436 Date.prototype.getGMTOffset = function() {
1437 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1438 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1439 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1443 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1444 * @return {String} 2-characters representing hours and 2-characters representing minutes
1445 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1447 Date.prototype.getGMTColonOffset = function() {
1448 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1449 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1451 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1455 * Get the numeric day number of the year, adjusted for leap year.
1456 * @return {Number} 0 through 364 (365 in leap years)
1458 Date.prototype.getDayOfYear = function() {
1460 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1461 for (var i = 0; i < this.getMonth(); ++i) {
1462 num += Date.daysInMonth[i];
1464 return num + this.getDate() - 1;
1468 * Get the string representation of the numeric week number of the year
1469 * (equivalent to the format specifier 'W').
1470 * @return {String} '00' through '52'
1472 Date.prototype.getWeekOfYear = function() {
1473 // Skip to Thursday of this week
1474 var now = this.getDayOfYear() + (4 - this.getDay());
1475 // Find the first Thursday of the year
1476 var jan1 = new Date(this.getFullYear(), 0, 1);
1477 var then = (7 - jan1.getDay() + 4);
1478 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1482 * Whether or not the current date is in a leap year.
1483 * @return {Boolean} True if the current date is in a leap year, else false
1485 Date.prototype.isLeapYear = function() {
1486 var year = this.getFullYear();
1487 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1491 * Get the first day of the current month, adjusted for leap year. The returned value
1492 * is the numeric day index within the week (0-6) which can be used in conjunction with
1493 * the {@link #monthNames} array to retrieve the textual day name.
1496 var dt = new Date('1/10/2007');
1497 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1499 * @return {Number} The day number (0-6)
1501 Date.prototype.getFirstDayOfMonth = function() {
1502 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1503 return (day < 0) ? (day + 7) : day;
1507 * Get the last day of the current month, adjusted for leap year. The returned value
1508 * is the numeric day index within the week (0-6) which can be used in conjunction with
1509 * the {@link #monthNames} array to retrieve the textual day name.
1512 var dt = new Date('1/10/2007');
1513 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1515 * @return {Number} The day number (0-6)
1517 Date.prototype.getLastDayOfMonth = function() {
1518 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1519 return (day < 0) ? (day + 7) : day;
1524 * Get the first date of this date's month
1527 Date.prototype.getFirstDateOfMonth = function() {
1528 return new Date(this.getFullYear(), this.getMonth(), 1);
1532 * Get the last date of this date's month
1535 Date.prototype.getLastDateOfMonth = function() {
1536 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1539 * Get the number of days in the current month, adjusted for leap year.
1540 * @return {Number} The number of days in the month
1542 Date.prototype.getDaysInMonth = function() {
1543 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1544 return Date.daysInMonth[this.getMonth()];
1548 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1549 * @return {String} 'st, 'nd', 'rd' or 'th'
1551 Date.prototype.getSuffix = function() {
1552 switch (this.getDate()) {
1569 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1572 * An array of textual month names.
1573 * Override these values for international dates, for example...
1574 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1593 * An array of textual day names.
1594 * Override these values for international dates, for example...
1595 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1611 Date.monthNumbers = {
1626 * Creates and returns a new Date instance with the exact same date value as the called instance.
1627 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1628 * variable will also be changed. When the intention is to create a new variable that will not
1629 * modify the original instance, you should create a clone.
1631 * Example of correctly cloning a date:
1634 var orig = new Date('10/1/2006');
1637 document.write(orig); //returns 'Thu Oct 05 2006'!
1640 var orig = new Date('10/1/2006');
1641 var copy = orig.clone();
1643 document.write(orig); //returns 'Thu Oct 01 2006'
1645 * @return {Date} The new Date instance
1647 Date.prototype.clone = function() {
1648 return new Date(this.getTime());
1652 * Clears any time information from this date
1653 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1654 @return {Date} this or the clone
1656 Date.prototype.clearTime = function(clone){
1658 return this.clone().clearTime();
1663 this.setMilliseconds(0);
1668 // safari setMonth is broken
1670 Date.brokenSetMonth = Date.prototype.setMonth;
1671 Date.prototype.setMonth = function(num){
1673 var n = Math.ceil(-num);
1674 var back_year = Math.ceil(n/12);
1675 var month = (n % 12) ? 12 - n % 12 : 0 ;
1676 this.setFullYear(this.getFullYear() - back_year);
1677 return Date.brokenSetMonth.call(this, month);
1679 return Date.brokenSetMonth.apply(this, arguments);
1684 /** Date interval constant
1688 /** Date interval constant
1692 /** Date interval constant
1696 /** Date interval constant
1700 /** Date interval constant
1704 /** Date interval constant
1708 /** Date interval constant
1714 * Provides a convenient method of performing basic date arithmetic. This method
1715 * does not modify the Date instance being called - it creates and returns
1716 * a new Date instance containing the resulting date value.
1721 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1722 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1724 //Negative values will subtract correctly:
1725 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1726 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1728 //You can even chain several calls together in one line!
1729 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1730 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1733 * @param {String} interval A valid date interval enum value
1734 * @param {Number} value The amount to add to the current date
1735 * @return {Date} The new Date instance
1737 Date.prototype.add = function(interval, value){
1738 var d = this.clone();
1739 if (!interval || value === 0) return d;
1740 switch(interval.toLowerCase()){
1742 d.setMilliseconds(this.getMilliseconds() + value);
1745 d.setSeconds(this.getSeconds() + value);
1748 d.setMinutes(this.getMinutes() + value);
1751 d.setHours(this.getHours() + value);
1754 d.setDate(this.getDate() + value);
1757 var day = this.getDate();
1759 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1762 d.setMonth(this.getMonth() + value);
1765 d.setFullYear(this.getFullYear() + value);
1772 * Ext JS Library 1.1.1
1773 * Copyright(c) 2006-2007, Ext JS, LLC.
1775 * Originally Released Under LGPL - original licence link has changed is not relivant.
1778 * <script type="text/javascript">
1782 * @class Roo.lib.Dom
1785 * Dom utils (from YIU afaik)
1790 * Get the view width
1791 * @param {Boolean} full True will get the full document, otherwise it's the view width
1792 * @return {Number} The width
1795 getViewWidth : function(full) {
1796 return full ? this.getDocumentWidth() : this.getViewportWidth();
1799 * Get the view height
1800 * @param {Boolean} full True will get the full document, otherwise it's the view height
1801 * @return {Number} The height
1803 getViewHeight : function(full) {
1804 return full ? this.getDocumentHeight() : this.getViewportHeight();
1807 getDocumentHeight: function() {
1808 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1809 return Math.max(scrollHeight, this.getViewportHeight());
1812 getDocumentWidth: function() {
1813 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1814 return Math.max(scrollWidth, this.getViewportWidth());
1817 getViewportHeight: function() {
1818 var height = self.innerHeight;
1819 var mode = document.compatMode;
1821 if ((mode || Roo.isIE) && !Roo.isOpera) {
1822 height = (mode == "CSS1Compat") ?
1823 document.documentElement.clientHeight :
1824 document.body.clientHeight;
1830 getViewportWidth: function() {
1831 var width = self.innerWidth;
1832 var mode = document.compatMode;
1834 if (mode || Roo.isIE) {
1835 width = (mode == "CSS1Compat") ?
1836 document.documentElement.clientWidth :
1837 document.body.clientWidth;
1842 isAncestor : function(p, c) {
1849 if (p.contains && !Roo.isSafari) {
1850 return p.contains(c);
1851 } else if (p.compareDocumentPosition) {
1852 return !!(p.compareDocumentPosition(c) & 16);
1854 var parent = c.parentNode;
1859 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1862 parent = parent.parentNode;
1868 getRegion : function(el) {
1869 return Roo.lib.Region.getRegion(el);
1872 getY : function(el) {
1873 return this.getXY(el)[1];
1876 getX : function(el) {
1877 return this.getXY(el)[0];
1880 getXY : function(el) {
1881 var p, pe, b, scroll, bd = document.body;
1882 el = Roo.getDom(el);
1883 var fly = Roo.lib.AnimBase.fly;
1884 if (el.getBoundingClientRect) {
1885 b = el.getBoundingClientRect();
1886 scroll = fly(document).getScroll();
1887 return [b.left + scroll.left, b.top + scroll.top];
1893 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1900 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1907 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1908 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1915 if (p != el && pe.getStyle('overflow') != 'visible') {
1923 if (Roo.isSafari && hasAbsolute) {
1928 if (Roo.isGecko && !hasAbsolute) {
1930 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1931 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1935 while (p && p != bd) {
1936 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1948 setXY : function(el, xy) {
1949 el = Roo.fly(el, '_setXY');
1951 var pts = el.translatePoints(xy);
1952 if (xy[0] !== false) {
1953 el.dom.style.left = pts.left + "px";
1955 if (xy[1] !== false) {
1956 el.dom.style.top = pts.top + "px";
1960 setX : function(el, x) {
1961 this.setXY(el, [x, false]);
1964 setY : function(el, y) {
1965 this.setXY(el, [false, y]);
1969 * Portions of this file are based on pieces of Yahoo User Interface Library
1970 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1971 * YUI licensed under the BSD License:
1972 * http://developer.yahoo.net/yui/license.txt
1973 * <script type="text/javascript">
1977 Roo.lib.Event = function() {
1978 var loadComplete = false;
1980 var unloadListeners = [];
1982 var onAvailStack = [];
1984 var lastError = null;
1997 startInterval: function() {
1998 if (!this._interval) {
2000 var callback = function() {
2001 self._tryPreloadAttach();
2003 this._interval = setInterval(callback, this.POLL_INTERVAL);
2008 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2009 onAvailStack.push({ id: p_id,
2012 override: p_override,
2013 checkReady: false });
2015 retryCount = this.POLL_RETRYS;
2016 this.startInterval();
2020 addListener: function(el, eventName, fn) {
2021 el = Roo.getDom(el);
2026 if ("unload" == eventName) {
2027 unloadListeners[unloadListeners.length] =
2028 [el, eventName, fn];
2032 var wrappedFn = function(e) {
2033 return fn(Roo.lib.Event.getEvent(e));
2036 var li = [el, eventName, fn, wrappedFn];
2038 var index = listeners.length;
2039 listeners[index] = li;
2041 this.doAdd(el, eventName, wrappedFn, false);
2047 removeListener: function(el, eventName, fn) {
2050 el = Roo.getDom(el);
2053 return this.purgeElement(el, false, eventName);
2057 if ("unload" == eventName) {
2059 for (i = 0,len = unloadListeners.length; i < len; i++) {
2060 var li = unloadListeners[i];
2063 li[1] == eventName &&
2065 unloadListeners.splice(i, 1);
2073 var cacheItem = null;
2076 var index = arguments[3];
2078 if ("undefined" == typeof index) {
2079 index = this._getCacheIndex(el, eventName, fn);
2083 cacheItem = listeners[index];
2086 if (!el || !cacheItem) {
2090 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2092 delete listeners[index][this.WFN];
2093 delete listeners[index][this.FN];
2094 listeners.splice(index, 1);
2101 getTarget: function(ev, resolveTextNode) {
2102 ev = ev.browserEvent || ev;
2103 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2104 var t = ev.target || ev.srcElement;
2105 return this.resolveTextNode(t);
2109 resolveTextNode: function(node) {
2110 if (Roo.isSafari && node && 3 == node.nodeType) {
2111 return node.parentNode;
2118 getPageX: function(ev) {
2119 ev = ev.browserEvent || ev;
2120 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2122 if (!x && 0 !== x) {
2123 x = ev.clientX || 0;
2126 x += this.getScroll()[1];
2134 getPageY: function(ev) {
2135 ev = ev.browserEvent || ev;
2136 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2138 if (!y && 0 !== y) {
2139 y = ev.clientY || 0;
2142 y += this.getScroll()[0];
2151 getXY: function(ev) {
2152 ev = ev.browserEvent || ev;
2153 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2154 return [this.getPageX(ev), this.getPageY(ev)];
2158 getRelatedTarget: function(ev) {
2159 ev = ev.browserEvent || ev;
2160 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2161 var t = ev.relatedTarget;
2163 if (ev.type == "mouseout") {
2165 } else if (ev.type == "mouseover") {
2170 return this.resolveTextNode(t);
2174 getTime: function(ev) {
2175 ev = ev.browserEvent || ev;
2176 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2178 var t = new Date().getTime();
2182 this.lastError = ex;
2191 stopEvent: function(ev) {
2192 this.stopPropagation(ev);
2193 this.preventDefault(ev);
2197 stopPropagation: function(ev) {
2198 ev = ev.browserEvent || ev;
2199 if (ev.stopPropagation) {
2200 ev.stopPropagation();
2202 ev.cancelBubble = true;
2207 preventDefault: function(ev) {
2208 ev = ev.browserEvent || ev;
2209 if(ev.preventDefault) {
2210 ev.preventDefault();
2212 ev.returnValue = false;
2217 getEvent: function(e) {
2218 var ev = e || window.event;
2220 var c = this.getEvent.caller;
2222 ev = c.arguments[0];
2223 if (ev && Event == ev.constructor) {
2233 getCharCode: function(ev) {
2234 ev = ev.browserEvent || ev;
2235 return ev.charCode || ev.keyCode || 0;
2239 _getCacheIndex: function(el, eventName, fn) {
2240 for (var i = 0,len = listeners.length; i < len; ++i) {
2241 var li = listeners[i];
2243 li[this.FN] == fn &&
2244 li[this.EL] == el &&
2245 li[this.TYPE] == eventName) {
2257 getEl: function(id) {
2258 return document.getElementById(id);
2262 clearCache: function() {
2266 _load: function(e) {
2267 loadComplete = true;
2268 var EU = Roo.lib.Event;
2272 EU.doRemove(window, "load", EU._load);
2277 _tryPreloadAttach: function() {
2286 var tryAgain = !loadComplete;
2288 tryAgain = (retryCount > 0);
2293 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2294 var item = onAvailStack[i];
2296 var el = this.getEl(item.id);
2299 if (!item.checkReady ||
2302 (document && document.body)) {
2305 if (item.override) {
2306 if (item.override === true) {
2309 scope = item.override;
2312 item.fn.call(scope, item.obj);
2313 onAvailStack[i] = null;
2316 notAvail.push(item);
2321 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2325 this.startInterval();
2327 clearInterval(this._interval);
2328 this._interval = null;
2331 this.locked = false;
2338 purgeElement: function(el, recurse, eventName) {
2339 var elListeners = this.getListeners(el, eventName);
2341 for (var i = 0,len = elListeners.length; i < len; ++i) {
2342 var l = elListeners[i];
2343 this.removeListener(el, l.type, l.fn);
2347 if (recurse && el && el.childNodes) {
2348 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2349 this.purgeElement(el.childNodes[i], recurse, eventName);
2355 getListeners: function(el, eventName) {
2356 var results = [], searchLists;
2358 searchLists = [listeners, unloadListeners];
2359 } else if (eventName == "unload") {
2360 searchLists = [unloadListeners];
2362 searchLists = [listeners];
2365 for (var j = 0; j < searchLists.length; ++j) {
2366 var searchList = searchLists[j];
2367 if (searchList && searchList.length > 0) {
2368 for (var i = 0,len = searchList.length; i < len; ++i) {
2369 var l = searchList[i];
2370 if (l && l[this.EL] === el &&
2371 (!eventName || eventName === l[this.TYPE])) {
2376 adjust: l[this.ADJ_SCOPE],
2384 return (results.length) ? results : null;
2388 _unload: function(e) {
2390 var EU = Roo.lib.Event, i, j, l, len, index;
2392 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2393 l = unloadListeners[i];
2396 if (l[EU.ADJ_SCOPE]) {
2397 if (l[EU.ADJ_SCOPE] === true) {
2400 scope = l[EU.ADJ_SCOPE];
2403 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2404 unloadListeners[i] = null;
2410 unloadListeners = null;
2412 if (listeners && listeners.length > 0) {
2413 j = listeners.length;
2416 l = listeners[index];
2418 EU.removeListener(l[EU.EL], l[EU.TYPE],
2428 EU.doRemove(window, "unload", EU._unload);
2433 getScroll: function() {
2434 var dd = document.documentElement, db = document.body;
2435 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2436 return [dd.scrollTop, dd.scrollLeft];
2438 return [db.scrollTop, db.scrollLeft];
2445 doAdd: function () {
2446 if (window.addEventListener) {
2447 return function(el, eventName, fn, capture) {
2448 el.addEventListener(eventName, fn, (capture));
2450 } else if (window.attachEvent) {
2451 return function(el, eventName, fn, capture) {
2452 el.attachEvent("on" + eventName, fn);
2461 doRemove: function() {
2462 if (window.removeEventListener) {
2463 return function (el, eventName, fn, capture) {
2464 el.removeEventListener(eventName, fn, (capture));
2466 } else if (window.detachEvent) {
2467 return function (el, eventName, fn) {
2468 el.detachEvent("on" + eventName, fn);
2480 var E = Roo.lib.Event;
2481 E.on = E.addListener;
2482 E.un = E.removeListener;
2484 if (document && document.body) {
2487 E.doAdd(window, "load", E._load);
2489 E.doAdd(window, "unload", E._unload);
2490 E._tryPreloadAttach();
2494 * Portions of this file are based on pieces of Yahoo User Interface Library
2495 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2496 * YUI licensed under the BSD License:
2497 * http://developer.yahoo.net/yui/license.txt
2498 * <script type="text/javascript">
2504 * @class Roo.lib.Ajax
2511 request : function(method, uri, cb, data, options) {
2513 var hs = options.headers;
2516 if(hs.hasOwnProperty(h)){
2517 this.initHeader(h, hs[h], false);
2521 if(options.xmlData){
2522 this.initHeader('Content-Type', 'text/xml', false);
2524 data = options.xmlData;
2528 return this.asyncRequest(method, uri, cb, data);
2531 serializeForm : function(form) {
2532 if(typeof form == 'string') {
2533 form = (document.getElementById(form) || document.forms[form]);
2536 var el, name, val, disabled, data = '', hasSubmit = false;
2537 for (var i = 0; i < form.elements.length; i++) {
2538 el = form.elements[i];
2539 disabled = form.elements[i].disabled;
2540 name = form.elements[i].name;
2541 val = form.elements[i].value;
2543 if (!disabled && name){
2547 case 'select-multiple':
2548 for (var j = 0; j < el.options.length; j++) {
2549 if (el.options[j].selected) {
2551 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2554 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2562 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2575 if(hasSubmit == false) {
2576 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2581 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2586 data = data.substr(0, data.length - 1);
2594 useDefaultHeader:true,
2596 defaultPostHeader:'application/x-www-form-urlencoded',
2598 useDefaultXhrHeader:true,
2600 defaultXhrHeader:'XMLHttpRequest',
2602 hasDefaultHeaders:true,
2614 setProgId:function(id)
2616 this.activeX.unshift(id);
2619 setDefaultPostHeader:function(b)
2621 this.useDefaultHeader = b;
2624 setDefaultXhrHeader:function(b)
2626 this.useDefaultXhrHeader = b;
2629 setPollingInterval:function(i)
2631 if (typeof i == 'number' && isFinite(i)) {
2632 this.pollInterval = i;
2636 createXhrObject:function(transactionId)
2642 http = new XMLHttpRequest();
2644 obj = { conn:http, tId:transactionId };
2648 for (var i = 0; i < this.activeX.length; ++i) {
2652 http = new ActiveXObject(this.activeX[i]);
2654 obj = { conn:http, tId:transactionId };
2667 getConnectionObject:function()
2670 var tId = this.transactionId;
2674 o = this.createXhrObject(tId);
2676 this.transactionId++;
2687 asyncRequest:function(method, uri, callback, postData)
2689 var o = this.getConnectionObject();
2695 o.conn.open(method, uri, true);
2697 if (this.useDefaultXhrHeader) {
2698 if (!this.defaultHeaders['X-Requested-With']) {
2699 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2703 if(postData && this.useDefaultHeader){
2704 this.initHeader('Content-Type', this.defaultPostHeader);
2707 if (this.hasDefaultHeaders || this.hasHeaders) {
2711 this.handleReadyState(o, callback);
2712 o.conn.send(postData || null);
2718 handleReadyState:function(o, callback)
2722 if (callback && callback.timeout) {
2724 this.timeout[o.tId] = window.setTimeout(function() {
2725 oConn.abort(o, callback, true);
2726 }, callback.timeout);
2729 this.poll[o.tId] = window.setInterval(
2731 if (o.conn && o.conn.readyState == 4) {
2732 window.clearInterval(oConn.poll[o.tId]);
2733 delete oConn.poll[o.tId];
2735 if(callback && callback.timeout) {
2736 window.clearTimeout(oConn.timeout[o.tId]);
2737 delete oConn.timeout[o.tId];
2740 oConn.handleTransactionResponse(o, callback);
2743 , this.pollInterval);
2746 handleTransactionResponse:function(o, callback, isAbort)
2750 this.releaseObject(o);
2754 var httpStatus, responseObject;
2758 if (o.conn.status !== undefined && o.conn.status != 0) {
2759 httpStatus = o.conn.status;
2771 if (httpStatus >= 200 && httpStatus < 300) {
2772 responseObject = this.createResponseObject(o, callback.argument);
2773 if (callback.success) {
2774 if (!callback.scope) {
2775 callback.success(responseObject);
2780 callback.success.apply(callback.scope, [responseObject]);
2785 switch (httpStatus) {
2793 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2794 if (callback.failure) {
2795 if (!callback.scope) {
2796 callback.failure(responseObject);
2799 callback.failure.apply(callback.scope, [responseObject]);
2804 responseObject = this.createResponseObject(o, callback.argument);
2805 if (callback.failure) {
2806 if (!callback.scope) {
2807 callback.failure(responseObject);
2810 callback.failure.apply(callback.scope, [responseObject]);
2816 this.releaseObject(o);
2817 responseObject = null;
2820 createResponseObject:function(o, callbackArg)
2827 var headerStr = o.conn.getAllResponseHeaders();
2828 var header = headerStr.split('\n');
2829 for (var i = 0; i < header.length; i++) {
2830 var delimitPos = header[i].indexOf(':');
2831 if (delimitPos != -1) {
2832 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2840 obj.status = o.conn.status;
2841 obj.statusText = o.conn.statusText;
2842 obj.getResponseHeader = headerObj;
2843 obj.getAllResponseHeaders = headerStr;
2844 obj.responseText = o.conn.responseText;
2845 obj.responseXML = o.conn.responseXML;
2847 if (typeof callbackArg !== undefined) {
2848 obj.argument = callbackArg;
2854 createExceptionObject:function(tId, callbackArg, isAbort)
2857 var COMM_ERROR = 'communication failure';
2858 var ABORT_CODE = -1;
2859 var ABORT_ERROR = 'transaction aborted';
2865 obj.status = ABORT_CODE;
2866 obj.statusText = ABORT_ERROR;
2869 obj.status = COMM_CODE;
2870 obj.statusText = COMM_ERROR;
2874 obj.argument = callbackArg;
2880 initHeader:function(label, value, isDefault)
2882 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2884 if (headerObj[label] === undefined) {
2885 headerObj[label] = value;
2890 headerObj[label] = value + "," + headerObj[label];
2894 this.hasDefaultHeaders = true;
2897 this.hasHeaders = true;
2902 setHeader:function(o)
2904 if (this.hasDefaultHeaders) {
2905 for (var prop in this.defaultHeaders) {
2906 if (this.defaultHeaders.hasOwnProperty(prop)) {
2907 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2912 if (this.hasHeaders) {
2913 for (var prop in this.headers) {
2914 if (this.headers.hasOwnProperty(prop)) {
2915 o.conn.setRequestHeader(prop, this.headers[prop]);
2919 this.hasHeaders = false;
2923 resetDefaultHeaders:function() {
2924 delete this.defaultHeaders;
2925 this.defaultHeaders = {};
2926 this.hasDefaultHeaders = false;
2929 abort:function(o, callback, isTimeout)
2931 if(this.isCallInProgress(o)) {
2933 window.clearInterval(this.poll[o.tId]);
2934 delete this.poll[o.tId];
2936 delete this.timeout[o.tId];
2939 this.handleTransactionResponse(o, callback, true);
2949 isCallInProgress:function(o)
2952 return o.conn.readyState != 4 && o.conn.readyState != 0;
2961 releaseObject:function(o)
2970 'MSXML2.XMLHTTP.3.0',
2978 * Portions of this file are based on pieces of Yahoo User Interface Library
2979 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2980 * YUI licensed under the BSD License:
2981 * http://developer.yahoo.net/yui/license.txt
2982 * <script type="text/javascript">
2986 Roo.lib.Region = function(t, r, b, l) {
2996 Roo.lib.Region.prototype = {
2997 contains : function(region) {
2998 return ( region.left >= this.left &&
2999 region.right <= this.right &&
3000 region.top >= this.top &&
3001 region.bottom <= this.bottom );
3005 getArea : function() {
3006 return ( (this.bottom - this.top) * (this.right - this.left) );
3009 intersect : function(region) {
3010 var t = Math.max(this.top, region.top);
3011 var r = Math.min(this.right, region.right);
3012 var b = Math.min(this.bottom, region.bottom);
3013 var l = Math.max(this.left, region.left);
3015 if (b >= t && r >= l) {
3016 return new Roo.lib.Region(t, r, b, l);
3021 union : function(region) {
3022 var t = Math.min(this.top, region.top);
3023 var r = Math.max(this.right, region.right);
3024 var b = Math.max(this.bottom, region.bottom);
3025 var l = Math.min(this.left, region.left);
3027 return new Roo.lib.Region(t, r, b, l);
3030 adjust : function(t, l, b, r) {
3039 Roo.lib.Region.getRegion = function(el) {
3040 var p = Roo.lib.Dom.getXY(el);
3043 var r = p[0] + el.offsetWidth;
3044 var b = p[1] + el.offsetHeight;
3047 return new Roo.lib.Region(t, r, b, l);
3050 * Portions of this file are based on pieces of Yahoo User Interface Library
3051 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3052 * YUI licensed under the BSD License:
3053 * http://developer.yahoo.net/yui/license.txt
3054 * <script type="text/javascript">
3057 //@@dep Roo.lib.Region
3060 Roo.lib.Point = function(x, y) {
3061 if (x instanceof Array) {
3065 this.x = this.right = this.left = this[0] = x;
3066 this.y = this.top = this.bottom = this[1] = y;
3069 Roo.lib.Point.prototype = new Roo.lib.Region();
3071 * Portions of this file are based on pieces of Yahoo User Interface Library
3072 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3073 * YUI licensed under the BSD License:
3074 * http://developer.yahoo.net/yui/license.txt
3075 * <script type="text/javascript">
3082 scroll : function(el, args, duration, easing, cb, scope) {
3083 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3086 motion : function(el, args, duration, easing, cb, scope) {
3087 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3090 color : function(el, args, duration, easing, cb, scope) {
3091 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3094 run : function(el, args, duration, easing, cb, scope, type) {
3095 type = type || Roo.lib.AnimBase;
3096 if (typeof easing == "string") {
3097 easing = Roo.lib.Easing[easing];
3099 var anim = new type(el, args, duration, easing);
3100 anim.animateX(function() {
3101 Roo.callback(cb, scope);
3107 * Portions of this file are based on pieces of Yahoo User Interface Library
3108 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3109 * YUI licensed under the BSD License:
3110 * http://developer.yahoo.net/yui/license.txt
3111 * <script type="text/javascript">
3119 if (!libFlyweight) {
3120 libFlyweight = new Roo.Element.Flyweight();
3122 libFlyweight.dom = el;
3123 return libFlyweight;
3126 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3130 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3132 this.init(el, attributes, duration, method);
3136 Roo.lib.AnimBase.fly = fly;
3140 Roo.lib.AnimBase.prototype = {
3142 toString: function() {
3143 var el = this.getEl();
3144 var id = el.id || el.tagName;
3145 return ("Anim " + id);
3149 noNegatives: /width|height|opacity|padding/i,
3150 offsetAttribute: /^((width|height)|(top|left))$/,
3151 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3152 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3156 doMethod: function(attr, start, end) {
3157 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3161 setAttribute: function(attr, val, unit) {
3162 if (this.patterns.noNegatives.test(attr)) {
3163 val = (val > 0) ? val : 0;
3166 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3170 getAttribute: function(attr) {
3171 var el = this.getEl();
3172 var val = fly(el).getStyle(attr);
3174 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3175 return parseFloat(val);
3178 var a = this.patterns.offsetAttribute.exec(attr) || [];
3179 var pos = !!( a[3] );
3180 var box = !!( a[2] );
3183 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3184 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3193 getDefaultUnit: function(attr) {
3194 if (this.patterns.defaultUnit.test(attr)) {
3201 animateX : function(callback, scope) {
3202 var f = function() {
3203 this.onComplete.removeListener(f);
3204 if (typeof callback == "function") {
3205 callback.call(scope || this, this);
3208 this.onComplete.addListener(f, this);
3213 setRuntimeAttribute: function(attr) {
3216 var attributes = this.attributes;
3218 this.runtimeAttributes[attr] = {};
3220 var isset = function(prop) {
3221 return (typeof prop !== 'undefined');
3224 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3228 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3231 if (isset(attributes[attr]['to'])) {
3232 end = attributes[attr]['to'];
3233 } else if (isset(attributes[attr]['by'])) {
3234 if (start.constructor == Array) {
3236 for (var i = 0, len = start.length; i < len; ++i) {
3237 end[i] = start[i] + attributes[attr]['by'][i];
3240 end = start + attributes[attr]['by'];
3244 this.runtimeAttributes[attr].start = start;
3245 this.runtimeAttributes[attr].end = end;
3248 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3252 init: function(el, attributes, duration, method) {
3254 var isAnimated = false;
3257 var startTime = null;
3260 var actualFrames = 0;
3263 el = Roo.getDom(el);
3266 this.attributes = attributes || {};
3269 this.duration = duration || 1;
3272 this.method = method || Roo.lib.Easing.easeNone;
3275 this.useSeconds = true;
3278 this.currentFrame = 0;
3281 this.totalFrames = Roo.lib.AnimMgr.fps;
3284 this.getEl = function() {
3289 this.isAnimated = function() {
3294 this.getStartTime = function() {
3298 this.runtimeAttributes = {};
3301 this.animate = function() {
3302 if (this.isAnimated()) {
3306 this.currentFrame = 0;
3308 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3310 Roo.lib.AnimMgr.registerElement(this);
3314 this.stop = function(finish) {
3316 this.currentFrame = this.totalFrames;
3317 this._onTween.fire();
3319 Roo.lib.AnimMgr.stop(this);
3322 var onStart = function() {
3323 this.onStart.fire();
3325 this.runtimeAttributes = {};
3326 for (var attr in this.attributes) {
3327 this.setRuntimeAttribute(attr);
3332 startTime = new Date();
3336 var onTween = function() {
3338 duration: new Date() - this.getStartTime(),
3339 currentFrame: this.currentFrame
3342 data.toString = function() {
3344 'duration: ' + data.duration +
3345 ', currentFrame: ' + data.currentFrame
3349 this.onTween.fire(data);
3351 var runtimeAttributes = this.runtimeAttributes;
3353 for (var attr in runtimeAttributes) {
3354 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3360 var onComplete = function() {
3361 var actual_duration = (new Date() - startTime) / 1000 ;
3364 duration: actual_duration,
3365 frames: actualFrames,
3366 fps: actualFrames / actual_duration
3369 data.toString = function() {
3371 'duration: ' + data.duration +
3372 ', frames: ' + data.frames +
3373 ', fps: ' + data.fps
3379 this.onComplete.fire(data);
3383 this._onStart = new Roo.util.Event(this);
3384 this.onStart = new Roo.util.Event(this);
3385 this.onTween = new Roo.util.Event(this);
3386 this._onTween = new Roo.util.Event(this);
3387 this.onComplete = new Roo.util.Event(this);
3388 this._onComplete = new Roo.util.Event(this);
3389 this._onStart.addListener(onStart);
3390 this._onTween.addListener(onTween);
3391 this._onComplete.addListener(onComplete);
3396 * Portions of this file are based on pieces of Yahoo User Interface Library
3397 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3398 * YUI licensed under the BSD License:
3399 * http://developer.yahoo.net/yui/license.txt
3400 * <script type="text/javascript">
3404 Roo.lib.AnimMgr = new function() {
3421 this.registerElement = function(tween) {
3422 queue[queue.length] = tween;
3424 tween._onStart.fire();
3429 this.unRegister = function(tween, index) {
3430 tween._onComplete.fire();
3431 index = index || getIndex(tween);
3433 queue.splice(index, 1);
3437 if (tweenCount <= 0) {
3443 this.start = function() {
3444 if (thread === null) {
3445 thread = setInterval(this.run, this.delay);
3450 this.stop = function(tween) {
3452 clearInterval(thread);
3454 for (var i = 0, len = queue.length; i < len; ++i) {
3455 if (queue[0].isAnimated()) {
3456 this.unRegister(queue[0], 0);
3465 this.unRegister(tween);
3470 this.run = function() {
3471 for (var i = 0, len = queue.length; i < len; ++i) {
3472 var tween = queue[i];
3473 if (!tween || !tween.isAnimated()) {
3477 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3479 tween.currentFrame += 1;
3481 if (tween.useSeconds) {
3482 correctFrame(tween);
3484 tween._onTween.fire();
3487 Roo.lib.AnimMgr.stop(tween, i);
3492 var getIndex = function(anim) {
3493 for (var i = 0, len = queue.length; i < len; ++i) {
3494 if (queue[i] == anim) {
3502 var correctFrame = function(tween) {
3503 var frames = tween.totalFrames;
3504 var frame = tween.currentFrame;
3505 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3506 var elapsed = (new Date() - tween.getStartTime());
3509 if (elapsed < tween.duration * 1000) {
3510 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3512 tweak = frames - (frame + 1);
3514 if (tweak > 0 && isFinite(tweak)) {
3515 if (tween.currentFrame + tweak >= frames) {
3516 tweak = frames - (frame + 1);
3519 tween.currentFrame += tweak;
3525 * Portions of this file are based on pieces of Yahoo User Interface Library
3526 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3527 * YUI licensed under the BSD License:
3528 * http://developer.yahoo.net/yui/license.txt
3529 * <script type="text/javascript">
3532 Roo.lib.Bezier = new function() {
3534 this.getPosition = function(points, t) {
3535 var n = points.length;
3538 for (var i = 0; i < n; ++i) {
3539 tmp[i] = [points[i][0], points[i][1]];
3542 for (var j = 1; j < n; ++j) {
3543 for (i = 0; i < n - j; ++i) {
3544 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3545 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3549 return [ tmp[0][0], tmp[0][1] ];
3553 * Portions of this file are based on pieces of Yahoo User Interface Library
3554 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3555 * YUI licensed under the BSD License:
3556 * http://developer.yahoo.net/yui/license.txt
3557 * <script type="text/javascript">
3562 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3563 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3566 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3568 var fly = Roo.lib.AnimBase.fly;
3570 var superclass = Y.ColorAnim.superclass;
3571 var proto = Y.ColorAnim.prototype;
3573 proto.toString = function() {
3574 var el = this.getEl();
3575 var id = el.id || el.tagName;
3576 return ("ColorAnim " + id);
3579 proto.patterns.color = /color$/i;
3580 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3581 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3582 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3583 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3586 proto.parseColor = function(s) {
3587 if (s.length == 3) {
3591 var c = this.patterns.hex.exec(s);
3592 if (c && c.length == 4) {
3593 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3596 c = this.patterns.rgb.exec(s);
3597 if (c && c.length == 4) {
3598 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3601 c = this.patterns.hex3.exec(s);
3602 if (c && c.length == 4) {
3603 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3608 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3609 proto.getAttribute = function(attr) {
3610 var el = this.getEl();
3611 if (this.patterns.color.test(attr)) {
3612 var val = fly(el).getStyle(attr);
3614 if (this.patterns.transparent.test(val)) {
3615 var parent = el.parentNode;
3616 val = fly(parent).getStyle(attr);
3618 while (parent && this.patterns.transparent.test(val)) {
3619 parent = parent.parentNode;
3620 val = fly(parent).getStyle(attr);
3621 if (parent.tagName.toUpperCase() == 'HTML') {
3627 val = superclass.getAttribute.call(this, attr);
3632 proto.getAttribute = function(attr) {
3633 var el = this.getEl();
3634 if (this.patterns.color.test(attr)) {
3635 var val = fly(el).getStyle(attr);
3637 if (this.patterns.transparent.test(val)) {
3638 var parent = el.parentNode;
3639 val = fly(parent).getStyle(attr);
3641 while (parent && this.patterns.transparent.test(val)) {
3642 parent = parent.parentNode;
3643 val = fly(parent).getStyle(attr);
3644 if (parent.tagName.toUpperCase() == 'HTML') {
3650 val = superclass.getAttribute.call(this, attr);
3656 proto.doMethod = function(attr, start, end) {
3659 if (this.patterns.color.test(attr)) {
3661 for (var i = 0, len = start.length; i < len; ++i) {
3662 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3665 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3668 val = superclass.doMethod.call(this, attr, start, end);
3674 proto.setRuntimeAttribute = function(attr) {
3675 superclass.setRuntimeAttribute.call(this, attr);
3677 if (this.patterns.color.test(attr)) {
3678 var attributes = this.attributes;
3679 var start = this.parseColor(this.runtimeAttributes[attr].start);
3680 var end = this.parseColor(this.runtimeAttributes[attr].end);
3682 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3683 end = this.parseColor(attributes[attr].by);
3685 for (var i = 0, len = start.length; i < len; ++i) {
3686 end[i] = start[i] + end[i];
3690 this.runtimeAttributes[attr].start = start;
3691 this.runtimeAttributes[attr].end = end;
3697 * Portions of this file are based on pieces of Yahoo User Interface Library
3698 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3699 * YUI licensed under the BSD License:
3700 * http://developer.yahoo.net/yui/license.txt
3701 * <script type="text/javascript">
3707 easeNone: function (t, b, c, d) {
3708 return c * t / d + b;
3712 easeIn: function (t, b, c, d) {
3713 return c * (t /= d) * t + b;
3717 easeOut: function (t, b, c, d) {
3718 return -c * (t /= d) * (t - 2) + b;
3722 easeBoth: function (t, b, c, d) {
3723 if ((t /= d / 2) < 1) {
3724 return c / 2 * t * t + b;
3727 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3731 easeInStrong: function (t, b, c, d) {
3732 return c * (t /= d) * t * t * t + b;
3736 easeOutStrong: function (t, b, c, d) {
3737 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3741 easeBothStrong: function (t, b, c, d) {
3742 if ((t /= d / 2) < 1) {
3743 return c / 2 * t * t * t * t + b;
3746 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3751 elasticIn: function (t, b, c, d, a, p) {
3755 if ((t /= d) == 1) {
3762 if (!a || a < Math.abs(c)) {
3767 var s = p / (2 * Math.PI) * Math.asin(c / a);
3770 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3774 elasticOut: function (t, b, c, d, a, p) {
3778 if ((t /= d) == 1) {
3785 if (!a || a < Math.abs(c)) {
3790 var s = p / (2 * Math.PI) * Math.asin(c / a);
3793 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3797 elasticBoth: function (t, b, c, d, a, p) {
3802 if ((t /= d / 2) == 2) {
3810 if (!a || a < Math.abs(c)) {
3815 var s = p / (2 * Math.PI) * Math.asin(c / a);
3819 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3820 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3822 return a * Math.pow(2, -10 * (t -= 1)) *
3823 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3828 backIn: function (t, b, c, d, s) {
3829 if (typeof s == 'undefined') {
3832 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3836 backOut: function (t, b, c, d, s) {
3837 if (typeof s == 'undefined') {
3840 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3844 backBoth: function (t, b, c, d, s) {
3845 if (typeof s == 'undefined') {
3849 if ((t /= d / 2 ) < 1) {
3850 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3852 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3856 bounceIn: function (t, b, c, d) {
3857 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3861 bounceOut: function (t, b, c, d) {
3862 if ((t /= d) < (1 / 2.75)) {
3863 return c * (7.5625 * t * t) + b;
3864 } else if (t < (2 / 2.75)) {
3865 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3866 } else if (t < (2.5 / 2.75)) {
3867 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3869 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3873 bounceBoth: function (t, b, c, d) {
3875 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3877 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3880 * Portions of this file are based on pieces of Yahoo User Interface Library
3881 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3882 * YUI licensed under the BSD License:
3883 * http://developer.yahoo.net/yui/license.txt
3884 * <script type="text/javascript">
3888 Roo.lib.Motion = function(el, attributes, duration, method) {
3890 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3894 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3898 var superclass = Y.Motion.superclass;
3899 var proto = Y.Motion.prototype;
3901 proto.toString = function() {
3902 var el = this.getEl();
3903 var id = el.id || el.tagName;
3904 return ("Motion " + id);
3907 proto.patterns.points = /^points$/i;
3909 proto.setAttribute = function(attr, val, unit) {
3910 if (this.patterns.points.test(attr)) {
3911 unit = unit || 'px';
3912 superclass.setAttribute.call(this, 'left', val[0], unit);
3913 superclass.setAttribute.call(this, 'top', val[1], unit);
3915 superclass.setAttribute.call(this, attr, val, unit);
3919 proto.getAttribute = function(attr) {
3920 if (this.patterns.points.test(attr)) {
3922 superclass.getAttribute.call(this, 'left'),
3923 superclass.getAttribute.call(this, 'top')
3926 val = superclass.getAttribute.call(this, attr);
3932 proto.doMethod = function(attr, start, end) {
3935 if (this.patterns.points.test(attr)) {
3936 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3937 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3939 val = superclass.doMethod.call(this, attr, start, end);
3944 proto.setRuntimeAttribute = function(attr) {
3945 if (this.patterns.points.test(attr)) {
3946 var el = this.getEl();
3947 var attributes = this.attributes;
3949 var control = attributes['points']['control'] || [];
3953 if (control.length > 0 && !(control[0] instanceof Array)) {
3954 control = [control];
3957 for (i = 0,len = control.length; i < len; ++i) {
3958 tmp[i] = control[i];
3963 Roo.fly(el).position();
3965 if (isset(attributes['points']['from'])) {
3966 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3969 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3972 start = this.getAttribute('points');
3975 if (isset(attributes['points']['to'])) {
3976 end = translateValues.call(this, attributes['points']['to'], start);
3978 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3979 for (i = 0,len = control.length; i < len; ++i) {
3980 control[i] = translateValues.call(this, control[i], start);
3984 } else if (isset(attributes['points']['by'])) {
3985 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3987 for (i = 0,len = control.length; i < len; ++i) {
3988 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3992 this.runtimeAttributes[attr] = [start];
3994 if (control.length > 0) {
3995 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3998 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4001 superclass.setRuntimeAttribute.call(this, attr);
4005 var translateValues = function(val, start) {
4006 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4007 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4012 var isset = function(prop) {
4013 return (typeof prop !== 'undefined');
4017 * Portions of this file are based on pieces of Yahoo User Interface Library
4018 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4019 * YUI licensed under the BSD License:
4020 * http://developer.yahoo.net/yui/license.txt
4021 * <script type="text/javascript">
4025 Roo.lib.Scroll = function(el, attributes, duration, method) {
4027 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4031 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4035 var superclass = Y.Scroll.superclass;
4036 var proto = Y.Scroll.prototype;
4038 proto.toString = function() {
4039 var el = this.getEl();
4040 var id = el.id || el.tagName;
4041 return ("Scroll " + id);
4044 proto.doMethod = function(attr, start, end) {
4047 if (attr == 'scroll') {
4049 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4050 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4054 val = superclass.doMethod.call(this, attr, start, end);
4059 proto.getAttribute = function(attr) {
4061 var el = this.getEl();
4063 if (attr == 'scroll') {
4064 val = [ el.scrollLeft, el.scrollTop ];
4066 val = superclass.getAttribute.call(this, attr);
4072 proto.setAttribute = function(attr, val, unit) {
4073 var el = this.getEl();
4075 if (attr == 'scroll') {
4076 el.scrollLeft = val[0];
4077 el.scrollTop = val[1];
4079 superclass.setAttribute.call(this, attr, val, unit);
4085 * Ext JS Library 1.1.1
4086 * Copyright(c) 2006-2007, Ext JS, LLC.
4088 * Originally Released Under LGPL - original licence link has changed is not relivant.
4091 * <script type="text/javascript">
4095 // nasty IE9 hack - what a pile of crap that is..
4097 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4098 Range.prototype.createContextualFragment = function (html) {
4099 var doc = window.document;
4100 var container = doc.createElement("div");
4101 container.innerHTML = html;
4102 var frag = doc.createDocumentFragment(), n;
4103 while ((n = container.firstChild)) {
4104 frag.appendChild(n);
4111 * @class Roo.DomHelper
4112 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4113 * For more information see <a href="http://web.archive.org/web/20071221063734/http://www.jackslocum.com/blog/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
4116 Roo.DomHelper = function(){
4117 var tempTableEl = null;
4118 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4119 var tableRe = /^table|tbody|tr|td$/i;
4121 // build as innerHTML where available
4123 var createHtml = function(o){
4124 if(typeof o == 'string'){
4133 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4134 if(attr == "style"){
4136 if(typeof s == "function"){
4139 if(typeof s == "string"){
4140 b += ' style="' + s + '"';
4141 }else if(typeof s == "object"){
4144 if(typeof s[key] != "function"){
4145 b += key + ":" + s[key] + ";";
4152 b += ' class="' + o["cls"] + '"';
4153 }else if(attr == "htmlFor"){
4154 b += ' for="' + o["htmlFor"] + '"';
4156 b += " " + attr + '="' + o[attr] + '"';
4160 if(emptyTags.test(o.tag)){
4164 var cn = o.children || o.cn;
4166 //http://bugs.kde.org/show_bug.cgi?id=71506
4167 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4168 for(var i = 0, len = cn.length; i < len; i++) {
4169 b += createHtml(cn[i], b);
4172 b += createHtml(cn, b);
4178 b += "</" + o.tag + ">";
4185 var createDom = function(o, parentNode){
4187 // defininition craeted..
4189 if (o.ns && o.ns != 'html') {
4191 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4192 xmlns[o.ns] = o.xmlns;
4195 if (typeof(xmlns[o.ns]) == 'undefined') {
4196 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4202 if (typeof(o) == 'string') {
4203 return parentNode.appendChild(document.createTextNode(o));
4205 o.tag = o.tag || div;
4206 if (o.ns && Roo.isIE) {
4208 o.tag = o.ns + ':' + o.tag;
4211 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4212 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4215 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4216 attr == "style" || typeof o[attr] == "function") continue;
4218 if(attr=="cls" && Roo.isIE){
4219 el.className = o["cls"];
4221 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4222 else el[attr] = o[attr];
4225 Roo.DomHelper.applyStyles(el, o.style);
4226 var cn = o.children || o.cn;
4228 //http://bugs.kde.org/show_bug.cgi?id=71506
4229 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4230 for(var i = 0, len = cn.length; i < len; i++) {
4231 createDom(cn[i], el);
4238 el.innerHTML = o.html;
4241 parentNode.appendChild(el);
4246 var ieTable = function(depth, s, h, e){
4247 tempTableEl.innerHTML = [s, h, e].join('');
4248 var i = -1, el = tempTableEl;
4255 // kill repeat to save bytes
4259 tbe = '</tbody>'+te,
4265 * Nasty code for IE's broken table implementation
4267 var insertIntoTable = function(tag, where, el, html){
4269 tempTableEl = document.createElement('div');
4274 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4277 if(where == 'beforebegin'){
4281 before = el.nextSibling;
4284 node = ieTable(4, trs, html, tre);
4286 else if(tag == 'tr'){
4287 if(where == 'beforebegin'){
4290 node = ieTable(3, tbs, html, tbe);
4291 } else if(where == 'afterend'){
4292 before = el.nextSibling;
4294 node = ieTable(3, tbs, html, tbe);
4295 } else{ // INTO a TR
4296 if(where == 'afterbegin'){
4297 before = el.firstChild;
4299 node = ieTable(4, trs, html, tre);
4301 } else if(tag == 'tbody'){
4302 if(where == 'beforebegin'){
4305 node = ieTable(2, ts, html, te);
4306 } else if(where == 'afterend'){
4307 before = el.nextSibling;
4309 node = ieTable(2, ts, html, te);
4311 if(where == 'afterbegin'){
4312 before = el.firstChild;
4314 node = ieTable(3, tbs, html, tbe);
4317 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4320 if(where == 'afterbegin'){
4321 before = el.firstChild;
4323 node = ieTable(2, ts, html, te);
4325 el.insertBefore(node, before);
4330 /** True to force the use of DOM instead of html fragments @type Boolean */
4334 * Returns the markup for the passed Element(s) config
4335 * @param {Object} o The Dom object spec (and children)
4338 markup : function(o){
4339 return createHtml(o);
4343 * Applies a style specification to an element
4344 * @param {String/HTMLElement} el The element to apply styles to
4345 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4346 * a function which returns such a specification.
4348 applyStyles : function(el, styles){
4351 if(typeof styles == "string"){
4352 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4354 while ((matches = re.exec(styles)) != null){
4355 el.setStyle(matches[1], matches[2]);
4357 }else if (typeof styles == "object"){
4358 for (var style in styles){
4359 el.setStyle(style, styles[style]);
4361 }else if (typeof styles == "function"){
4362 Roo.DomHelper.applyStyles(el, styles.call());
4368 * Inserts an HTML fragment into the Dom
4369 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4370 * @param {HTMLElement} el The context element
4371 * @param {String} html The HTML fragmenet
4372 * @return {HTMLElement} The new node
4374 insertHtml : function(where, el, html){
4375 where = where.toLowerCase();
4376 if(el.insertAdjacentHTML){
4377 if(tableRe.test(el.tagName)){
4379 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4385 el.insertAdjacentHTML('BeforeBegin', html);
4386 return el.previousSibling;
4388 el.insertAdjacentHTML('AfterBegin', html);
4389 return el.firstChild;
4391 el.insertAdjacentHTML('BeforeEnd', html);
4392 return el.lastChild;
4394 el.insertAdjacentHTML('AfterEnd', html);
4395 return el.nextSibling;
4397 throw 'Illegal insertion point -> "' + where + '"';
4399 var range = el.ownerDocument.createRange();
4403 range.setStartBefore(el);
4404 frag = range.createContextualFragment(html);
4405 el.parentNode.insertBefore(frag, el);
4406 return el.previousSibling;
4409 range.setStartBefore(el.firstChild);
4410 frag = range.createContextualFragment(html);
4411 el.insertBefore(frag, el.firstChild);
4412 return el.firstChild;
4414 el.innerHTML = html;
4415 return el.firstChild;
4419 range.setStartAfter(el.lastChild);
4420 frag = range.createContextualFragment(html);
4421 el.appendChild(frag);
4422 return el.lastChild;
4424 el.innerHTML = html;
4425 return el.lastChild;
4428 range.setStartAfter(el);
4429 frag = range.createContextualFragment(html);
4430 el.parentNode.insertBefore(frag, el.nextSibling);
4431 return el.nextSibling;
4433 throw 'Illegal insertion point -> "' + where + '"';
4437 * Creates new Dom element(s) and inserts them before el
4438 * @param {String/HTMLElement/Element} el The context element
4439 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4440 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4441 * @return {HTMLElement/Roo.Element} The new node
4443 insertBefore : function(el, o, returnElement){
4444 return this.doInsert(el, o, returnElement, "beforeBegin");
4448 * Creates new Dom element(s) and inserts them after el
4449 * @param {String/HTMLElement/Element} el The context element
4450 * @param {Object} o The Dom object spec (and children)
4451 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4452 * @return {HTMLElement/Roo.Element} The new node
4454 insertAfter : function(el, o, returnElement){
4455 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4459 * Creates new Dom element(s) and inserts them as the first child of el
4460 * @param {String/HTMLElement/Element} el The context element
4461 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4462 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4463 * @return {HTMLElement/Roo.Element} The new node
4465 insertFirst : function(el, o, returnElement){
4466 return this.doInsert(el, o, returnElement, "afterBegin");
4470 doInsert : function(el, o, returnElement, pos, sibling){
4471 el = Roo.getDom(el);
4473 if(this.useDom || o.ns){
4474 newNode = createDom(o, null);
4475 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4477 var html = createHtml(o);
4478 newNode = this.insertHtml(pos, el, html);
4480 return returnElement ? Roo.get(newNode, true) : newNode;
4484 * Creates new Dom element(s) and appends them to el
4485 * @param {String/HTMLElement/Element} el The context element
4486 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4487 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4488 * @return {HTMLElement/Roo.Element} The new node
4490 append : function(el, o, returnElement){
4491 el = Roo.getDom(el);
4493 if(this.useDom || o.ns){
4494 newNode = createDom(o, null);
4495 el.appendChild(newNode);
4497 var html = createHtml(o);
4498 newNode = this.insertHtml("beforeEnd", el, html);
4500 return returnElement ? Roo.get(newNode, true) : newNode;
4504 * Creates new Dom element(s) and overwrites the contents of el with them
4505 * @param {String/HTMLElement/Element} el The context element
4506 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4507 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4508 * @return {HTMLElement/Roo.Element} The new node
4510 overwrite : function(el, o, returnElement){
4511 el = Roo.getDom(el);
4514 while (el.childNodes.length) {
4515 el.removeChild(el.firstChild);
4519 el.innerHTML = createHtml(o);
4522 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4526 * Creates a new Roo.DomHelper.Template from the Dom object spec
4527 * @param {Object} o The Dom object spec (and children)
4528 * @return {Roo.DomHelper.Template} The new template
4530 createTemplate : function(o){
4531 var html = createHtml(o);
4532 return new Roo.Template(html);
4538 * Ext JS Library 1.1.1
4539 * Copyright(c) 2006-2007, Ext JS, LLC.
4541 * Originally Released Under LGPL - original licence link has changed is not relivant.
4544 * <script type="text/javascript">
4548 * @class Roo.Template
4549 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4550 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4553 var t = new Roo.Template({
4554 html : '<div name="{id}">' +
4555 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4557 myformat: function (value, allValues) {
4558 return 'XX' + value;
4561 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4563 * For more information see this blog post with examples:
4564 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4565 - Create Elements using DOM, HTML fragments and Templates</a>.
4567 * @param {Object} cfg - Configuration object.
4569 Roo.Template = function(cfg){
4571 if(cfg instanceof Array){
4573 }else if(arguments.length > 1){
4574 cfg = Array.prototype.join.call(arguments, "");
4578 if (typeof(cfg) == 'object') {
4589 Roo.Template.prototype = {
4592 * @cfg {String} url The Url to load the template from. beware if you are loading from a url, the data may not be ready if you use it instantly..
4593 * it should be fixed so that template is observable...
4597 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4601 * Returns an HTML fragment of this template with the specified values applied.
4602 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4603 * @return {String} The HTML fragment
4605 applyTemplate : function(values){
4609 return this.compiled(values);
4611 var useF = this.disableFormats !== true;
4612 var fm = Roo.util.Format, tpl = this;
4613 var fn = function(m, name, format, args){
4615 if(format.substr(0, 5) == "this."){
4616 return tpl.call(format.substr(5), values[name], values);
4619 // quoted values are required for strings in compiled templates,
4620 // but for non compiled we need to strip them
4621 // quoted reversed for jsmin
4622 var re = /^\s*['"](.*)["']\s*$/;
4623 args = args.split(',');
4624 for(var i = 0, len = args.length; i < len; i++){
4625 args[i] = args[i].replace(re, "$1");
4627 args = [values[name]].concat(args);
4629 args = [values[name]];
4631 return fm[format].apply(fm, args);
4634 return values[name] !== undefined ? values[name] : "";
4637 return this.html.replace(this.re, fn);
4655 this.loading = true;
4656 this.compiled = false;
4658 var cx = new Roo.data.Connection();
4662 success : function (response) {
4664 _t.html = response.responseText;
4668 failure : function(response) {
4669 Roo.log("Template failed to load from " + _t.url);
4676 * Sets the HTML used as the template and optionally compiles it.
4677 * @param {String} html
4678 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4679 * @return {Roo.Template} this
4681 set : function(html, compile){
4683 this.compiled = null;
4691 * True to disable format functions (defaults to false)
4694 disableFormats : false,
4697 * The regular expression used to match template variables
4701 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4704 * Compiles the template into an internal function, eliminating the RegEx overhead.
4705 * @return {Roo.Template} this
4707 compile : function(){
4708 var fm = Roo.util.Format;
4709 var useF = this.disableFormats !== true;
4710 var sep = Roo.isGecko ? "+" : ",";
4711 var fn = function(m, name, format, args){
4713 args = args ? ',' + args : "";
4714 if(format.substr(0, 5) != "this."){
4715 format = "fm." + format + '(';
4717 format = 'this.call("'+ format.substr(5) + '", ';
4721 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4723 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4726 // branched to use + in gecko and [].join() in others
4728 body = "this.compiled = function(values){ return '" +
4729 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4732 body = ["this.compiled = function(values){ return ['"];
4733 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4734 body.push("'].join('');};");
4735 body = body.join('');
4745 // private function used to call members
4746 call : function(fnName, value, allValues){
4747 return this[fnName](value, allValues);
4751 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4752 * @param {String/HTMLElement/Roo.Element} el The context element
4753 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4754 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4755 * @return {HTMLElement/Roo.Element} The new node or Element
4757 insertFirst: function(el, values, returnElement){
4758 return this.doInsert('afterBegin', el, values, returnElement);
4762 * Applies the supplied values to the template and inserts the new node(s) before el.
4763 * @param {String/HTMLElement/Roo.Element} el The context element
4764 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4765 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4766 * @return {HTMLElement/Roo.Element} The new node or Element
4768 insertBefore: function(el, values, returnElement){
4769 return this.doInsert('beforeBegin', el, values, returnElement);
4773 * Applies the supplied values to the template and inserts the new node(s) after el.
4774 * @param {String/HTMLElement/Roo.Element} el The context element
4775 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4776 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4777 * @return {HTMLElement/Roo.Element} The new node or Element
4779 insertAfter : function(el, values, returnElement){
4780 return this.doInsert('afterEnd', el, values, returnElement);
4784 * Applies the supplied values to the template and appends the new node(s) to el.
4785 * @param {String/HTMLElement/Roo.Element} el The context element
4786 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4787 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4788 * @return {HTMLElement/Roo.Element} The new node or Element
4790 append : function(el, values, returnElement){
4791 return this.doInsert('beforeEnd', el, values, returnElement);
4794 doInsert : function(where, el, values, returnEl){
4795 el = Roo.getDom(el);
4796 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4797 return returnEl ? Roo.get(newNode, true) : newNode;
4801 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4802 * @param {String/HTMLElement/Roo.Element} el The context element
4803 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4804 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4805 * @return {HTMLElement/Roo.Element} The new node or Element
4807 overwrite : function(el, values, returnElement){
4808 el = Roo.getDom(el);
4809 el.innerHTML = this.applyTemplate(values);
4810 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4814 * Alias for {@link #applyTemplate}
4817 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4820 Roo.DomHelper.Template = Roo.Template;
4823 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4824 * @param {String/HTMLElement} el A DOM element or its id
4825 * @returns {Roo.Template} The created template
4828 Roo.Template.from = function(el){
4829 el = Roo.getDom(el);
4830 return new Roo.Template(el.value || el.innerHTML);
4833 * Ext JS Library 1.1.1
4834 * Copyright(c) 2006-2007, Ext JS, LLC.
4836 * Originally Released Under LGPL - original licence link has changed is not relivant.
4839 * <script type="text/javascript">
4844 * This is code is also distributed under MIT license for use
4845 * with jQuery and prototype JavaScript libraries.
4848 * @class Roo.DomQuery
4849 Provides high performance selector/xpath processing by compiling queries into reusable functions. New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
4851 DomQuery supports most of the <a href="http://www.w3.org/TR/2005/WD-css3-selectors-20051215/">CSS3 selectors spec</a>, along with some custom selectors and basic XPath.</p>
4854 All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example "div.foo:nth-child(odd)[@foo=bar].bar:first" would be a perfectly valid selector. Node filters are processed in the order in which they appear, which allows you to optimize your queries for your document structure.
4856 <h4>Element Selectors:</h4>
4858 <li> <b>*</b> any element</li>
4859 <li> <b>E</b> an element with the tag E</li>
4860 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4861 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4862 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4863 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4865 <h4>Attribute Selectors:</h4>
4866 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4868 <li> <b>E[foo]</b> has an attribute "foo"</li>
4869 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4870 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4871 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4872 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4873 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4874 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4876 <h4>Pseudo Classes:</h4>
4878 <li> <b>E:first-child</b> E is the first child of its parent</li>
4879 <li> <b>E:last-child</b> E is the last child of its parent</li>
4880 <li> <b>E:nth-child(<i>n</i>)</b> E is the <i>n</i>th child of its parent (1 based as per the spec)</li>
4881 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4882 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4883 <li> <b>E:only-child</b> E is the only child of its parent</li>
4884 <li> <b>E:checked</b> E is an element that is has a checked attribute that is true (e.g. a radio or checkbox) </li>
4885 <li> <b>E:first</b> the first E in the resultset</li>
4886 <li> <b>E:last</b> the last E in the resultset</li>
4887 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4888 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4889 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4890 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4891 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4892 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4893 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4894 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4895 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4897 <h4>CSS Value Selectors:</h4>
4899 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4900 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4901 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4902 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4903 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4904 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4908 Roo.DomQuery = function(){
4909 var cache = {}, simpleCache = {}, valueCache = {};
4910 var nonSpace = /\S/;
4911 var trimRe = /^\s+|\s+$/g;
4912 var tplRe = /\{(\d+)\}/g;
4913 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4914 var tagTokenRe = /^(#)?([\w-\*]+)/;
4915 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4917 function child(p, index){
4919 var n = p.firstChild;
4921 if(n.nodeType == 1){
4932 while((n = n.nextSibling) && n.nodeType != 1);
4937 while((n = n.previousSibling) && n.nodeType != 1);
4941 function children(d){
4942 var n = d.firstChild, ni = -1;
4944 var nx = n.nextSibling;
4945 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4955 function byClassName(c, a, v){
4959 var r = [], ri = -1, cn;
4960 for(var i = 0, ci; ci = c[i]; i++){
4961 if((' '+ci.className+' ').indexOf(v) != -1){
4968 function attrValue(n, attr){
4969 if(!n.tagName && typeof n.length != "undefined"){
4978 if(attr == "class" || attr == "className"){
4981 return n.getAttribute(attr) || n[attr];
4985 function getNodes(ns, mode, tagName){
4986 var result = [], ri = -1, cs;
4990 tagName = tagName || "*";
4991 if(typeof ns.getElementsByTagName != "undefined"){
4995 for(var i = 0, ni; ni = ns[i]; i++){
4996 cs = ni.getElementsByTagName(tagName);
4997 for(var j = 0, ci; ci = cs[j]; j++){
5001 }else if(mode == "/" || mode == ">"){
5002 var utag = tagName.toUpperCase();
5003 for(var i = 0, ni, cn; ni = ns[i]; i++){
5004 cn = ni.children || ni.childNodes;
5005 for(var j = 0, cj; cj = cn[j]; j++){
5006 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5011 }else if(mode == "+"){
5012 var utag = tagName.toUpperCase();
5013 for(var i = 0, n; n = ns[i]; i++){
5014 while((n = n.nextSibling) && n.nodeType != 1);
5015 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5019 }else if(mode == "~"){
5020 for(var i = 0, n; n = ns[i]; i++){
5021 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5030 function concat(a, b){
5034 for(var i = 0, l = b.length; i < l; i++){
5040 function byTag(cs, tagName){
5041 if(cs.tagName || cs == document){
5047 var r = [], ri = -1;
5048 tagName = tagName.toLowerCase();
5049 for(var i = 0, ci; ci = cs[i]; i++){
5050 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5057 function byId(cs, attr, id){
5058 if(cs.tagName || cs == document){
5064 var r = [], ri = -1;
5065 for(var i = 0,ci; ci = cs[i]; i++){
5066 if(ci && ci.id == id){
5074 function byAttribute(cs, attr, value, op, custom){
5075 var r = [], ri = -1, st = custom=="{";
5076 var f = Roo.DomQuery.operators[op];
5077 for(var i = 0, ci; ci = cs[i]; i++){
5080 a = Roo.DomQuery.getStyle(ci, attr);
5082 else if(attr == "class" || attr == "className"){
5084 }else if(attr == "for"){
5086 }else if(attr == "href"){
5087 a = ci.getAttribute("href", 2);
5089 a = ci.getAttribute(attr);
5091 if((f && f(a, value)) || (!f && a)){
5098 function byPseudo(cs, name, value){
5099 return Roo.DomQuery.pseudos[name](cs, value);
5102 // This is for IE MSXML which does not support expandos.
5103 // IE runs the same speed using setAttribute, however FF slows way down
5104 // and Safari completely fails so they need to continue to use expandos.
5105 var isIE = window.ActiveXObject ? true : false;
5107 // this eval is stop the compressor from
5108 // renaming the variable to something shorter
5110 /** eval:var:batch */
5115 function nodupIEXml(cs){
5117 cs[0].setAttribute("_nodup", d);
5119 for(var i = 1, len = cs.length; i < len; i++){
5121 if(!c.getAttribute("_nodup") != d){
5122 c.setAttribute("_nodup", d);
5126 for(var i = 0, len = cs.length; i < len; i++){
5127 cs[i].removeAttribute("_nodup");
5136 var len = cs.length, c, i, r = cs, cj, ri = -1;
5137 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5140 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5141 return nodupIEXml(cs);
5145 for(i = 1; c = cs[i]; i++){
5150 for(var j = 0; j < i; j++){
5153 for(j = i+1; cj = cs[j]; j++){
5165 function quickDiffIEXml(c1, c2){
5167 for(var i = 0, len = c1.length; i < len; i++){
5168 c1[i].setAttribute("_qdiff", d);
5171 for(var i = 0, len = c2.length; i < len; i++){
5172 if(c2[i].getAttribute("_qdiff") != d){
5173 r[r.length] = c2[i];
5176 for(var i = 0, len = c1.length; i < len; i++){
5177 c1[i].removeAttribute("_qdiff");
5182 function quickDiff(c1, c2){
5183 var len1 = c1.length;
5187 if(isIE && c1[0].selectSingleNode){
5188 return quickDiffIEXml(c1, c2);
5191 for(var i = 0; i < len1; i++){
5195 for(var i = 0, len = c2.length; i < len; i++){
5196 if(c2[i]._qdiff != d){
5197 r[r.length] = c2[i];
5203 function quickId(ns, mode, root, id){
5205 var d = root.ownerDocument || root;
5206 return d.getElementById(id);
5208 ns = getNodes(ns, mode, "*");
5209 return byId(ns, null, id);
5213 getStyle : function(el, name){
5214 return Roo.fly(el).getStyle(name);
5217 * Compiles a selector/xpath query into a reusable function. The returned function
5218 * takes one parameter "root" (optional), which is the context node from where the query should start.
5219 * @param {String} selector The selector/xpath query
5220 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5221 * @return {Function}
5223 compile : function(path, type){
5224 type = type || "select";
5226 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5227 var q = path, mode, lq;
5228 var tk = Roo.DomQuery.matchers;
5229 var tklen = tk.length;
5232 // accept leading mode switch
5233 var lmode = q.match(modeRe);
5234 if(lmode && lmode[1]){
5235 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5236 q = q.replace(lmode[1], "");
5238 // strip leading slashes
5239 while(path.substr(0, 1)=="/"){
5240 path = path.substr(1);
5243 while(q && lq != q){
5245 var tm = q.match(tagTokenRe);
5246 if(type == "select"){
5249 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5251 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5253 q = q.replace(tm[0], "");
5254 }else if(q.substr(0, 1) != '@'){
5255 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5260 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5262 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5264 q = q.replace(tm[0], "");
5267 while(!(mm = q.match(modeRe))){
5268 var matched = false;
5269 for(var j = 0; j < tklen; j++){
5271 var m = q.match(t.re);
5273 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5276 q = q.replace(m[0], "");
5281 // prevent infinite loop on bad selector
5283 throw 'Error parsing selector, parsing failed at "' + q + '"';
5287 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5288 q = q.replace(mm[1], "");
5291 fn[fn.length] = "return nodup(n);\n}";
5294 * list of variables that need from compression as they are used by eval.
5304 * eval:var:byClassName
5306 * eval:var:byAttribute
5307 * eval:var:attrValue
5315 * Selects a group of elements.
5316 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5317 * @param {Node} root (optional) The start of the query (defaults to document).
5320 select : function(path, root, type){
5321 if(!root || root == document){
5324 if(typeof root == "string"){
5325 root = document.getElementById(root);
5327 var paths = path.split(",");
5329 for(var i = 0, len = paths.length; i < len; i++){
5330 var p = paths[i].replace(trimRe, "");
5332 cache[p] = Roo.DomQuery.compile(p);
5334 throw p + " is not a valid selector";
5337 var result = cache[p](root);
5338 if(result && result != document){
5339 results = results.concat(result);
5342 if(paths.length > 1){
5343 return nodup(results);
5349 * Selects a single element.
5350 * @param {String} selector The selector/xpath query
5351 * @param {Node} root (optional) The start of the query (defaults to document).
5354 selectNode : function(path, root){
5355 return Roo.DomQuery.select(path, root)[0];
5359 * Selects the value of a node, optionally replacing null with the defaultValue.
5360 * @param {String} selector The selector/xpath query
5361 * @param {Node} root (optional) The start of the query (defaults to document).
5362 * @param {String} defaultValue
5364 selectValue : function(path, root, defaultValue){
5365 path = path.replace(trimRe, "");
5366 if(!valueCache[path]){
5367 valueCache[path] = Roo.DomQuery.compile(path, "select");
5369 var n = valueCache[path](root);
5370 n = n[0] ? n[0] : n;
5371 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5372 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5376 * Selects the value of a node, parsing integers and floats.
5377 * @param {String} selector The selector/xpath query
5378 * @param {Node} root (optional) The start of the query (defaults to document).
5379 * @param {Number} defaultValue
5382 selectNumber : function(path, root, defaultValue){
5383 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5384 return parseFloat(v);
5388 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5389 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5390 * @param {String} selector The simple selector to test
5393 is : function(el, ss){
5394 if(typeof el == "string"){
5395 el = document.getElementById(el);
5397 var isArray = (el instanceof Array);
5398 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5399 return isArray ? (result.length == el.length) : (result.length > 0);
5403 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5404 * @param {Array} el An array of elements to filter
5405 * @param {String} selector The simple selector to test
5406 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5407 * the selector instead of the ones that match
5410 filter : function(els, ss, nonMatches){
5411 ss = ss.replace(trimRe, "");
5412 if(!simpleCache[ss]){
5413 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5415 var result = simpleCache[ss](els);
5416 return nonMatches ? quickDiff(result, els) : result;
5420 * Collection of matching regular expressions and code snippets.
5424 select: 'n = byClassName(n, null, " {1} ");'
5426 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5427 select: 'n = byPseudo(n, "{1}", "{2}");'
5429 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5430 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5433 select: 'n = byId(n, null, "{1}");'
5436 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5441 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5442 * New operators can be added as long as the match the format <i>c</i>= where <i>c</i> is any character other than space, > <.
5445 "=" : function(a, v){
5448 "!=" : function(a, v){
5451 "^=" : function(a, v){
5452 return a && a.substr(0, v.length) == v;
5454 "$=" : function(a, v){
5455 return a && a.substr(a.length-v.length) == v;
5457 "*=" : function(a, v){
5458 return a && a.indexOf(v) !== -1;
5460 "%=" : function(a, v){
5461 return (a % v) == 0;
5463 "|=" : function(a, v){
5464 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5466 "~=" : function(a, v){
5467 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5472 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5473 * and the argument (if any) supplied in the selector.
5476 "first-child" : function(c){
5477 var r = [], ri = -1, n;
5478 for(var i = 0, ci; ci = n = c[i]; i++){
5479 while((n = n.previousSibling) && n.nodeType != 1);
5487 "last-child" : function(c){
5488 var r = [], ri = -1, n;
5489 for(var i = 0, ci; ci = n = c[i]; i++){
5490 while((n = n.nextSibling) && n.nodeType != 1);
5498 "nth-child" : function(c, a) {
5499 var r = [], ri = -1;
5500 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5501 var f = (m[1] || 1) - 0, l = m[2] - 0;
5502 for(var i = 0, n; n = c[i]; i++){
5503 var pn = n.parentNode;
5504 if (batch != pn._batch) {
5506 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5507 if(cn.nodeType == 1){
5514 if (l == 0 || n.nodeIndex == l){
5517 } else if ((n.nodeIndex + l) % f == 0){
5525 "only-child" : function(c){
5526 var r = [], ri = -1;;
5527 for(var i = 0, ci; ci = c[i]; i++){
5528 if(!prev(ci) && !next(ci)){
5535 "empty" : function(c){
5536 var r = [], ri = -1;
5537 for(var i = 0, ci; ci = c[i]; i++){
5538 var cns = ci.childNodes, j = 0, cn, empty = true;
5541 if(cn.nodeType == 1 || cn.nodeType == 3){
5553 "contains" : function(c, v){
5554 var r = [], ri = -1;
5555 for(var i = 0, ci; ci = c[i]; i++){
5556 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5563 "nodeValue" : function(c, v){
5564 var r = [], ri = -1;
5565 for(var i = 0, ci; ci = c[i]; i++){
5566 if(ci.firstChild && ci.firstChild.nodeValue == v){
5573 "checked" : function(c){
5574 var r = [], ri = -1;
5575 for(var i = 0, ci; ci = c[i]; i++){
5576 if(ci.checked == true){
5583 "not" : function(c, ss){
5584 return Roo.DomQuery.filter(c, ss, true);
5587 "odd" : function(c){
5588 return this["nth-child"](c, "odd");
5591 "even" : function(c){
5592 return this["nth-child"](c, "even");
5595 "nth" : function(c, a){
5596 return c[a-1] || [];
5599 "first" : function(c){
5603 "last" : function(c){
5604 return c[c.length-1] || [];
5607 "has" : function(c, ss){
5608 var s = Roo.DomQuery.select;
5609 var r = [], ri = -1;
5610 for(var i = 0, ci; ci = c[i]; i++){
5611 if(s(ss, ci).length > 0){
5618 "next" : function(c, ss){
5619 var is = Roo.DomQuery.is;
5620 var r = [], ri = -1;
5621 for(var i = 0, ci; ci = c[i]; i++){
5630 "prev" : function(c, ss){
5631 var is = Roo.DomQuery.is;
5632 var r = [], ri = -1;
5633 for(var i = 0, ci; ci = c[i]; i++){
5646 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5647 * @param {String} path The selector/xpath query
5648 * @param {Node} root (optional) The start of the query (defaults to document).
5653 Roo.query = Roo.DomQuery.select;
5656 * Ext JS Library 1.1.1
5657 * Copyright(c) 2006-2007, Ext JS, LLC.
5659 * Originally Released Under LGPL - original licence link has changed is not relivant.
5662 * <script type="text/javascript">
5666 * @class Roo.util.Observable
5667 * Base class that provides a common interface for publishing events. Subclasses are expected to
5668 * to have a property "events" with all the events defined.<br>
5671 Employee = function(name){
5678 Roo.extend(Employee, Roo.util.Observable);
5680 * @param {Object} config properties to use (incuding events / listeners)
5683 Roo.util.Observable = function(cfg){
5686 this.addEvents(cfg.events || {});
5688 delete cfg.events; // make sure
5691 Roo.apply(this, cfg);
5694 this.on(this.listeners);
5695 delete this.listeners;
5698 Roo.util.Observable.prototype = {
5700 * @cfg {Object} listeners list of events and functions to call for this object,
5704 'click' : function(e) {
5714 * Fires the specified event with the passed parameters (minus the event name).
5715 * @param {String} eventName
5716 * @param {Object...} args Variable number of parameters are passed to handlers
5717 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5719 fireEvent : function(){
5720 var ce = this.events[arguments[0].toLowerCase()];
5721 if(typeof ce == "object"){
5722 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5729 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5732 * Appends an event handler to this component
5733 * @param {String} eventName The type of event to listen for
5734 * @param {Function} handler The method the event invokes
5735 * @param {Object} scope (optional) The scope in which to execute the handler
5736 * function. The handler function's "this" context.
5737 * @param {Object} options (optional) An object containing handler configuration
5738 * properties. This may contain any of the following properties:<ul>
5739 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5740 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5741 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5742 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5743 * by the specified number of milliseconds. If the event fires again within that time, the original
5744 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5747 * <b>Combining Options</b><br>
5748 * Using the options argument, it is possible to combine different types of listeners:<br>
5750 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5752 el.on('click', this.onClick, this, {
5759 * <b>Attaching multiple handlers in 1 call</b><br>
5760 * The method also allows for a single argument to be passed which is a config object containing properties
5761 * which specify multiple handlers.
5770 fn: this.onMouseOver,
5774 fn: this.onMouseOut,
5780 * Or a shorthand syntax which passes the same scope object to all handlers:
5783 'click': this.onClick,
5784 'mouseover': this.onMouseOver,
5785 'mouseout': this.onMouseOut,
5790 addListener : function(eventName, fn, scope, o){
5791 if(typeof eventName == "object"){
5794 if(this.filterOptRe.test(e)){
5797 if(typeof o[e] == "function"){
5799 this.addListener(e, o[e], o.scope, o);
5801 // individual options
5802 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5807 o = (!o || typeof o == "boolean") ? {} : o;
5808 eventName = eventName.toLowerCase();
5809 var ce = this.events[eventName] || true;
5810 if(typeof ce == "boolean"){
5811 ce = new Roo.util.Event(this, eventName);
5812 this.events[eventName] = ce;
5814 ce.addListener(fn, scope, o);
5818 * Removes a listener
5819 * @param {String} eventName The type of event to listen for
5820 * @param {Function} handler The handler to remove
5821 * @param {Object} scope (optional) The scope (this object) for the handler
5823 removeListener : function(eventName, fn, scope){
5824 var ce = this.events[eventName.toLowerCase()];
5825 if(typeof ce == "object"){
5826 ce.removeListener(fn, scope);
5831 * Removes all listeners for this object
5833 purgeListeners : function(){
5834 for(var evt in this.events){
5835 if(typeof this.events[evt] == "object"){
5836 this.events[evt].clearListeners();
5841 relayEvents : function(o, events){
5842 var createHandler = function(ename){
5844 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5847 for(var i = 0, len = events.length; i < len; i++){
5848 var ename = events[i];
5849 if(!this.events[ename]){ this.events[ename] = true; };
5850 o.on(ename, createHandler(ename), this);
5855 * Used to define events on this Observable
5856 * @param {Object} object The object with the events defined
5858 addEvents : function(o){
5862 Roo.applyIf(this.events, o);
5866 * Checks to see if this object has any listeners for a specified event
5867 * @param {String} eventName The name of the event to check for
5868 * @return {Boolean} True if the event is being listened for, else false
5870 hasListener : function(eventName){
5871 var e = this.events[eventName];
5872 return typeof e == "object" && e.listeners.length > 0;
5876 * Appends an event handler to this element (shorthand for addListener)
5877 * @param {String} eventName The type of event to listen for
5878 * @param {Function} handler The method the event invokes
5879 * @param {Object} scope (optional) The scope in which to execute the handler
5880 * function. The handler function's "this" context.
5881 * @param {Object} options (optional)
5884 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5886 * Removes a listener (shorthand for removeListener)
5887 * @param {String} eventName The type of event to listen for
5888 * @param {Function} handler The handler to remove
5889 * @param {Object} scope (optional) The scope (this object) for the handler
5892 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5895 * Starts capture on the specified Observable. All events will be passed
5896 * to the supplied function with the event name + standard signature of the event
5897 * <b>before</b> the event is fired. If the supplied function returns false,
5898 * the event will not fire.
5899 * @param {Observable} o The Observable to capture
5900 * @param {Function} fn The function to call
5901 * @param {Object} scope (optional) The scope (this object) for the fn
5904 Roo.util.Observable.capture = function(o, fn, scope){
5905 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5909 * Removes <b>all</b> added captures from the Observable.
5910 * @param {Observable} o The Observable to release
5913 Roo.util.Observable.releaseCapture = function(o){
5914 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5919 var createBuffered = function(h, o, scope){
5920 var task = new Roo.util.DelayedTask();
5922 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5926 var createSingle = function(h, e, fn, scope){
5928 e.removeListener(fn, scope);
5929 return h.apply(scope, arguments);
5933 var createDelayed = function(h, o, scope){
5935 var args = Array.prototype.slice.call(arguments, 0);
5936 setTimeout(function(){
5937 h.apply(scope, args);
5942 Roo.util.Event = function(obj, name){
5945 this.listeners = [];
5948 Roo.util.Event.prototype = {
5949 addListener : function(fn, scope, options){
5950 var o = options || {};
5951 scope = scope || this.obj;
5952 if(!this.isListening(fn, scope)){
5953 var l = {fn: fn, scope: scope, options: o};
5956 h = createDelayed(h, o, scope);
5959 h = createSingle(h, this, fn, scope);
5962 h = createBuffered(h, o, scope);
5965 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5966 this.listeners.push(l);
5968 this.listeners = this.listeners.slice(0);
5969 this.listeners.push(l);
5974 findListener : function(fn, scope){
5975 scope = scope || this.obj;
5976 var ls = this.listeners;
5977 for(var i = 0, len = ls.length; i < len; i++){
5979 if(l.fn == fn && l.scope == scope){
5986 isListening : function(fn, scope){
5987 return this.findListener(fn, scope) != -1;
5990 removeListener : function(fn, scope){
5992 if((index = this.findListener(fn, scope)) != -1){
5994 this.listeners.splice(index, 1);
5996 this.listeners = this.listeners.slice(0);
5997 this.listeners.splice(index, 1);
6004 clearListeners : function(){
6005 this.listeners = [];
6009 var ls = this.listeners, scope, len = ls.length;
6012 var args = Array.prototype.slice.call(arguments, 0);
6013 for(var i = 0; i < len; i++){
6015 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6016 this.firing = false;
6020 this.firing = false;
6027 * Ext JS Library 1.1.1
6028 * Copyright(c) 2006-2007, Ext JS, LLC.
6030 * Originally Released Under LGPL - original licence link has changed is not relivant.
6033 * <script type="text/javascript">
6037 * @class Roo.EventManager
6038 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6039 * several useful events directly.
6040 * See {@link Roo.EventObject} for more details on normalized event objects.
6043 Roo.EventManager = function(){
6044 var docReadyEvent, docReadyProcId, docReadyState = false;
6045 var resizeEvent, resizeTask, textEvent, textSize;
6046 var E = Roo.lib.Event;
6047 var D = Roo.lib.Dom;
6050 var fireDocReady = function(){
6052 docReadyState = true;
6055 clearInterval(docReadyProcId);
6057 if(Roo.isGecko || Roo.isOpera) {
6058 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6061 var defer = document.getElementById("ie-deferred-loader");
6063 defer.onreadystatechange = null;
6064 defer.parentNode.removeChild(defer);
6068 docReadyEvent.fire();
6069 docReadyEvent.clearListeners();
6074 var initDocReady = function(){
6075 docReadyEvent = new Roo.util.Event();
6076 if(Roo.isGecko || Roo.isOpera) {
6077 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6079 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6080 var defer = document.getElementById("ie-deferred-loader");
6081 defer.onreadystatechange = function(){
6082 if(this.readyState == "complete"){
6086 }else if(Roo.isSafari){
6087 docReadyProcId = setInterval(function(){
6088 var rs = document.readyState;
6089 if(rs == "complete") {
6094 // no matter what, make sure it fires on load
6095 E.on(window, "load", fireDocReady);
6098 var createBuffered = function(h, o){
6099 var task = new Roo.util.DelayedTask(h);
6101 // create new event object impl so new events don't wipe out properties
6102 e = new Roo.EventObjectImpl(e);
6103 task.delay(o.buffer, h, null, [e]);
6107 var createSingle = function(h, el, ename, fn){
6109 Roo.EventManager.removeListener(el, ename, fn);
6114 var createDelayed = function(h, o){
6116 // create new event object impl so new events don't wipe out properties
6117 e = new Roo.EventObjectImpl(e);
6118 setTimeout(function(){
6124 var listen = function(element, ename, opt, fn, scope){
6125 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6126 fn = fn || o.fn; scope = scope || o.scope;
6127 var el = Roo.getDom(element);
6129 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6131 var h = function(e){
6132 e = Roo.EventObject.setEvent(e);
6135 t = e.getTarget(o.delegate, el);
6142 if(o.stopEvent === true){
6145 if(o.preventDefault === true){
6148 if(o.stopPropagation === true){
6149 e.stopPropagation();
6152 if(o.normalized === false){
6156 fn.call(scope || el, e, t, o);
6159 h = createDelayed(h, o);
6162 h = createSingle(h, el, ename, fn);
6165 h = createBuffered(h, o);
6167 fn._handlers = fn._handlers || [];
6168 fn._handlers.push([Roo.id(el), ename, h]);
6171 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6172 el.addEventListener("DOMMouseScroll", h, false);
6173 E.on(window, 'unload', function(){
6174 el.removeEventListener("DOMMouseScroll", h, false);
6177 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6178 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6183 var stopListening = function(el, ename, fn){
6184 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6186 for(var i = 0, len = hds.length; i < len; i++){
6188 if(h[0] == id && h[1] == ename){
6195 E.un(el, ename, hd);
6196 el = Roo.getDom(el);
6197 if(ename == "mousewheel" && el.addEventListener){
6198 el.removeEventListener("DOMMouseScroll", hd, false);
6200 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6201 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6205 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6212 * @scope Roo.EventManager
6217 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6218 * object with a Roo.EventObject
6219 * @param {Function} fn The method the event invokes
6220 * @param {Object} scope An object that becomes the scope of the handler
6221 * @param {boolean} override If true, the obj passed in becomes
6222 * the execution scope of the listener
6223 * @return {Function} The wrapped function
6226 wrap : function(fn, scope, override){
6228 Roo.EventObject.setEvent(e);
6229 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6234 * Appends an event handler to an element (shorthand for addListener)
6235 * @param {String/HTMLElement} element The html element or id to assign the
6236 * @param {String} eventName The type of event to listen for
6237 * @param {Function} handler The method the event invokes
6238 * @param {Object} scope (optional) The scope in which to execute the handler
6239 * function. The handler function's "this" context.
6240 * @param {Object} options (optional) An object containing handler configuration
6241 * properties. This may contain any of the following properties:<ul>
6242 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6243 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6244 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6245 * <li>preventDefault {Boolean} True to prevent the default action</li>
6246 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6247 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6248 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6249 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6250 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6251 * by the specified number of milliseconds. If the event fires again within that time, the original
6252 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6255 * <b>Combining Options</b><br>
6256 * Using the options argument, it is possible to combine different types of listeners:<br>
6258 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6260 el.on('click', this.onClick, this, {
6267 * <b>Attaching multiple handlers in 1 call</b><br>
6268 * The method also allows for a single argument to be passed which is a config object containing properties
6269 * which specify multiple handlers.
6279 fn: this.onMouseOver
6288 * Or a shorthand syntax:<br>
6291 'click' : this.onClick,
6292 'mouseover' : this.onMouseOver,
6293 'mouseout' : this.onMouseOut
6297 addListener : function(element, eventName, fn, scope, options){
6298 if(typeof eventName == "object"){
6304 if(typeof o[e] == "function"){
6306 listen(element, e, o, o[e], o.scope);
6308 // individual options
6309 listen(element, e, o[e]);
6314 return listen(element, eventName, options, fn, scope);
6318 * Removes an event handler
6320 * @param {String/HTMLElement} element The id or html element to remove the
6322 * @param {String} eventName The type of event
6323 * @param {Function} fn
6324 * @return {Boolean} True if a listener was actually removed
6326 removeListener : function(element, eventName, fn){
6327 return stopListening(element, eventName, fn);
6331 * Fires when the document is ready (before onload and before images are loaded). Can be
6332 * accessed shorthanded Roo.onReady().
6333 * @param {Function} fn The method the event invokes
6334 * @param {Object} scope An object that becomes the scope of the handler
6335 * @param {boolean} options
6337 onDocumentReady : function(fn, scope, options){
6338 if(docReadyState){ // if it already fired
6339 docReadyEvent.addListener(fn, scope, options);
6340 docReadyEvent.fire();
6341 docReadyEvent.clearListeners();
6347 docReadyEvent.addListener(fn, scope, options);
6351 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6352 * @param {Function} fn The method the event invokes
6353 * @param {Object} scope An object that becomes the scope of the handler
6354 * @param {boolean} options
6356 onWindowResize : function(fn, scope, options){
6358 resizeEvent = new Roo.util.Event();
6359 resizeTask = new Roo.util.DelayedTask(function(){
6360 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6362 E.on(window, "resize", function(){
6364 resizeTask.delay(50);
6366 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6370 resizeEvent.addListener(fn, scope, options);
6374 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6375 * @param {Function} fn The method the event invokes
6376 * @param {Object} scope An object that becomes the scope of the handler
6377 * @param {boolean} options
6379 onTextResize : function(fn, scope, options){
6381 textEvent = new Roo.util.Event();
6382 var textEl = new Roo.Element(document.createElement('div'));
6383 textEl.dom.className = 'x-text-resize';
6384 textEl.dom.innerHTML = 'X';
6385 textEl.appendTo(document.body);
6386 textSize = textEl.dom.offsetHeight;
6387 setInterval(function(){
6388 if(textEl.dom.offsetHeight != textSize){
6389 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6391 }, this.textResizeInterval);
6393 textEvent.addListener(fn, scope, options);
6397 * Removes the passed window resize listener.
6398 * @param {Function} fn The method the event invokes
6399 * @param {Object} scope The scope of handler
6401 removeResizeListener : function(fn, scope){
6403 resizeEvent.removeListener(fn, scope);
6408 fireResize : function(){
6410 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6414 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6418 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6420 textResizeInterval : 50
6425 * @scopeAlias pub=Roo.EventManager
6429 * Appends an event handler to an element (shorthand for addListener)
6430 * @param {String/HTMLElement} element The html element or id to assign the
6431 * @param {String} eventName The type of event to listen for
6432 * @param {Function} handler The method the event invokes
6433 * @param {Object} scope (optional) The scope in which to execute the handler
6434 * function. The handler function's "this" context.
6435 * @param {Object} options (optional) An object containing handler configuration
6436 * properties. This may contain any of the following properties:<ul>
6437 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6438 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6439 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6440 * <li>preventDefault {Boolean} True to prevent the default action</li>
6441 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6442 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6443 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6444 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6445 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6446 * by the specified number of milliseconds. If the event fires again within that time, the original
6447 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6450 * <b>Combining Options</b><br>
6451 * Using the options argument, it is possible to combine different types of listeners:<br>
6453 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6455 el.on('click', this.onClick, this, {
6462 * <b>Attaching multiple handlers in 1 call</b><br>
6463 * The method also allows for a single argument to be passed which is a config object containing properties
6464 * which specify multiple handlers.
6474 fn: this.onMouseOver
6483 * Or a shorthand syntax:<br>
6486 'click' : this.onClick,
6487 'mouseover' : this.onMouseOver,
6488 'mouseout' : this.onMouseOut
6492 pub.on = pub.addListener;
6493 pub.un = pub.removeListener;
6495 pub.stoppedMouseDownEvent = new Roo.util.Event();
6499 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6500 * @param {Function} fn The method the event invokes
6501 * @param {Object} scope An object that becomes the scope of the handler
6502 * @param {boolean} override If true, the obj passed in becomes
6503 * the execution scope of the listener
6507 Roo.onReady = Roo.EventManager.onDocumentReady;
6509 Roo.onReady(function(){
6510 var bd = Roo.get(document.body);
6515 : Roo.isGecko ? "roo-gecko"
6516 : Roo.isOpera ? "roo-opera"
6517 : Roo.isSafari ? "roo-safari" : ""];
6520 cls.push("roo-mac");
6523 cls.push("roo-linux");
6525 if(Roo.isBorderBox){
6526 cls.push('roo-border-box');
6528 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6529 var p = bd.dom.parentNode;
6531 p.className += ' roo-strict';
6534 bd.addClass(cls.join(' '));
6538 * @class Roo.EventObject
6539 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6540 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6543 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6545 var target = e.getTarget();
6548 var myDiv = Roo.get("myDiv");
6549 myDiv.on("click", handleClick);
6551 Roo.EventManager.on("myDiv", 'click', handleClick);
6552 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6556 Roo.EventObject = function(){
6558 var E = Roo.lib.Event;
6560 // safari keypress events for special keys return bad keycodes
6563 63235 : 39, // right
6566 63276 : 33, // page up
6567 63277 : 34, // page down
6568 63272 : 46, // delete
6573 // normalize button clicks
6574 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6575 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6577 Roo.EventObjectImpl = function(e){
6579 this.setEvent(e.browserEvent || e);
6582 Roo.EventObjectImpl.prototype = {
6584 * Used to fix doc tools.
6585 * @scope Roo.EventObject.prototype
6591 /** The normal browser event */
6592 browserEvent : null,
6593 /** The button pressed in a mouse event */
6595 /** True if the shift key was down during the event */
6597 /** True if the control key was down during the event */
6599 /** True if the alt key was down during the event */
6658 setEvent : function(e){
6659 if(e == this || (e && e.browserEvent)){ // already wrapped
6662 this.browserEvent = e;
6664 // normalize buttons
6665 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6666 if(e.type == 'click' && this.button == -1){
6670 this.shiftKey = e.shiftKey;
6671 // mac metaKey behaves like ctrlKey
6672 this.ctrlKey = e.ctrlKey || e.metaKey;
6673 this.altKey = e.altKey;
6674 // in getKey these will be normalized for the mac
6675 this.keyCode = e.keyCode;
6676 // keyup warnings on firefox.
6677 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6678 // cache the target for the delayed and or buffered events
6679 this.target = E.getTarget(e);
6681 this.xy = E.getXY(e);
6684 this.shiftKey = false;
6685 this.ctrlKey = false;
6686 this.altKey = false;
6696 * Stop the event (preventDefault and stopPropagation)
6698 stopEvent : function(){
6699 if(this.browserEvent){
6700 if(this.browserEvent.type == 'mousedown'){
6701 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6703 E.stopEvent(this.browserEvent);
6708 * Prevents the browsers default handling of the event.
6710 preventDefault : function(){
6711 if(this.browserEvent){
6712 E.preventDefault(this.browserEvent);
6717 isNavKeyPress : function(){
6718 var k = this.keyCode;
6719 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6720 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6723 isSpecialKey : function(){
6724 var k = this.keyCode;
6725 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6726 (k == 16) || (k == 17) ||
6727 (k >= 18 && k <= 20) ||
6728 (k >= 33 && k <= 35) ||
6729 (k >= 36 && k <= 39) ||
6730 (k >= 44 && k <= 45);
6733 * Cancels bubbling of the event.
6735 stopPropagation : function(){
6736 if(this.browserEvent){
6737 if(this.type == 'mousedown'){
6738 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6740 E.stopPropagation(this.browserEvent);
6745 * Gets the key code for the event.
6748 getCharCode : function(){
6749 return this.charCode || this.keyCode;
6753 * Returns a normalized keyCode for the event.
6754 * @return {Number} The key code
6756 getKey : function(){
6757 var k = this.keyCode || this.charCode;
6758 return Roo.isSafari ? (safariKeys[k] || k) : k;
6762 * Gets the x coordinate of the event.
6765 getPageX : function(){
6770 * Gets the y coordinate of the event.
6773 getPageY : function(){
6778 * Gets the time of the event.
6781 getTime : function(){
6782 if(this.browserEvent){
6783 return E.getTime(this.browserEvent);
6789 * Gets the page coordinates of the event.
6790 * @return {Array} The xy values like [x, y]
6797 * Gets the target for the event.
6798 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6799 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6800 search as a number or element (defaults to 10 || document.body)
6801 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6802 * @return {HTMLelement}
6804 getTarget : function(selector, maxDepth, returnEl){
6805 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6808 * Gets the related target.
6809 * @return {HTMLElement}
6811 getRelatedTarget : function(){
6812 if(this.browserEvent){
6813 return E.getRelatedTarget(this.browserEvent);
6819 * Normalizes mouse wheel delta across browsers
6820 * @return {Number} The delta
6822 getWheelDelta : function(){
6823 var e = this.browserEvent;
6825 if(e.wheelDelta){ /* IE/Opera. */
6826 delta = e.wheelDelta/120;
6827 }else if(e.detail){ /* Mozilla case. */
6828 delta = -e.detail/3;
6834 * Returns true if the control, meta, shift or alt key was pressed during this event.
6837 hasModifier : function(){
6838 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6842 * Returns true if the target of this event equals el or is a child of el
6843 * @param {String/HTMLElement/Element} el
6844 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6847 within : function(el, related){
6848 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6849 return t && Roo.fly(el).contains(t);
6852 getPoint : function(){
6853 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6857 return new Roo.EventObjectImpl();
6862 * Ext JS Library 1.1.1
6863 * Copyright(c) 2006-2007, Ext JS, LLC.
6865 * Originally Released Under LGPL - original licence link has changed is not relivant.
6868 * <script type="text/javascript">
6872 // was in Composite Element!??!?!
6875 var D = Roo.lib.Dom;
6876 var E = Roo.lib.Event;
6877 var A = Roo.lib.Anim;
6879 // local style camelizing for speed
6881 var camelRe = /(-[a-z])/gi;
6882 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6883 var view = document.defaultView;
6886 * @class Roo.Element
6887 * Represents an Element in the DOM.<br><br>
6890 var el = Roo.get("my-div");
6893 var el = getEl("my-div");
6895 // or with a DOM element
6896 var el = Roo.get(myDivElement);
6898 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6899 * each call instead of constructing a new one.<br><br>
6900 * <b>Animations</b><br />
6901 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6902 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6904 Option Default Description
6905 --------- -------- ---------------------------------------------
6906 duration .35 The duration of the animation in seconds
6907 easing easeOut The YUI easing method
6908 callback none A function to execute when the anim completes
6909 scope this The scope (this) of the callback function
6911 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6912 * manipulate the animation. Here's an example:
6914 var el = Roo.get("my-div");
6919 // default animation
6920 el.setWidth(100, true);
6922 // animation with some options set
6929 // using the "anim" property to get the Anim object
6935 el.setWidth(100, opt);
6937 if(opt.anim.isAnimated()){
6941 * <b> Composite (Collections of) Elements</b><br />
6942 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6943 * @constructor Create a new Element directly.
6944 * @param {String/HTMLElement} element
6945 * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
6947 Roo.Element = function(element, forceNew){
6948 var dom = typeof element == "string" ?
6949 document.getElementById(element) : element;
6950 if(!dom){ // invalid id/element
6954 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6955 return Roo.Element.cache[id];
6965 * The DOM element ID
6968 this.id = id || Roo.id(dom);
6971 var El = Roo.Element;
6975 * The element's default display mode (defaults to "")
6978 originalDisplay : "",
6982 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6987 * Sets the element's visibility mode. When setVisible() is called it
6988 * will use this to determine whether to set the visibility or the display property.
6989 * @param visMode Element.VISIBILITY or Element.DISPLAY
6990 * @return {Roo.Element} this
6992 setVisibilityMode : function(visMode){
6993 this.visibilityMode = visMode;
6997 * Convenience method for setVisibilityMode(Element.DISPLAY)
6998 * @param {String} display (optional) What to set display to when visible
6999 * @return {Roo.Element} this
7001 enableDisplayMode : function(display){
7002 this.setVisibilityMode(El.DISPLAY);
7003 if(typeof display != "undefined") this.originalDisplay = display;
7008 * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7009 * @param {String} selector The simple selector to test
7010 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7011 search as a number or element (defaults to 10 || document.body)
7012 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7013 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7015 findParent : function(simpleSelector, maxDepth, returnEl){
7016 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7017 maxDepth = maxDepth || 50;
7018 if(typeof maxDepth != "number"){
7019 stopEl = Roo.getDom(maxDepth);
7022 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7023 if(dq.is(p, simpleSelector)){
7024 return returnEl ? Roo.get(p) : p;
7034 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7035 * @param {String} selector The simple selector to test
7036 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7037 search as a number or element (defaults to 10 || document.body)
7038 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7039 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7041 findParentNode : function(simpleSelector, maxDepth, returnEl){
7042 var p = Roo.fly(this.dom.parentNode, '_internal');
7043 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7047 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7048 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7049 * @param {String} selector The simple selector to test
7050 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7051 search as a number or element (defaults to 10 || document.body)
7052 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7054 up : function(simpleSelector, maxDepth){
7055 return this.findParentNode(simpleSelector, maxDepth, true);
7061 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7062 * @param {String} selector The simple selector to test
7063 * @return {Boolean} True if this element matches the selector, else false
7065 is : function(simpleSelector){
7066 return Roo.DomQuery.is(this.dom, simpleSelector);
7070 * Perform animation on this element.
7071 * @param {Object} args The YUI animation control args
7072 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7073 * @param {Function} onComplete (optional) Function to call when animation completes
7074 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7075 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7076 * @return {Roo.Element} this
7078 animate : function(args, duration, onComplete, easing, animType){
7079 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7084 * @private Internal animation call
7086 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7087 animType = animType || 'run';
7089 var anim = Roo.lib.Anim[animType](
7091 (opt.duration || defaultDur) || .35,
7092 (opt.easing || defaultEase) || 'easeOut',
7094 Roo.callback(cb, this);
7095 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7103 // private legacy anim prep
7104 preanim : function(a, i){
7105 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7109 * Removes worthless text nodes
7110 * @param {Boolean} forceReclean (optional) By default the element
7111 * keeps track if it has been cleaned already so
7112 * you can call this over and over. However, if you update the element and
7113 * need to force a reclean, you can pass true.
7115 clean : function(forceReclean){
7116 if(this.isCleaned && forceReclean !== true){
7120 var d = this.dom, n = d.firstChild, ni = -1;
7122 var nx = n.nextSibling;
7123 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7130 this.isCleaned = true;
7135 calcOffsetsTo : function(el){
7138 var restorePos = false;
7139 if(el.getStyle('position') == 'static'){
7140 el.position('relative');
7145 while(op && op != d && op.tagName != 'HTML'){
7148 op = op.offsetParent;
7151 el.position('static');
7157 * Scrolls this element into view within the passed container.
7158 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7159 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7160 * @return {Roo.Element} this
7162 scrollIntoView : function(container, hscroll){
7163 var c = Roo.getDom(container) || document.body;
7166 var o = this.calcOffsetsTo(c),
7169 b = t+el.offsetHeight,
7170 r = l+el.offsetWidth;
7172 var ch = c.clientHeight;
7173 var ct = parseInt(c.scrollTop, 10);
7174 var cl = parseInt(c.scrollLeft, 10);
7176 var cr = cl + c.clientWidth;
7184 if(hscroll !== false){
7188 c.scrollLeft = r-c.clientWidth;
7195 scrollChildIntoView : function(child, hscroll){
7196 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7200 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7201 * the new height may not be available immediately.
7202 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7203 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7204 * @param {Function} onComplete (optional) Function to call when animation completes
7205 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7206 * @return {Roo.Element} this
7208 autoHeight : function(animate, duration, onComplete, easing){
7209 var oldHeight = this.getHeight();
7211 this.setHeight(1); // force clipping
7212 setTimeout(function(){
7213 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7215 this.setHeight(height);
7217 if(typeof onComplete == "function"){
7221 this.setHeight(oldHeight); // restore original height
7222 this.setHeight(height, animate, duration, function(){
7224 if(typeof onComplete == "function") onComplete();
7225 }.createDelegate(this), easing);
7227 }.createDelegate(this), 0);
7232 * Returns true if this element is an ancestor of the passed element
7233 * @param {HTMLElement/String} el The element to check
7234 * @return {Boolean} True if this element is an ancestor of el, else false
7236 contains : function(el){
7237 if(!el){return false;}
7238 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7242 * Checks whether the element is currently visible using both visibility and display properties.
7243 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7244 * @return {Boolean} True if the element is currently visible, else false
7246 isVisible : function(deep) {
7247 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7248 if(deep !== true || !vis){
7251 var p = this.dom.parentNode;
7252 while(p && p.tagName.toLowerCase() != "body"){
7253 if(!Roo.fly(p, '_isVisible').isVisible()){
7262 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7263 * @param {String} selector The CSS selector
7264 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7265 * @return {CompositeElement/CompositeElementLite} The composite element
7267 select : function(selector, unique){
7268 return El.select(selector, unique, this.dom);
7272 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7273 * @param {String} selector The CSS selector
7274 * @return {Array} An array of the matched nodes
7276 query : function(selector, unique){
7277 return Roo.DomQuery.select(selector, this.dom);
7281 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7282 * @param {String} selector The CSS selector
7283 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7284 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7286 child : function(selector, returnDom){
7287 var n = Roo.DomQuery.selectNode(selector, this.dom);
7288 return returnDom ? n : Roo.get(n);
7292 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7293 * @param {String} selector The CSS selector
7294 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7295 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7297 down : function(selector, returnDom){
7298 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7299 return returnDom ? n : Roo.get(n);
7303 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7304 * @param {String} group The group the DD object is member of
7305 * @param {Object} config The DD config object
7306 * @param {Object} overrides An object containing methods to override/implement on the DD object
7307 * @return {Roo.dd.DD} The DD object
7309 initDD : function(group, config, overrides){
7310 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7311 return Roo.apply(dd, overrides);
7315 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7316 * @param {String} group The group the DDProxy object is member of
7317 * @param {Object} config The DDProxy config object
7318 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7319 * @return {Roo.dd.DDProxy} The DDProxy object
7321 initDDProxy : function(group, config, overrides){
7322 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7323 return Roo.apply(dd, overrides);
7327 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7328 * @param {String} group The group the DDTarget object is member of
7329 * @param {Object} config The DDTarget config object
7330 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7331 * @return {Roo.dd.DDTarget} The DDTarget object
7333 initDDTarget : function(group, config, overrides){
7334 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7335 return Roo.apply(dd, overrides);
7339 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7340 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7341 * @param {Boolean} visible Whether the element is visible
7342 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7343 * @return {Roo.Element} this
7345 setVisible : function(visible, animate){
7347 if(this.visibilityMode == El.DISPLAY){
7348 this.setDisplayed(visible);
7351 this.dom.style.visibility = visible ? "visible" : "hidden";
7354 // closure for composites
7356 var visMode = this.visibilityMode;
7358 this.setOpacity(.01);
7359 this.setVisible(true);
7361 this.anim({opacity: { to: (visible?1:0) }},
7362 this.preanim(arguments, 1),
7363 null, .35, 'easeIn', function(){
7365 if(visMode == El.DISPLAY){
7366 dom.style.display = "none";
7368 dom.style.visibility = "hidden";
7370 Roo.get(dom).setOpacity(1);
7378 * Returns true if display is not "none"
7381 isDisplayed : function() {
7382 return this.getStyle("display") != "none";
7386 * Toggles the element's visibility or display, depending on visibility mode.
7387 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7388 * @return {Roo.Element} this
7390 toggle : function(animate){
7391 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7396 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7397 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7398 * @return {Roo.Element} this
7400 setDisplayed : function(value) {
7401 if(typeof value == "boolean"){
7402 value = value ? this.originalDisplay : "none";
7404 this.setStyle("display", value);
7409 * Tries to focus the element. Any exceptions are caught and ignored.
7410 * @return {Roo.Element} this
7412 focus : function() {
7420 * Tries to blur the element. Any exceptions are caught and ignored.
7421 * @return {Roo.Element} this
7431 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7432 * @param {String/Array} className The CSS class to add, or an array of classes
7433 * @return {Roo.Element} this
7435 addClass : function(className){
7436 if(className instanceof Array){
7437 for(var i = 0, len = className.length; i < len; i++) {
7438 this.addClass(className[i]);
7441 if(className && !this.hasClass(className)){
7442 this.dom.className = this.dom.className + " " + className;
7449 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7450 * @param {String/Array} className The CSS class to add, or an array of classes
7451 * @return {Roo.Element} this
7453 radioClass : function(className){
7454 var siblings = this.dom.parentNode.childNodes;
7455 for(var i = 0; i < siblings.length; i++) {
7456 var s = siblings[i];
7457 if(s.nodeType == 1){
7458 Roo.get(s).removeClass(className);
7461 this.addClass(className);
7466 * Removes one or more CSS classes from the element.
7467 * @param {String/Array} className The CSS class to remove, or an array of classes
7468 * @return {Roo.Element} this
7470 removeClass : function(className){
7471 if(!className || !this.dom.className){
7474 if(className instanceof Array){
7475 for(var i = 0, len = className.length; i < len; i++) {
7476 this.removeClass(className[i]);
7479 if(this.hasClass(className)){
7480 var re = this.classReCache[className];
7482 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7483 this.classReCache[className] = re;
7485 this.dom.className =
7486 this.dom.className.replace(re, " ");
7496 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7497 * @param {String} className The CSS class to toggle
7498 * @return {Roo.Element} this
7500 toggleClass : function(className){
7501 if(this.hasClass(className)){
7502 this.removeClass(className);
7504 this.addClass(className);
7510 * Checks if the specified CSS class exists on this element's DOM node.
7511 * @param {String} className The CSS class to check for
7512 * @return {Boolean} True if the class exists, else false
7514 hasClass : function(className){
7515 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7519 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7520 * @param {String} oldClassName The CSS class to replace
7521 * @param {String} newClassName The replacement CSS class
7522 * @return {Roo.Element} this
7524 replaceClass : function(oldClassName, newClassName){
7525 this.removeClass(oldClassName);
7526 this.addClass(newClassName);
7531 * Returns an object with properties matching the styles requested.
7532 * For example, el.getStyles('color', 'font-size', 'width') might return
7533 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7534 * @param {String} style1 A style name
7535 * @param {String} style2 A style name
7536 * @param {String} etc.
7537 * @return {Object} The style object
7539 getStyles : function(){
7540 var a = arguments, len = a.length, r = {};
7541 for(var i = 0; i < len; i++){
7542 r[a[i]] = this.getStyle(a[i]);
7548 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7549 * @param {String} property The style property whose value is returned.
7550 * @return {String} The current value of the style property for this element.
7552 getStyle : function(){
7553 return view && view.getComputedStyle ?
7555 var el = this.dom, v, cs, camel;
7556 if(prop == 'float'){
7559 if(el.style && (v = el.style[prop])){
7562 if(cs = view.getComputedStyle(el, "")){
7563 if(!(camel = propCache[prop])){
7564 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7571 var el = this.dom, v, cs, camel;
7572 if(prop == 'opacity'){
7573 if(typeof el.style.filter == 'string'){
7574 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7576 var fv = parseFloat(m[1]);
7578 return fv ? fv / 100 : 0;
7583 }else if(prop == 'float'){
7584 prop = "styleFloat";
7586 if(!(camel = propCache[prop])){
7587 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7589 if(v = el.style[camel]){
7592 if(cs = el.currentStyle){
7600 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7601 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7602 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7603 * @return {Roo.Element} this
7605 setStyle : function(prop, value){
7606 if(typeof prop == "string"){
7608 if (prop == 'float') {
7609 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7614 if(!(camel = propCache[prop])){
7615 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7618 if(camel == 'opacity') {
7619 this.setOpacity(value);
7621 this.dom.style[camel] = value;
7624 for(var style in prop){
7625 if(typeof prop[style] != "function"){
7626 this.setStyle(style, prop[style]);
7634 * More flexible version of {@link #setStyle} for setting style properties.
7635 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7636 * a function which returns such a specification.
7637 * @return {Roo.Element} this
7639 applyStyles : function(style){
7640 Roo.DomHelper.applyStyles(this.dom, style);
7645 * 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).
7646 * @return {Number} The X position of the element
7649 return D.getX(this.dom);
7653 * Gets the current Y 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).
7654 * @return {Number} The Y position of the element
7657 return D.getY(this.dom);
7661 * Gets the current 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).
7662 * @return {Array} The XY position of the element
7665 return D.getXY(this.dom);
7669 * Sets the 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).
7670 * @param {Number} The X position of the element
7671 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7672 * @return {Roo.Element} this
7674 setX : function(x, animate){
7676 D.setX(this.dom, x);
7678 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7684 * Sets the Y 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).
7685 * @param {Number} The Y position of the element
7686 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7687 * @return {Roo.Element} this
7689 setY : function(y, animate){
7691 D.setY(this.dom, y);
7693 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7699 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7700 * @param {String} left The left CSS property value
7701 * @return {Roo.Element} this
7703 setLeft : function(left){
7704 this.setStyle("left", this.addUnits(left));
7709 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7710 * @param {String} top The top CSS property value
7711 * @return {Roo.Element} this
7713 setTop : function(top){
7714 this.setStyle("top", this.addUnits(top));
7719 * Sets the element's CSS right style.
7720 * @param {String} right The right CSS property value
7721 * @return {Roo.Element} this
7723 setRight : function(right){
7724 this.setStyle("right", this.addUnits(right));
7729 * Sets the element's CSS bottom style.
7730 * @param {String} bottom The bottom CSS property value
7731 * @return {Roo.Element} this
7733 setBottom : function(bottom){
7734 this.setStyle("bottom", this.addUnits(bottom));
7739 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7740 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7741 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7742 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7743 * @return {Roo.Element} this
7745 setXY : function(pos, animate){
7747 D.setXY(this.dom, pos);
7749 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7755 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7756 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7757 * @param {Number} x X value for new position (coordinates are page-based)
7758 * @param {Number} y Y value for new position (coordinates are page-based)
7759 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7760 * @return {Roo.Element} this
7762 setLocation : function(x, y, animate){
7763 this.setXY([x, y], this.preanim(arguments, 2));
7768 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7769 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7770 * @param {Number} x X value for new position (coordinates are page-based)
7771 * @param {Number} y Y value for new position (coordinates are page-based)
7772 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7773 * @return {Roo.Element} this
7775 moveTo : function(x, y, animate){
7776 this.setXY([x, y], this.preanim(arguments, 2));
7781 * Returns the region of the given element.
7782 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7783 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7785 getRegion : function(){
7786 return D.getRegion(this.dom);
7790 * Returns the offset height of the element
7791 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7792 * @return {Number} The element's height
7794 getHeight : function(contentHeight){
7795 var h = this.dom.offsetHeight || 0;
7796 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7800 * Returns the offset width of the element
7801 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7802 * @return {Number} The element's width
7804 getWidth : function(contentWidth){
7805 var w = this.dom.offsetWidth || 0;
7806 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7810 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7811 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7812 * if a height has not been set using CSS.
7815 getComputedHeight : function(){
7816 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7818 h = parseInt(this.getStyle('height'), 10) || 0;
7819 if(!this.isBorderBox()){
7820 h += this.getFrameWidth('tb');
7827 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7828 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7829 * if a width has not been set using CSS.
7832 getComputedWidth : function(){
7833 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7835 w = parseInt(this.getStyle('width'), 10) || 0;
7836 if(!this.isBorderBox()){
7837 w += this.getFrameWidth('lr');
7844 * Returns the size of the element.
7845 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7846 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7848 getSize : function(contentSize){
7849 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7853 * Returns the width and height of the viewport.
7854 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7856 getViewSize : function(){
7857 var d = this.dom, doc = document, aw = 0, ah = 0;
7858 if(d == doc || d == doc.body){
7859 return {width : D.getViewWidth(), height: D.getViewHeight()};
7862 width : d.clientWidth,
7863 height: d.clientHeight
7869 * Returns the value of the "value" attribute
7870 * @param {Boolean} asNumber true to parse the value as a number
7871 * @return {String/Number}
7873 getValue : function(asNumber){
7874 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7878 adjustWidth : function(width){
7879 if(typeof width == "number"){
7880 if(this.autoBoxAdjust && !this.isBorderBox()){
7881 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7891 adjustHeight : function(height){
7892 if(typeof height == "number"){
7893 if(this.autoBoxAdjust && !this.isBorderBox()){
7894 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7904 * Set the width of the element
7905 * @param {Number} width The new width
7906 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7907 * @return {Roo.Element} this
7909 setWidth : function(width, animate){
7910 width = this.adjustWidth(width);
7912 this.dom.style.width = this.addUnits(width);
7914 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7920 * Set the height of the element
7921 * @param {Number} height The new height
7922 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7923 * @return {Roo.Element} this
7925 setHeight : function(height, animate){
7926 height = this.adjustHeight(height);
7928 this.dom.style.height = this.addUnits(height);
7930 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7936 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7937 * @param {Number} width The new width
7938 * @param {Number} height The new height
7939 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7940 * @return {Roo.Element} this
7942 setSize : function(width, height, animate){
7943 if(typeof width == "object"){ // in case of object from getSize()
7944 height = width.height; width = width.width;
7946 width = this.adjustWidth(width); height = this.adjustHeight(height);
7948 this.dom.style.width = this.addUnits(width);
7949 this.dom.style.height = this.addUnits(height);
7951 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7957 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7958 * @param {Number} x X value for new position (coordinates are page-based)
7959 * @param {Number} y Y value for new position (coordinates are page-based)
7960 * @param {Number} width The new width
7961 * @param {Number} height The new height
7962 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7963 * @return {Roo.Element} this
7965 setBounds : function(x, y, width, height, animate){
7967 this.setSize(width, height);
7968 this.setLocation(x, y);
7970 width = this.adjustWidth(width); height = this.adjustHeight(height);
7971 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7972 this.preanim(arguments, 4), 'motion');
7978 * Sets the element's position and size the the specified region. If animation is true then width, height, x and y will be animated concurrently.
7979 * @param {Roo.lib.Region} region The region to fill
7980 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7981 * @return {Roo.Element} this
7983 setRegion : function(region, animate){
7984 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7989 * Appends an event handler
7991 * @param {String} eventName The type of event to append
7992 * @param {Function} fn The method the event invokes
7993 * @param {Object} scope (optional) The scope (this object) of the fn
7994 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7996 addListener : function(eventName, fn, scope, options){
7998 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8003 * Removes an event handler from this element
8004 * @param {String} eventName the type of event to remove
8005 * @param {Function} fn the method the event invokes
8006 * @return {Roo.Element} this
8008 removeListener : function(eventName, fn){
8009 Roo.EventManager.removeListener(this.dom, eventName, fn);
8014 * Removes all previous added listeners from this element
8015 * @return {Roo.Element} this
8017 removeAllListeners : function(){
8018 E.purgeElement(this.dom);
8022 relayEvent : function(eventName, observable){
8023 this.on(eventName, function(e){
8024 observable.fireEvent(eventName, e);
8029 * Set the opacity of the element
8030 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8031 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8032 * @return {Roo.Element} this
8034 setOpacity : function(opacity, animate){
8036 var s = this.dom.style;
8039 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8040 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8042 s.opacity = opacity;
8045 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8051 * Gets the left X coordinate
8052 * @param {Boolean} local True to get the local css position instead of page coordinate
8055 getLeft : function(local){
8059 return parseInt(this.getStyle("left"), 10) || 0;
8064 * Gets the right X coordinate of the element (element X position + element width)
8065 * @param {Boolean} local True to get the local css position instead of page coordinate
8068 getRight : function(local){
8070 return this.getX() + this.getWidth();
8072 return (this.getLeft(true) + this.getWidth()) || 0;
8077 * Gets the top Y coordinate
8078 * @param {Boolean} local True to get the local css position instead of page coordinate
8081 getTop : function(local) {
8085 return parseInt(this.getStyle("top"), 10) || 0;
8090 * Gets the bottom Y coordinate of the element (element Y position + element height)
8091 * @param {Boolean} local True to get the local css position instead of page coordinate
8094 getBottom : function(local){
8096 return this.getY() + this.getHeight();
8098 return (this.getTop(true) + this.getHeight()) || 0;
8103 * Initializes positioning on this element. If a desired position is not passed, it will make the
8104 * the element positioned relative IF it is not already positioned.
8105 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8106 * @param {Number} zIndex (optional) The zIndex to apply
8107 * @param {Number} x (optional) Set the page X position
8108 * @param {Number} y (optional) Set the page Y position
8110 position : function(pos, zIndex, x, y){
8112 if(this.getStyle('position') == 'static'){
8113 this.setStyle('position', 'relative');
8116 this.setStyle("position", pos);
8119 this.setStyle("z-index", zIndex);
8121 if(x !== undefined && y !== undefined){
8123 }else if(x !== undefined){
8125 }else if(y !== undefined){
8131 * Clear positioning back to the default when the document was loaded
8132 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8133 * @return {Roo.Element} this
8135 clearPositioning : function(value){
8143 "position" : "static"
8149 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8150 * snapshot before performing an update and then restoring the element.
8153 getPositioning : function(){
8154 var l = this.getStyle("left");
8155 var t = this.getStyle("top");
8157 "position" : this.getStyle("position"),
8159 "right" : l ? "" : this.getStyle("right"),
8161 "bottom" : t ? "" : this.getStyle("bottom"),
8162 "z-index" : this.getStyle("z-index")
8167 * Gets the width of the border(s) for the specified side(s)
8168 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8169 * passing lr would get the border (l)eft width + the border (r)ight width.
8170 * @return {Number} The width of the sides passed added together
8172 getBorderWidth : function(side){
8173 return this.addStyles(side, El.borders);
8177 * Gets the width of the padding(s) for the specified side(s)
8178 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8179 * passing lr would get the padding (l)eft + the padding (r)ight.
8180 * @return {Number} The padding of the sides passed added together
8182 getPadding : function(side){
8183 return this.addStyles(side, El.paddings);
8187 * Set positioning with an object returned by getPositioning().
8188 * @param {Object} posCfg
8189 * @return {Roo.Element} this
8191 setPositioning : function(pc){
8192 this.applyStyles(pc);
8193 if(pc.right == "auto"){
8194 this.dom.style.right = "";
8196 if(pc.bottom == "auto"){
8197 this.dom.style.bottom = "";
8203 fixDisplay : function(){
8204 if(this.getStyle("display") == "none"){
8205 this.setStyle("visibility", "hidden");
8206 this.setStyle("display", this.originalDisplay); // first try reverting to default
8207 if(this.getStyle("display") == "none"){ // if that fails, default to block
8208 this.setStyle("display", "block");
8214 * Quick set left and top adding default units
8215 * @param {String} left The left CSS property value
8216 * @param {String} top The top CSS property value
8217 * @return {Roo.Element} this
8219 setLeftTop : function(left, top){
8220 this.dom.style.left = this.addUnits(left);
8221 this.dom.style.top = this.addUnits(top);
8226 * Move this element relative to its current position.
8227 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8228 * @param {Number} distance How far to move the element in pixels
8229 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8230 * @return {Roo.Element} this
8232 move : function(direction, distance, animate){
8233 var xy = this.getXY();
8234 direction = direction.toLowerCase();
8238 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8242 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8247 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8252 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8259 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8260 * @return {Roo.Element} this
8263 if(!this.isClipped){
8264 this.isClipped = true;
8265 this.originalClip = {
8266 "o": this.getStyle("overflow"),
8267 "x": this.getStyle("overflow-x"),
8268 "y": this.getStyle("overflow-y")
8270 this.setStyle("overflow", "hidden");
8271 this.setStyle("overflow-x", "hidden");
8272 this.setStyle("overflow-y", "hidden");
8278 * Return clipping (overflow) to original clipping before clip() was called
8279 * @return {Roo.Element} this
8281 unclip : function(){
8283 this.isClipped = false;
8284 var o = this.originalClip;
8285 if(o.o){this.setStyle("overflow", o.o);}
8286 if(o.x){this.setStyle("overflow-x", o.x);}
8287 if(o.y){this.setStyle("overflow-y", o.y);}
8294 * Gets the x,y coordinates specified by the anchor position on the element.
8295 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8296 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8297 * {width: (target width), height: (target height)} (defaults to the element's current size)
8298 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8299 * @return {Array} [x, y] An array containing the element's x and y coordinates
8301 getAnchorXY : function(anchor, local, s){
8302 //Passing a different size is useful for pre-calculating anchors,
8303 //especially for anchored animations that change the el size.
8305 var w, h, vp = false;
8308 if(d == document.body || d == document){
8310 w = D.getViewWidth(); h = D.getViewHeight();
8312 w = this.getWidth(); h = this.getHeight();
8315 w = s.width; h = s.height;
8317 var x = 0, y = 0, r = Math.round;
8318 switch((anchor || "tl").toLowerCase()){
8360 var sc = this.getScroll();
8361 return [x + sc.left, y + sc.top];
8363 //Add the element's offset xy
8364 var o = this.getXY();
8365 return [x+o[0], y+o[1]];
8369 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8370 * supported position values.
8371 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8372 * @param {String} position The position to align to.
8373 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8374 * @return {Array} [x, y]
8376 getAlignToXY : function(el, p, o){
8380 throw "Element.alignTo with an element that doesn't exist";
8382 var c = false; //constrain to viewport
8383 var p1 = "", p2 = "";
8390 }else if(p.indexOf("-") == -1){
8393 p = p.toLowerCase();
8394 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8396 throw "Element.alignTo with an invalid alignment " + p;
8398 p1 = m[1]; p2 = m[2]; c = !!m[3];
8400 //Subtract the aligned el's internal xy from the target's offset xy
8401 //plus custom offset to get the aligned el's new offset xy
8402 var a1 = this.getAnchorXY(p1, true);
8403 var a2 = el.getAnchorXY(p2, false);
8404 var x = a2[0] - a1[0] + o[0];
8405 var y = a2[1] - a1[1] + o[1];
8407 //constrain the aligned el to viewport if necessary
8408 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8409 // 5px of margin for ie
8410 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8412 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8413 //perpendicular to the vp border, allow the aligned el to slide on that border,
8414 //otherwise swap the aligned el to the opposite border of the target.
8415 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8416 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8417 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8418 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8421 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8422 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8424 if((x+w) > dw + scrollX){
8425 x = swapX ? r.left-w : dw+scrollX-w;
8428 x = swapX ? r.right : scrollX;
8430 if((y+h) > dh + scrollY){
8431 y = swapY ? r.top-h : dh+scrollY-h;
8434 y = swapY ? r.bottom : scrollY;
8441 getConstrainToXY : function(){
8442 var os = {top:0, left:0, bottom:0, right: 0};
8444 return function(el, local, offsets, proposedXY){
8446 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8448 var vw, vh, vx = 0, vy = 0;
8449 if(el.dom == document.body || el.dom == document){
8450 vw = Roo.lib.Dom.getViewWidth();
8451 vh = Roo.lib.Dom.getViewHeight();
8453 vw = el.dom.clientWidth;
8454 vh = el.dom.clientHeight;
8456 var vxy = el.getXY();
8462 var s = el.getScroll();
8464 vx += offsets.left + s.left;
8465 vy += offsets.top + s.top;
8467 vw -= offsets.right;
8468 vh -= offsets.bottom;
8473 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8474 var x = xy[0], y = xy[1];
8475 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8477 // only move it if it needs it
8480 // first validate right/bottom
8489 // then make sure top/left isn't negative
8498 return moved ? [x, y] : false;
8503 adjustForConstraints : function(xy, parent, offsets){
8504 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8508 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8509 * document it aligns it to the viewport.
8510 * The position parameter is optional, and can be specified in any one of the following formats:
8512 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8513 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8514 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8515 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8516 * <li><b>Two anchors</b>: If two values from the table below are passed separated by a dash, the first value is used as the
8517 * element's anchor point, and the second value is used as the target's anchor point.</li>
8519 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8520 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8521 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8522 * that specified in order to enforce the viewport constraints.
8523 * Following are all of the supported anchor positions:
8526 ----- -----------------------------
8527 tl The top left corner (default)
8528 t The center of the top edge
8529 tr The top right corner
8530 l The center of the left edge
8531 c In the center of the element
8532 r The center of the right edge
8533 bl The bottom left corner
8534 b The center of the bottom edge
8535 br The bottom right corner
8539 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8540 el.alignTo("other-el");
8542 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8543 el.alignTo("other-el", "tr?");
8545 // align the bottom right corner of el with the center left edge of other-el
8546 el.alignTo("other-el", "br-l?");
8548 // align the center of el with the bottom left corner of other-el and
8549 // adjust the x position by -6 pixels (and the y position by 0)
8550 el.alignTo("other-el", "c-bl", [-6, 0]);
8552 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8553 * @param {String} position The position to align to.
8554 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8555 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8556 * @return {Roo.Element} this
8558 alignTo : function(element, position, offsets, animate){
8559 var xy = this.getAlignToXY(element, position, offsets);
8560 this.setXY(xy, this.preanim(arguments, 3));
8565 * Anchors an element to another element and realigns it when the window is resized.
8566 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8567 * @param {String} position The position to align to.
8568 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8569 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8570 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8571 * is a number, it is used as the buffer delay (defaults to 50ms).
8572 * @param {Function} callback The function to call after the animation finishes
8573 * @return {Roo.Element} this
8575 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8576 var action = function(){
8577 this.alignTo(el, alignment, offsets, animate);
8578 Roo.callback(callback, this);
8580 Roo.EventManager.onWindowResize(action, this);
8581 var tm = typeof monitorScroll;
8582 if(tm != 'undefined'){
8583 Roo.EventManager.on(window, 'scroll', action, this,
8584 {buffer: tm == 'number' ? monitorScroll : 50});
8586 action.call(this); // align immediately
8590 * Clears any opacity settings from this element. Required in some cases for IE.
8591 * @return {Roo.Element} this
8593 clearOpacity : function(){
8594 if (window.ActiveXObject) {
8595 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8596 this.dom.style.filter = "";
8599 this.dom.style.opacity = "";
8600 this.dom.style["-moz-opacity"] = "";
8601 this.dom.style["-khtml-opacity"] = "";
8607 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8608 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8609 * @return {Roo.Element} this
8611 hide : function(animate){
8612 this.setVisible(false, this.preanim(arguments, 0));
8617 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8618 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8619 * @return {Roo.Element} this
8621 show : function(animate){
8622 this.setVisible(true, this.preanim(arguments, 0));
8627 * @private Test if size has a unit, otherwise appends the default
8629 addUnits : function(size){
8630 return Roo.Element.addUnits(size, this.defaultUnit);
8634 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8635 * @return {Roo.Element} this
8637 beginMeasure : function(){
8639 if(el.offsetWidth || el.offsetHeight){
8640 return this; // offsets work already
8643 var p = this.dom, b = document.body; // start with this element
8644 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8645 var pe = Roo.get(p);
8646 if(pe.getStyle('display') == 'none'){
8647 changed.push({el: p, visibility: pe.getStyle("visibility")});
8648 p.style.visibility = "hidden";
8649 p.style.display = "block";
8653 this._measureChanged = changed;
8659 * Restores displays to before beginMeasure was called
8660 * @return {Roo.Element} this
8662 endMeasure : function(){
8663 var changed = this._measureChanged;
8665 for(var i = 0, len = changed.length; i < len; i++) {
8667 r.el.style.visibility = r.visibility;
8668 r.el.style.display = "none";
8670 this._measureChanged = null;
8676 * Update the innerHTML of this element, optionally searching for and processing scripts
8677 * @param {String} html The new HTML
8678 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8679 * @param {Function} callback For async script loading you can be noticed when the update completes
8680 * @return {Roo.Element} this
8682 update : function(html, loadScripts, callback){
8683 if(typeof html == "undefined"){
8686 if(loadScripts !== true){
8687 this.dom.innerHTML = html;
8688 if(typeof callback == "function"){
8696 html += '<span id="' + id + '"></span>';
8698 E.onAvailable(id, function(){
8699 var hd = document.getElementsByTagName("head")[0];
8700 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8701 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8702 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8705 while(match = re.exec(html)){
8706 var attrs = match[1];
8707 var srcMatch = attrs ? attrs.match(srcRe) : false;
8708 if(srcMatch && srcMatch[2]){
8709 var s = document.createElement("script");
8710 s.src = srcMatch[2];
8711 var typeMatch = attrs.match(typeRe);
8712 if(typeMatch && typeMatch[2]){
8713 s.type = typeMatch[2];
8716 }else if(match[2] && match[2].length > 0){
8717 if(window.execScript) {
8718 window.execScript(match[2]);
8726 window.eval(match[2]);
8730 var el = document.getElementById(id);
8731 if(el){el.parentNode.removeChild(el);}
8732 if(typeof callback == "function"){
8736 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8741 * Direct access to the UpdateManager update() method (takes the same parameters).
8742 * @param {String/Function} url The url for this request or a function to call to get the url
8743 * @param {String/Object} params (optional) The parameters to pass as either a url encoded string "param1=1&param2=2" or an object {param1: 1, param2: 2}
8744 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8745 * @param {Boolean} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used url. If true, it will not store the url.
8746 * @return {Roo.Element} this
8749 var um = this.getUpdateManager();
8750 um.update.apply(um, arguments);
8755 * Gets this element's UpdateManager
8756 * @return {Roo.UpdateManager} The UpdateManager
8758 getUpdateManager : function(){
8759 if(!this.updateManager){
8760 this.updateManager = new Roo.UpdateManager(this);
8762 return this.updateManager;
8766 * Disables text selection for this element (normalized across browsers)
8767 * @return {Roo.Element} this
8769 unselectable : function(){
8770 this.dom.unselectable = "on";
8771 this.swallowEvent("selectstart", true);
8772 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8773 this.addClass("x-unselectable");
8778 * Calculates the x, y to center this element on the screen
8779 * @return {Array} The x, y values [x, y]
8781 getCenterXY : function(){
8782 return this.getAlignToXY(document, 'c-c');
8786 * Centers the Element in either the viewport, or another Element.
8787 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8789 center : function(centerIn){
8790 this.alignTo(centerIn || document, 'c-c');
8795 * Tests various css rules/browsers to determine if this element uses a border box
8798 isBorderBox : function(){
8799 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8803 * Return a box {x, y, width, height} that can be used to set another elements
8804 * size/location to match this element.
8805 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8806 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8807 * @return {Object} box An object in the format {x, y, width, height}
8809 getBox : function(contentBox, local){
8814 var left = parseInt(this.getStyle("left"), 10) || 0;
8815 var top = parseInt(this.getStyle("top"), 10) || 0;
8818 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8820 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8822 var l = this.getBorderWidth("l")+this.getPadding("l");
8823 var r = this.getBorderWidth("r")+this.getPadding("r");
8824 var t = this.getBorderWidth("t")+this.getPadding("t");
8825 var b = this.getBorderWidth("b")+this.getPadding("b");
8826 bx = {x: xy[0]+l, y: xy[1]+t, 0: xy[0]+l, 1: xy[1]+t, width: w-(l+r), height: h-(t+b)};
8828 bx.right = bx.x + bx.width;
8829 bx.bottom = bx.y + bx.height;
8834 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8835 for more information about the sides.
8836 * @param {String} sides
8839 getFrameWidth : function(sides, onlyContentBox){
8840 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8844 * Sets the element's box. Use getBox() on another element to get a box obj. If animate is true then width, height, x and y will be animated concurrently.
8845 * @param {Object} box The box to fill {x, y, width, height}
8846 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8847 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8848 * @return {Roo.Element} this
8850 setBox : function(box, adjust, animate){
8851 var w = box.width, h = box.height;
8852 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8853 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8854 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8856 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8861 * Forces the browser to repaint this element
8862 * @return {Roo.Element} this
8864 repaint : function(){
8866 this.addClass("x-repaint");
8867 setTimeout(function(){
8868 Roo.get(dom).removeClass("x-repaint");
8874 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8875 * then it returns the calculated width of the sides (see getPadding)
8876 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8877 * @return {Object/Number}
8879 getMargins : function(side){
8882 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8883 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8884 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8885 right: parseInt(this.getStyle("margin-right"), 10) || 0
8888 return this.addStyles(side, El.margins);
8893 addStyles : function(sides, styles){
8895 for(var i = 0, len = sides.length; i < len; i++){
8896 v = this.getStyle(styles[sides.charAt(i)]);
8898 w = parseInt(v, 10);
8906 * Creates a proxy element of this element
8907 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8908 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8909 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8910 * @return {Roo.Element} The new proxy element
8912 createProxy : function(config, renderTo, matchBox){
8914 renderTo = Roo.getDom(renderTo);
8916 renderTo = document.body;
8918 config = typeof config == "object" ?
8919 config : {tag : "div", cls: config};
8920 var proxy = Roo.DomHelper.append(renderTo, config, true);
8922 proxy.setBox(this.getBox());
8928 * Puts a mask over this element to disable user interaction. Requires core.css.
8929 * This method can only be applied to elements which accept child nodes.
8930 * @param {String} msg (optional) A message to display in the mask
8931 * @param {String} msgCls (optional) A css class to apply to the msg element
8932 * @return {Element} The mask element
8934 mask : function(msg, msgCls)
8936 if(this.getStyle("position") == "static"){
8937 this.setStyle("position", "relative");
8940 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8942 this.addClass("x-masked");
8943 this._mask.setDisplayed(true);
8948 while (dom && dom.style) {
8949 if (!isNaN(parseInt(dom.style.zIndex))) {
8950 z = Math.max(z, parseInt(dom.style.zIndex));
8952 dom = dom.parentNode;
8954 // if we are masking the body - then it hides everything..
8955 if (this.dom == document.body) {
8957 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
8958 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
8961 if(typeof msg == 'string'){
8963 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8965 var mm = this._maskMsg;
8966 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8967 mm.dom.firstChild.innerHTML = msg;
8968 mm.setDisplayed(true);
8970 mm.setStyle('z-index', z + 102);
8972 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8973 this._mask.setHeight(this.getHeight());
8975 this._mask.setStyle('z-index', z + 100);
8981 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8982 * it is cached for reuse.
8984 unmask : function(removeEl){
8986 if(removeEl === true){
8987 this._mask.remove();
8990 this._maskMsg.remove();
8991 delete this._maskMsg;
8994 this._mask.setDisplayed(false);
8996 this._maskMsg.setDisplayed(false);
9000 this.removeClass("x-masked");
9004 * Returns true if this element is masked
9007 isMasked : function(){
9008 return this._mask && this._mask.isVisible();
9012 * Creates an iframe shim for this element to keep selects and other windowed objects from
9014 * @return {Roo.Element} The new shim element
9016 createShim : function(){
9017 var el = document.createElement('iframe');
9018 el.frameBorder = 'no';
9019 el.className = 'roo-shim';
9020 if(Roo.isIE && Roo.isSecure){
9021 el.src = Roo.SSL_SECURE_URL;
9023 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9024 shim.autoBoxAdjust = false;
9029 * Removes this element from the DOM and deletes it from the cache
9031 remove : function(){
9032 if(this.dom.parentNode){
9033 this.dom.parentNode.removeChild(this.dom);
9035 delete El.cache[this.dom.id];
9039 * Sets up event handlers to add and remove a css class when the mouse is over this element
9040 * @param {String} className
9041 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9042 * mouseout events for children elements
9043 * @return {Roo.Element} this
9045 addClassOnOver : function(className, preventFlicker){
9046 this.on("mouseover", function(){
9047 Roo.fly(this, '_internal').addClass(className);
9049 var removeFn = function(e){
9050 if(preventFlicker !== true || !e.within(this, true)){
9051 Roo.fly(this, '_internal').removeClass(className);
9054 this.on("mouseout", removeFn, this.dom);
9059 * Sets up event handlers to add and remove a css class when this element has the focus
9060 * @param {String} className
9061 * @return {Roo.Element} this
9063 addClassOnFocus : function(className){
9064 this.on("focus", function(){
9065 Roo.fly(this, '_internal').addClass(className);
9067 this.on("blur", function(){
9068 Roo.fly(this, '_internal').removeClass(className);
9073 * Sets up event handlers to add and remove a css class when the mouse is down and then up on this element (a click effect)
9074 * @param {String} className
9075 * @return {Roo.Element} this
9077 addClassOnClick : function(className){
9079 this.on("mousedown", function(){
9080 Roo.fly(dom, '_internal').addClass(className);
9081 var d = Roo.get(document);
9082 var fn = function(){
9083 Roo.fly(dom, '_internal').removeClass(className);
9084 d.removeListener("mouseup", fn);
9086 d.on("mouseup", fn);
9092 * Stops the specified event from bubbling and optionally prevents the default action
9093 * @param {String} eventName
9094 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9095 * @return {Roo.Element} this
9097 swallowEvent : function(eventName, preventDefault){
9098 var fn = function(e){
9099 e.stopPropagation();
9104 if(eventName instanceof Array){
9105 for(var i = 0, len = eventName.length; i < len; i++){
9106 this.on(eventName[i], fn);
9110 this.on(eventName, fn);
9117 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9120 * Sizes this element to its parent element's dimensions performing
9121 * neccessary box adjustments.
9122 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9123 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9124 * @return {Roo.Element} this
9126 fitToParent : function(monitorResize, targetParent) {
9127 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9128 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9129 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9132 var p = Roo.get(targetParent || this.dom.parentNode);
9133 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9134 if (monitorResize === true) {
9135 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9136 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9142 * Gets the next sibling, skipping text nodes
9143 * @return {HTMLElement} The next sibling or null
9145 getNextSibling : function(){
9146 var n = this.dom.nextSibling;
9147 while(n && n.nodeType != 1){
9154 * Gets the previous sibling, skipping text nodes
9155 * @return {HTMLElement} The previous sibling or null
9157 getPrevSibling : function(){
9158 var n = this.dom.previousSibling;
9159 while(n && n.nodeType != 1){
9160 n = n.previousSibling;
9167 * Appends the passed element(s) to this element
9168 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9169 * @return {Roo.Element} this
9171 appendChild: function(el){
9178 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9179 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9180 * automatically generated with the specified attributes.
9181 * @param {HTMLElement} insertBefore (optional) a child element of this element
9182 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9183 * @return {Roo.Element} The new child element
9185 createChild: function(config, insertBefore, returnDom){
9186 config = config || {tag:'div'};
9188 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9190 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9194 * Appends this element to the passed element
9195 * @param {String/HTMLElement/Element} el The new parent element
9196 * @return {Roo.Element} this
9198 appendTo: function(el){
9199 el = Roo.getDom(el);
9200 el.appendChild(this.dom);
9205 * Inserts this element before the passed element in the DOM
9206 * @param {String/HTMLElement/Element} el The element to insert before
9207 * @return {Roo.Element} this
9209 insertBefore: function(el){
9210 el = Roo.getDom(el);
9211 el.parentNode.insertBefore(this.dom, el);
9216 * Inserts this element after the passed element in the DOM
9217 * @param {String/HTMLElement/Element} el The element to insert after
9218 * @return {Roo.Element} this
9220 insertAfter: function(el){
9221 el = Roo.getDom(el);
9222 el.parentNode.insertBefore(this.dom, el.nextSibling);
9227 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9228 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9229 * @return {Roo.Element} The new child
9231 insertFirst: function(el, returnDom){
9233 if(typeof el == 'object' && !el.nodeType){ // dh config
9234 return this.createChild(el, this.dom.firstChild, returnDom);
9236 el = Roo.getDom(el);
9237 this.dom.insertBefore(el, this.dom.firstChild);
9238 return !returnDom ? Roo.get(el) : el;
9243 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9244 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9245 * @param {String} where (optional) 'before' or 'after' defaults to before
9246 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9247 * @return {Roo.Element} the inserted Element
9249 insertSibling: function(el, where, returnDom){
9250 where = where ? where.toLowerCase() : 'before';
9252 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9254 if(typeof el == 'object' && !el.nodeType){ // dh config
9255 if(where == 'after' && !this.dom.nextSibling){
9256 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9258 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9262 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9263 where == 'before' ? this.dom : this.dom.nextSibling);
9272 * Creates and wraps this element with another element
9273 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9274 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9275 * @return {HTMLElement/Element} The newly created wrapper element
9277 wrap: function(config, returnDom){
9279 config = {tag: "div"};
9281 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9282 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9287 * Replaces the passed element with this element
9288 * @param {String/HTMLElement/Element} el The element to replace
9289 * @return {Roo.Element} this
9291 replace: function(el){
9293 this.insertBefore(el);
9299 * Inserts an html fragment into this element
9300 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9301 * @param {String} html The HTML fragment
9302 * @param {Boolean} returnEl True to return an Roo.Element
9303 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9305 insertHtml : function(where, html, returnEl){
9306 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9307 return returnEl ? Roo.get(el) : el;
9311 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9312 * @param {Object} o The object with the attributes
9313 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9314 * @return {Roo.Element} this
9316 set : function(o, useSet){
9318 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9320 if(attr == "style" || typeof o[attr] == "function") continue;
9322 el.className = o["cls"];
9324 if(useSet) el.setAttribute(attr, o[attr]);
9325 else el[attr] = o[attr];
9329 Roo.DomHelper.applyStyles(el, o.style);
9335 * Convenience method for constructing a KeyMap
9336 * @param {Number/Array/Object/String} key Either a string with the keys to listen for, the numeric key code, array of key codes or an object with the following options:
9337 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9338 * @param {Function} fn The function to call
9339 * @param {Object} scope (optional) The scope of the function
9340 * @return {Roo.KeyMap} The KeyMap created
9342 addKeyListener : function(key, fn, scope){
9344 if(typeof key != "object" || key instanceof Array){
9360 return new Roo.KeyMap(this, config);
9364 * Creates a KeyMap for this element
9365 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9366 * @return {Roo.KeyMap} The KeyMap created
9368 addKeyMap : function(config){
9369 return new Roo.KeyMap(this, config);
9373 * Returns true if this element is scrollable.
9376 isScrollable : function(){
9378 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9382 * Scrolls this element the specified scroll point. It does NOT do bounds checking so if you scroll to a weird value it will try to do it. For auto bounds checking, use scroll().
9383 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9384 * @param {Number} value The new scroll value
9385 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9386 * @return {Element} this
9389 scrollTo : function(side, value, animate){
9390 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9392 this.dom[prop] = value;
9394 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9395 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9401 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9402 * within this element's scrollable range.
9403 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9404 * @param {Number} distance How far to scroll the element in pixels
9405 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9406 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9407 * was scrolled as far as it could go.
9409 scroll : function(direction, distance, animate){
9410 if(!this.isScrollable()){
9414 var l = el.scrollLeft, t = el.scrollTop;
9415 var w = el.scrollWidth, h = el.scrollHeight;
9416 var cw = el.clientWidth, ch = el.clientHeight;
9417 direction = direction.toLowerCase();
9418 var scrolled = false;
9419 var a = this.preanim(arguments, 2);
9424 var v = Math.min(l + distance, w-cw);
9425 this.scrollTo("left", v, a);
9432 var v = Math.max(l - distance, 0);
9433 this.scrollTo("left", v, a);
9441 var v = Math.max(t - distance, 0);
9442 this.scrollTo("top", v, a);
9450 var v = Math.min(t + distance, h-ch);
9451 this.scrollTo("top", v, a);
9460 * Translates the passed page coordinates into left/top css values for this element
9461 * @param {Number/Array} x The page x or an array containing [x, y]
9462 * @param {Number} y The page y
9463 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9465 translatePoints : function(x, y){
9466 if(typeof x == 'object' || x instanceof Array){
9469 var p = this.getStyle('position');
9470 var o = this.getXY();
9472 var l = parseInt(this.getStyle('left'), 10);
9473 var t = parseInt(this.getStyle('top'), 10);
9476 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9479 t = (p == "relative") ? 0 : this.dom.offsetTop;
9482 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9486 * Returns the current scroll position of the element.
9487 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9489 getScroll : function(){
9490 var d = this.dom, doc = document;
9491 if(d == doc || d == doc.body){
9492 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9493 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9494 return {left: l, top: t};
9496 return {left: d.scrollLeft, top: d.scrollTop};
9501 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9502 * are convert to standard 6 digit hex color.
9503 * @param {String} attr The css attribute
9504 * @param {String} defaultValue The default value to use when a valid color isn't found
9505 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9508 getColor : function(attr, defaultValue, prefix){
9509 var v = this.getStyle(attr);
9510 if(!v || v == "transparent" || v == "inherit") {
9511 return defaultValue;
9513 var color = typeof prefix == "undefined" ? "#" : prefix;
9514 if(v.substr(0, 4) == "rgb("){
9515 var rvs = v.slice(4, v.length -1).split(",");
9516 for(var i = 0; i < 3; i++){
9517 var h = parseInt(rvs[i]).toString(16);
9524 if(v.substr(0, 1) == "#"){
9526 for(var i = 1; i < 4; i++){
9527 var c = v.charAt(i);
9530 }else if(v.length == 7){
9531 color += v.substr(1);
9535 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9539 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9540 * gradient background, rounded corners and a 4-way shadow.
9541 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9542 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9543 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9544 * @return {Roo.Element} this
9546 boxWrap : function(cls){
9547 cls = cls || 'x-box';
9548 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9549 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9554 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9555 * @param {String} namespace The namespace in which to look for the attribute
9556 * @param {String} name The attribute name
9557 * @return {String} The attribute value
9559 getAttributeNS : Roo.isIE ? function(ns, name){
9561 var type = typeof d[ns+":"+name];
9562 if(type != 'undefined' && type != 'unknown'){
9563 return d[ns+":"+name];
9566 } : function(ns, name){
9568 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9573 * Sets or Returns the value the dom attribute value
9574 * @param {String} name The attribute name
9575 * @param {String} value (optional) The value to set the attribute to
9576 * @return {String} The attribute value
9578 attr : function(name){
9579 if (arguments.length > 1) {
9580 this.dom.setAttribute(name, arguments[1]);
9581 return arguments[1];
9583 if (!this.dom.hasAttribute(name)) {
9586 return this.dom.getAttribute(name);
9593 var ep = El.prototype;
9596 * Appends an event handler (Shorthand for addListener)
9597 * @param {String} eventName The type of event to append
9598 * @param {Function} fn The method the event invokes
9599 * @param {Object} scope (optional) The scope (this object) of the fn
9600 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9603 ep.on = ep.addListener;
9605 ep.mon = ep.addListener;
9608 * Removes an event handler from this element (shorthand for removeListener)
9609 * @param {String} eventName the type of event to remove
9610 * @param {Function} fn the method the event invokes
9611 * @return {Roo.Element} this
9614 ep.un = ep.removeListener;
9617 * true to automatically adjust width and height settings for box-model issues (default to true)
9619 ep.autoBoxAdjust = true;
9622 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9625 El.addUnits = function(v, defaultUnit){
9626 if(v === "" || v == "auto"){
9629 if(v === undefined){
9632 if(typeof v == "number" || !El.unitPattern.test(v)){
9633 return v + (defaultUnit || 'px');
9638 // special markup used throughout Roo when box wrapping elements
9639 El.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
9641 * Visibility mode constant - Use visibility to hide element
9647 * Visibility mode constant - Use display to hide element
9653 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9654 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9655 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9667 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9668 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9669 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9670 * @return {Element} The Element object
9673 El.get = function(el){
9675 if(!el){ return null; }
9676 if(typeof el == "string"){ // element id
9677 if(!(elm = document.getElementById(el))){
9680 if(ex = El.cache[el]){
9683 ex = El.cache[el] = new El(elm);
9686 }else if(el.tagName){ // dom element
9690 if(ex = El.cache[id]){
9693 ex = El.cache[id] = new El(el);
9696 }else if(el instanceof El){
9698 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9699 // catch case where it hasn't been appended
9700 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9703 }else if(el.isComposite){
9705 }else if(el instanceof Array){
9706 return El.select(el);
9707 }else if(el == document){
9708 // create a bogus element object representing the document object
9710 var f = function(){};
9711 f.prototype = El.prototype;
9713 docEl.dom = document;
9721 El.uncache = function(el){
9722 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9724 delete El.cache[a[i].id || a[i]];
9730 // Garbage collection - uncache elements/purge listeners on orphaned elements
9731 // so we don't hold a reference and cause the browser to retain them
9732 El.garbageCollect = function(){
9733 if(!Roo.enableGarbageCollector){
9734 clearInterval(El.collectorThread);
9737 for(var eid in El.cache){
9738 var el = El.cache[eid], d = el.dom;
9739 // -------------------------------------------------------
9740 // Determining what is garbage:
9741 // -------------------------------------------------------
9743 // dom node is null, definitely garbage
9744 // -------------------------------------------------------
9746 // no parentNode == direct orphan, definitely garbage
9747 // -------------------------------------------------------
9748 // !d.offsetParent && !document.getElementById(eid)
9749 // display none elements have no offsetParent so we will
9750 // also try to look it up by it's id. However, check
9751 // offsetParent first so we don't do unneeded lookups.
9752 // This enables collection of elements that are not orphans
9753 // directly, but somewhere up the line they have an orphan
9755 // -------------------------------------------------------
9756 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9757 delete El.cache[eid];
9758 if(d && Roo.enableListenerCollection){
9764 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9768 El.Flyweight = function(dom){
9771 El.Flyweight.prototype = El.prototype;
9773 El._flyweights = {};
9775 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9776 * the dom node can be overwritten by other code.
9777 * @param {String/HTMLElement} el The dom node or id
9778 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9779 * prevent conflicts (e.g. internally Roo uses "_internal")
9781 * @return {Element} The shared Element object
9783 El.fly = function(el, named){
9784 named = named || '_global';
9785 el = Roo.getDom(el);
9789 if(!El._flyweights[named]){
9790 El._flyweights[named] = new El.Flyweight();
9792 El._flyweights[named].dom = el;
9793 return El._flyweights[named];
9797 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9798 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9799 * Shorthand of {@link Roo.Element#get}
9800 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9801 * @return {Element} The Element object
9807 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9808 * the dom node can be overwritten by other code.
9809 * Shorthand of {@link Roo.Element#fly}
9810 * @param {String/HTMLElement} el The dom node or id
9811 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9812 * prevent conflicts (e.g. internally Roo uses "_internal")
9814 * @return {Element} The shared Element object
9820 // speedy lookup for elements never to box adjust
9821 var noBoxAdjust = Roo.isStrict ? {
9824 input:1, select:1, textarea:1
9826 if(Roo.isIE || Roo.isGecko){
9827 noBoxAdjust['button'] = 1;
9831 Roo.EventManager.on(window, 'unload', function(){
9833 delete El._flyweights;
9841 Roo.Element.selectorFunction = Roo.DomQuery.select;
9844 Roo.Element.select = function(selector, unique, root){
9846 if(typeof selector == "string"){
9847 els = Roo.Element.selectorFunction(selector, root);
9848 }else if(selector.length !== undefined){
9851 throw "Invalid selector";
9853 if(unique === true){
9854 return new Roo.CompositeElement(els);
9856 return new Roo.CompositeElementLite(els);
9860 * Selects elements based on the passed CSS selector to enable working on them as 1.
9861 * @param {String/Array} selector The CSS selector or an array of elements
9862 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9863 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9864 * @return {CompositeElementLite/CompositeElement}
9868 Roo.select = Roo.Element.select;
9885 * Ext JS Library 1.1.1
9886 * Copyright(c) 2006-2007, Ext JS, LLC.
9888 * Originally Released Under LGPL - original licence link has changed is not relivant.
9891 * <script type="text/javascript">
9896 //Notifies Element that fx methods are available
9897 Roo.enableFx = true;
9901 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9902 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9903 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9904 * Element effects to work.</p><br/>
9906 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9907 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9908 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9909 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9910 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9911 * expected results and should be done with care.</p><br/>
9913 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9914 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9917 ----- -----------------------------
9918 tl The top left corner
9919 t The center of the top edge
9920 tr The top right corner
9921 l The center of the left edge
9922 r The center of the right edge
9923 bl The bottom left corner
9924 b The center of the bottom edge
9925 br The bottom right corner
9927 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9928 * below are common options that can be passed to any Fx method.</b>
9929 * @cfg {Function} callback A function called when the effect is finished
9930 * @cfg {Object} scope The scope of the effect function
9931 * @cfg {String} easing A valid Easing value for the effect
9932 * @cfg {String} afterCls A css class to apply after the effect
9933 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9934 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9935 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9936 * effects that end with the element being visually hidden, ignored otherwise)
9937 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9938 * a function which returns such a specification that will be applied to the Element after the effect finishes
9939 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9940 * @cfg {Boolean} concurrent Whether to allow subsequently-queued effects to run at the same time as the current effect, or to ensure that they run in sequence
9941 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9945 * Slides the element into view. An anchor point can be optionally passed to set the point of
9946 * origin for the slide effect. This function automatically handles wrapping the element with
9947 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9950 // default: slide the element in from the top
9953 // custom: slide the element in from the right with a 2-second duration
9954 el.slideIn('r', { duration: 2 });
9956 // common config options shown with default values
9962 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9963 * @param {Object} options (optional) Object literal with any of the Fx config options
9964 * @return {Roo.Element} The Element
9966 slideIn : function(anchor, o){
9967 var el = this.getFxEl();
9970 el.queueFx(o, function(){
9972 anchor = anchor || "t";
9974 // fix display to visibility
9977 // restore values after effect
9978 var r = this.getFxRestore();
9979 var b = this.getBox();
9980 // fixed size for slide
9984 var wrap = this.fxWrap(r.pos, o, "hidden");
9986 var st = this.dom.style;
9987 st.visibility = "visible";
9988 st.position = "absolute";
9990 // clear out temp styles after slide and unwrap
9991 var after = function(){
9992 el.fxUnwrap(wrap, r.pos, o);
9994 st.height = r.height;
9997 // time to calc the positions
9998 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10000 switch(anchor.toLowerCase()){
10002 wrap.setSize(b.width, 0);
10003 st.left = st.bottom = "0";
10007 wrap.setSize(0, b.height);
10008 st.right = st.top = "0";
10012 wrap.setSize(0, b.height);
10013 wrap.setX(b.right);
10014 st.left = st.top = "0";
10015 a = {width: bw, points: pt};
10018 wrap.setSize(b.width, 0);
10019 wrap.setY(b.bottom);
10020 st.left = st.top = "0";
10021 a = {height: bh, points: pt};
10024 wrap.setSize(0, 0);
10025 st.right = st.bottom = "0";
10026 a = {width: bw, height: bh};
10029 wrap.setSize(0, 0);
10030 wrap.setY(b.y+b.height);
10031 st.right = st.top = "0";
10032 a = {width: bw, height: bh, points: pt};
10035 wrap.setSize(0, 0);
10036 wrap.setXY([b.right, b.bottom]);
10037 st.left = st.top = "0";
10038 a = {width: bw, height: bh, points: pt};
10041 wrap.setSize(0, 0);
10042 wrap.setX(b.x+b.width);
10043 st.left = st.bottom = "0";
10044 a = {width: bw, height: bh, points: pt};
10047 this.dom.style.visibility = "visible";
10050 arguments.callee.anim = wrap.fxanim(a,
10060 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10061 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10062 * 'hidden') but block elements will still take up space in the document. The element must be removed
10063 * from the DOM using the 'remove' config option if desired. This function automatically handles
10064 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10067 // default: slide the element out to the top
10070 // custom: slide the element out to the right with a 2-second duration
10071 el.slideOut('r', { duration: 2 });
10073 // common config options shown with default values
10081 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10082 * @param {Object} options (optional) Object literal with any of the Fx config options
10083 * @return {Roo.Element} The Element
10085 slideOut : function(anchor, o){
10086 var el = this.getFxEl();
10089 el.queueFx(o, function(){
10091 anchor = anchor || "t";
10093 // restore values after effect
10094 var r = this.getFxRestore();
10096 var b = this.getBox();
10097 // fixed size for slide
10101 var wrap = this.fxWrap(r.pos, o, "visible");
10103 var st = this.dom.style;
10104 st.visibility = "visible";
10105 st.position = "absolute";
10109 var after = function(){
10111 el.setDisplayed(false);
10116 el.fxUnwrap(wrap, r.pos, o);
10118 st.width = r.width;
10119 st.height = r.height;
10124 var a, zero = {to: 0};
10125 switch(anchor.toLowerCase()){
10127 st.left = st.bottom = "0";
10128 a = {height: zero};
10131 st.right = st.top = "0";
10135 st.left = st.top = "0";
10136 a = {width: zero, points: {to:[b.right, b.y]}};
10139 st.left = st.top = "0";
10140 a = {height: zero, points: {to:[b.x, b.bottom]}};
10143 st.right = st.bottom = "0";
10144 a = {width: zero, height: zero};
10147 st.right = st.top = "0";
10148 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10151 st.left = st.top = "0";
10152 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10155 st.left = st.bottom = "0";
10156 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10160 arguments.callee.anim = wrap.fxanim(a,
10170 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10171 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10172 * The element must be removed from the DOM using the 'remove' config option if desired.
10178 // common config options shown with default values
10186 * @param {Object} options (optional) Object literal with any of the Fx config options
10187 * @return {Roo.Element} The Element
10189 puff : function(o){
10190 var el = this.getFxEl();
10193 el.queueFx(o, function(){
10194 this.clearOpacity();
10197 // restore values after effect
10198 var r = this.getFxRestore();
10199 var st = this.dom.style;
10201 var after = function(){
10203 el.setDisplayed(false);
10210 el.setPositioning(r.pos);
10211 st.width = r.width;
10212 st.height = r.height;
10217 var width = this.getWidth();
10218 var height = this.getHeight();
10220 arguments.callee.anim = this.fxanim({
10221 width : {to: this.adjustWidth(width * 2)},
10222 height : {to: this.adjustHeight(height * 2)},
10223 points : {by: [-(width * .5), -(height * .5)]},
10225 fontSize: {to:200, unit: "%"}
10236 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10237 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10238 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10244 // all config options shown with default values
10252 * @param {Object} options (optional) Object literal with any of the Fx config options
10253 * @return {Roo.Element} The Element
10255 switchOff : function(o){
10256 var el = this.getFxEl();
10259 el.queueFx(o, function(){
10260 this.clearOpacity();
10263 // restore values after effect
10264 var r = this.getFxRestore();
10265 var st = this.dom.style;
10267 var after = function(){
10269 el.setDisplayed(false);
10275 el.setPositioning(r.pos);
10276 st.width = r.width;
10277 st.height = r.height;
10282 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10283 this.clearOpacity();
10287 points:{by:[0, this.getHeight() * .5]}
10288 }, o, 'motion', 0.3, 'easeIn', after);
10289 }).defer(100, this);
10296 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10297 * changed using the "attr" config option) and then fading back to the original color. If no original
10298 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10301 // default: highlight background to yellow
10304 // custom: highlight foreground text to blue for 2 seconds
10305 el.highlight("0000ff", { attr: 'color', duration: 2 });
10307 // common config options shown with default values
10308 el.highlight("ffff9c", {
10309 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10310 endColor: (current color) or "ffffff",
10315 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10316 * @param {Object} options (optional) Object literal with any of the Fx config options
10317 * @return {Roo.Element} The Element
10319 highlight : function(color, o){
10320 var el = this.getFxEl();
10323 el.queueFx(o, function(){
10324 color = color || "ffff9c";
10325 attr = o.attr || "backgroundColor";
10327 this.clearOpacity();
10330 var origColor = this.getColor(attr);
10331 var restoreColor = this.dom.style[attr];
10332 endColor = (o.endColor || origColor) || "ffffff";
10334 var after = function(){
10335 el.dom.style[attr] = restoreColor;
10340 a[attr] = {from: color, to: endColor};
10341 arguments.callee.anim = this.fxanim(a,
10351 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10354 // default: a single light blue ripple
10357 // custom: 3 red ripples lasting 3 seconds total
10358 el.frame("ff0000", 3, { duration: 3 });
10360 // common config options shown with default values
10361 el.frame("C3DAF9", 1, {
10362 duration: 1 //duration of entire animation (not each individual ripple)
10363 // Note: Easing is not configurable and will be ignored if included
10366 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10367 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10368 * @param {Object} options (optional) Object literal with any of the Fx config options
10369 * @return {Roo.Element} The Element
10371 frame : function(color, count, o){
10372 var el = this.getFxEl();
10375 el.queueFx(o, function(){
10376 color = color || "#C3DAF9";
10377 if(color.length == 6){
10378 color = "#" + color;
10380 count = count || 1;
10381 duration = o.duration || 1;
10384 var b = this.getBox();
10385 var animFn = function(){
10386 var proxy = this.createProxy({
10389 visbility:"hidden",
10390 position:"absolute",
10391 "z-index":"35000", // yee haw
10392 border:"0px solid " + color
10395 var scale = Roo.isBorderBox ? 2 : 1;
10397 top:{from:b.y, to:b.y - 20},
10398 left:{from:b.x, to:b.x - 20},
10399 borderWidth:{from:0, to:10},
10400 opacity:{from:1, to:0},
10401 height:{from:b.height, to:(b.height + (20*scale))},
10402 width:{from:b.width, to:(b.width + (20*scale))}
10403 }, duration, function(){
10407 animFn.defer((duration/2)*1000, this);
10418 * Creates a pause before any subsequent queued effects begin. If there are
10419 * no effects queued after the pause it will have no effect.
10424 * @param {Number} seconds The length of time to pause (in seconds)
10425 * @return {Roo.Element} The Element
10427 pause : function(seconds){
10428 var el = this.getFxEl();
10431 el.queueFx(o, function(){
10432 setTimeout(function(){
10434 }, seconds * 1000);
10440 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10441 * using the "endOpacity" config option.
10444 // default: fade in from opacity 0 to 100%
10447 // custom: fade in from opacity 0 to 75% over 2 seconds
10448 el.fadeIn({ endOpacity: .75, duration: 2});
10450 // common config options shown with default values
10452 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10457 * @param {Object} options (optional) Object literal with any of the Fx config options
10458 * @return {Roo.Element} The Element
10460 fadeIn : function(o){
10461 var el = this.getFxEl();
10463 el.queueFx(o, function(){
10464 this.setOpacity(0);
10466 this.dom.style.visibility = 'visible';
10467 var to = o.endOpacity || 1;
10468 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10469 o, null, .5, "easeOut", function(){
10471 this.clearOpacity();
10480 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10481 * using the "endOpacity" config option.
10484 // default: fade out from the element's current opacity to 0
10487 // custom: fade out from the element's current opacity to 25% over 2 seconds
10488 el.fadeOut({ endOpacity: .25, duration: 2});
10490 // common config options shown with default values
10492 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10499 * @param {Object} options (optional) Object literal with any of the Fx config options
10500 * @return {Roo.Element} The Element
10502 fadeOut : function(o){
10503 var el = this.getFxEl();
10505 el.queueFx(o, function(){
10506 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10507 o, null, .5, "easeOut", function(){
10508 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10509 this.dom.style.display = "none";
10511 this.dom.style.visibility = "hidden";
10513 this.clearOpacity();
10521 * Animates the transition of an element's dimensions from a starting height/width
10522 * to an ending height/width.
10525 // change height and width to 100x100 pixels
10526 el.scale(100, 100);
10528 // common config options shown with default values. The height and width will default to
10529 // the element's existing values if passed as null.
10532 [element's height], {
10537 * @param {Number} width The new width (pass undefined to keep the original width)
10538 * @param {Number} height The new height (pass undefined to keep the original height)
10539 * @param {Object} options (optional) Object literal with any of the Fx config options
10540 * @return {Roo.Element} The Element
10542 scale : function(w, h, o){
10543 this.shift(Roo.apply({}, o, {
10551 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10552 * Any of these properties not specified in the config object will not be changed. This effect
10553 * requires that at least one new dimension, position or opacity setting must be passed in on
10554 * the config object in order for the function to have any effect.
10557 // slide the element horizontally to x position 200 while changing the height and opacity
10558 el.shift({ x: 200, height: 50, opacity: .8 });
10560 // common config options shown with default values.
10562 width: [element's width],
10563 height: [element's height],
10564 x: [element's x position],
10565 y: [element's y position],
10566 opacity: [element's opacity],
10571 * @param {Object} options Object literal with any of the Fx config options
10572 * @return {Roo.Element} The Element
10574 shift : function(o){
10575 var el = this.getFxEl();
10577 el.queueFx(o, function(){
10578 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10579 if(w !== undefined){
10580 a.width = {to: this.adjustWidth(w)};
10582 if(h !== undefined){
10583 a.height = {to: this.adjustHeight(h)};
10585 if(x !== undefined || y !== undefined){
10587 x !== undefined ? x : this.getX(),
10588 y !== undefined ? y : this.getY()
10591 if(op !== undefined){
10592 a.opacity = {to: op};
10594 if(o.xy !== undefined){
10595 a.points = {to: o.xy};
10597 arguments.callee.anim = this.fxanim(a,
10598 o, 'motion', .35, "easeOut", function(){
10606 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10607 * ending point of the effect.
10610 // default: slide the element downward while fading out
10613 // custom: slide the element out to the right with a 2-second duration
10614 el.ghost('r', { duration: 2 });
10616 // common config options shown with default values
10624 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10625 * @param {Object} options (optional) Object literal with any of the Fx config options
10626 * @return {Roo.Element} The Element
10628 ghost : function(anchor, o){
10629 var el = this.getFxEl();
10632 el.queueFx(o, function(){
10633 anchor = anchor || "b";
10635 // restore values after effect
10636 var r = this.getFxRestore();
10637 var w = this.getWidth(),
10638 h = this.getHeight();
10640 var st = this.dom.style;
10642 var after = function(){
10644 el.setDisplayed(false);
10650 el.setPositioning(r.pos);
10651 st.width = r.width;
10652 st.height = r.height;
10657 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10658 switch(anchor.toLowerCase()){
10685 arguments.callee.anim = this.fxanim(a,
10695 * Ensures that all effects queued after syncFx is called on the element are
10696 * run concurrently. This is the opposite of {@link #sequenceFx}.
10697 * @return {Roo.Element} The Element
10699 syncFx : function(){
10700 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10709 * Ensures that all effects queued after sequenceFx is called on the element are
10710 * run in sequence. This is the opposite of {@link #syncFx}.
10711 * @return {Roo.Element} The Element
10713 sequenceFx : function(){
10714 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10716 concurrent : false,
10723 nextFx : function(){
10724 var ef = this.fxQueue[0];
10731 * Returns true if the element has any effects actively running or queued, else returns false.
10732 * @return {Boolean} True if element has active effects, else false
10734 hasActiveFx : function(){
10735 return this.fxQueue && this.fxQueue[0];
10739 * Stops any running effects and clears the element's internal effects queue if it contains
10740 * any additional effects that haven't started yet.
10741 * @return {Roo.Element} The Element
10743 stopFx : function(){
10744 if(this.hasActiveFx()){
10745 var cur = this.fxQueue[0];
10746 if(cur && cur.anim && cur.anim.isAnimated()){
10747 this.fxQueue = [cur]; // clear out others
10748 cur.anim.stop(true);
10755 beforeFx : function(o){
10756 if(this.hasActiveFx() && !o.concurrent){
10767 * Returns true if the element is currently blocking so that no other effect can be queued
10768 * until this effect is finished, else returns false if blocking is not set. This is commonly
10769 * used to ensure that an effect initiated by a user action runs to completion prior to the
10770 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10771 * @return {Boolean} True if blocking, else false
10773 hasFxBlock : function(){
10774 var q = this.fxQueue;
10775 return q && q[0] && q[0].block;
10779 queueFx : function(o, fn){
10783 if(!this.hasFxBlock()){
10784 Roo.applyIf(o, this.fxDefaults);
10786 var run = this.beforeFx(o);
10787 fn.block = o.block;
10788 this.fxQueue.push(fn);
10800 fxWrap : function(pos, o, vis){
10802 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10805 wrapXY = this.getXY();
10807 var div = document.createElement("div");
10808 div.style.visibility = vis;
10809 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10810 wrap.setPositioning(pos);
10811 if(wrap.getStyle("position") == "static"){
10812 wrap.position("relative");
10814 this.clearPositioning('auto');
10816 wrap.dom.appendChild(this.dom);
10818 wrap.setXY(wrapXY);
10825 fxUnwrap : function(wrap, pos, o){
10826 this.clearPositioning();
10827 this.setPositioning(pos);
10829 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10835 getFxRestore : function(){
10836 var st = this.dom.style;
10837 return {pos: this.getPositioning(), width: st.width, height : st.height};
10841 afterFx : function(o){
10843 this.applyStyles(o.afterStyle);
10846 this.addClass(o.afterCls);
10848 if(o.remove === true){
10851 Roo.callback(o.callback, o.scope, [this]);
10853 this.fxQueue.shift();
10859 getFxEl : function(){ // support for composite element fx
10860 return Roo.get(this.dom);
10864 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10865 animType = animType || 'run';
10867 var anim = Roo.lib.Anim[animType](
10869 (opt.duration || defaultDur) || .35,
10870 (opt.easing || defaultEase) || 'easeOut',
10872 Roo.callback(cb, this);
10881 // backwords compat
10882 Roo.Fx.resize = Roo.Fx.scale;
10884 //When included, Roo.Fx is automatically applied to Element so that all basic
10885 //effects are available directly via the Element API
10886 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10888 * Ext JS Library 1.1.1
10889 * Copyright(c) 2006-2007, Ext JS, LLC.
10891 * Originally Released Under LGPL - original licence link has changed is not relivant.
10894 * <script type="text/javascript">
10899 * @class Roo.CompositeElement
10900 * Standard composite class. Creates a Roo.Element for every element in the collection.
10902 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10903 * actions will be performed on all the elements in this collection.</b>
10905 * All methods return <i>this</i> and can be chained.
10907 var els = Roo.select("#some-el div.some-class", true);
10908 // or select directly from an existing element
10909 var el = Roo.get('some-el');
10910 el.select('div.some-class', true);
10912 els.setWidth(100); // all elements become 100 width
10913 els.hide(true); // all elements fade out and hide
10915 els.setWidth(100).hide(true);
10918 Roo.CompositeElement = function(els){
10919 this.elements = [];
10920 this.addElements(els);
10922 Roo.CompositeElement.prototype = {
10924 addElements : function(els){
10925 if(!els) return this;
10926 if(typeof els == "string"){
10927 els = Roo.Element.selectorFunction(els);
10929 var yels = this.elements;
10930 var index = yels.length-1;
10931 for(var i = 0, len = els.length; i < len; i++) {
10932 yels[++index] = Roo.get(els[i]);
10938 * Clears this composite and adds the elements returned by the passed selector.
10939 * @param {String/Array} els A string CSS selector, an array of elements or an element
10940 * @return {CompositeElement} this
10942 fill : function(els){
10943 this.elements = [];
10949 * Filters this composite to only elements that match the passed selector.
10950 * @param {String} selector A string CSS selector
10951 * @return {CompositeElement} this
10953 filter : function(selector){
10955 this.each(function(el){
10956 if(el.is(selector)){
10957 els[els.length] = el.dom;
10964 invoke : function(fn, args){
10965 var els = this.elements;
10966 for(var i = 0, len = els.length; i < len; i++) {
10967 Roo.Element.prototype[fn].apply(els[i], args);
10972 * Adds elements to this composite.
10973 * @param {String/Array} els A string CSS selector, an array of elements or an element
10974 * @return {CompositeElement} this
10976 add : function(els){
10977 if(typeof els == "string"){
10978 this.addElements(Roo.Element.selectorFunction(els));
10979 }else if(els.length !== undefined){
10980 this.addElements(els);
10982 this.addElements([els]);
10987 * Calls the passed function passing (el, this, index) for each element in this composite.
10988 * @param {Function} fn The function to call
10989 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10990 * @return {CompositeElement} this
10992 each : function(fn, scope){
10993 var els = this.elements;
10994 for(var i = 0, len = els.length; i < len; i++){
10995 if(fn.call(scope || els[i], els[i], this, i) === false) {
11003 * Returns the Element object at the specified index
11004 * @param {Number} index
11005 * @return {Roo.Element}
11007 item : function(index){
11008 return this.elements[index] || null;
11012 * Returns the first Element
11013 * @return {Roo.Element}
11015 first : function(){
11016 return this.item(0);
11020 * Returns the last Element
11021 * @return {Roo.Element}
11024 return this.item(this.elements.length-1);
11028 * Returns the number of elements in this composite
11031 getCount : function(){
11032 return this.elements.length;
11036 * Returns true if this composite contains the passed element
11039 contains : function(el){
11040 return this.indexOf(el) !== -1;
11044 * Returns true if this composite contains the passed element
11047 indexOf : function(el){
11048 return this.elements.indexOf(Roo.get(el));
11053 * Removes the specified element(s).
11054 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11055 * or an array of any of those.
11056 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11057 * @return {CompositeElement} this
11059 removeElement : function(el, removeDom){
11060 if(el instanceof Array){
11061 for(var i = 0, len = el.length; i < len; i++){
11062 this.removeElement(el[i]);
11066 var index = typeof el == 'number' ? el : this.indexOf(el);
11069 var d = this.elements[index];
11073 d.parentNode.removeChild(d);
11076 this.elements.splice(index, 1);
11082 * Replaces the specified element with the passed element.
11083 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11085 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11086 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11087 * @return {CompositeElement} this
11089 replaceElement : function(el, replacement, domReplace){
11090 var index = typeof el == 'number' ? el : this.indexOf(el);
11093 this.elements[index].replaceWith(replacement);
11095 this.elements.splice(index, 1, Roo.get(replacement))
11102 * Removes all elements.
11104 clear : function(){
11105 this.elements = [];
11109 Roo.CompositeElement.createCall = function(proto, fnName){
11110 if(!proto[fnName]){
11111 proto[fnName] = function(){
11112 return this.invoke(fnName, arguments);
11116 for(var fnName in Roo.Element.prototype){
11117 if(typeof Roo.Element.prototype[fnName] == "function"){
11118 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11124 * Ext JS Library 1.1.1
11125 * Copyright(c) 2006-2007, Ext JS, LLC.
11127 * Originally Released Under LGPL - original licence link has changed is not relivant.
11130 * <script type="text/javascript">
11134 * @class Roo.CompositeElementLite
11135 * @extends Roo.CompositeElement
11136 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11138 var els = Roo.select("#some-el div.some-class");
11139 // or select directly from an existing element
11140 var el = Roo.get('some-el');
11141 el.select('div.some-class');
11143 els.setWidth(100); // all elements become 100 width
11144 els.hide(true); // all elements fade out and hide
11146 els.setWidth(100).hide(true);
11147 </code></pre><br><br>
11148 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11149 * actions will be performed on all the elements in this collection.</b>
11151 Roo.CompositeElementLite = function(els){
11152 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11153 this.el = new Roo.Element.Flyweight();
11155 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11156 addElements : function(els){
11158 if(els instanceof Array){
11159 this.elements = this.elements.concat(els);
11161 var yels = this.elements;
11162 var index = yels.length-1;
11163 for(var i = 0, len = els.length; i < len; i++) {
11164 yels[++index] = els[i];
11170 invoke : function(fn, args){
11171 var els = this.elements;
11173 for(var i = 0, len = els.length; i < len; i++) {
11175 Roo.Element.prototype[fn].apply(el, args);
11180 * Returns a flyweight Element of the dom element object at the specified index
11181 * @param {Number} index
11182 * @return {Roo.Element}
11184 item : function(index){
11185 if(!this.elements[index]){
11188 this.el.dom = this.elements[index];
11192 // fixes scope with flyweight
11193 addListener : function(eventName, handler, scope, opt){
11194 var els = this.elements;
11195 for(var i = 0, len = els.length; i < len; i++) {
11196 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11202 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11203 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11204 * a reference to the dom node, use el.dom.</b>
11205 * @param {Function} fn The function to call
11206 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11207 * @return {CompositeElement} this
11209 each : function(fn, scope){
11210 var els = this.elements;
11212 for(var i = 0, len = els.length; i < len; i++){
11214 if(fn.call(scope || el, el, this, i) === false){
11221 indexOf : function(el){
11222 return this.elements.indexOf(Roo.getDom(el));
11225 replaceElement : function(el, replacement, domReplace){
11226 var index = typeof el == 'number' ? el : this.indexOf(el);
11228 replacement = Roo.getDom(replacement);
11230 var d = this.elements[index];
11231 d.parentNode.insertBefore(replacement, d);
11232 d.parentNode.removeChild(d);
11234 this.elements.splice(index, 1, replacement);
11239 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11243 * Ext JS Library 1.1.1
11244 * Copyright(c) 2006-2007, Ext JS, LLC.
11246 * Originally Released Under LGPL - original licence link has changed is not relivant.
11249 * <script type="text/javascript">
11255 * @class Roo.data.Connection
11256 * @extends Roo.util.Observable
11257 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11258 * either to a configured URL, or to a URL specified at request time.<br><br>
11260 * Requests made by this class are asynchronous, and will return immediately. No data from
11261 * the server will be available to the statement immediately following the {@link #request} call.
11262 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11264 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11265 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11266 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11267 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11268 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11269 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11270 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11271 * standard DOM methods.
11273 * @param {Object} config a configuration object.
11275 Roo.data.Connection = function(config){
11276 Roo.apply(this, config);
11279 * @event beforerequest
11280 * Fires before a network request is made to retrieve a data object.
11281 * @param {Connection} conn This Connection object.
11282 * @param {Object} options The options config object passed to the {@link #request} method.
11284 "beforerequest" : true,
11286 * @event requestcomplete
11287 * Fires if the request was successfully completed.
11288 * @param {Connection} conn This Connection object.
11289 * @param {Object} response The XHR object containing the response data.
11290 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11291 * @param {Object} options The options config object passed to the {@link #request} method.
11293 "requestcomplete" : true,
11295 * @event requestexception
11296 * Fires if an error HTTP status was returned from the server.
11297 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11298 * @param {Connection} conn This Connection object.
11299 * @param {Object} response The XHR object containing the response data.
11300 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11301 * @param {Object} options The options config object passed to the {@link #request} method.
11303 "requestexception" : true
11305 Roo.data.Connection.superclass.constructor.call(this);
11308 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11310 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11313 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11314 * extra parameters to each request made by this object. (defaults to undefined)
11317 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11318 * to each request made by this object. (defaults to undefined)
11321 * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11324 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11328 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11334 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11337 disableCaching: true,
11340 * Sends an HTTP request to a remote server.
11341 * @param {Object} options An object which may contain the following properties:<ul>
11342 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11343 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11344 * request, a url encoded string or a function to call to get either.</li>
11345 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11346 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11347 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11348 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11349 * <li>options {Object} The parameter to the request call.</li>
11350 * <li>success {Boolean} True if the request succeeded.</li>
11351 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11353 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11354 * The callback is passed the following parameters:<ul>
11355 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11356 * <li>options {Object} The parameter to the request call.</li>
11358 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11359 * The callback is passed the following parameters:<ul>
11360 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11361 * <li>options {Object} The parameter to the request call.</li>
11363 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11364 * for the callback function. Defaults to the browser window.</li>
11365 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11366 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11367 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11368 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11369 * params for the post data. Any params will be appended to the URL.</li>
11370 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11372 * @return {Number} transactionId
11374 request : function(o){
11375 if(this.fireEvent("beforerequest", this, o) !== false){
11378 if(typeof p == "function"){
11379 p = p.call(o.scope||window, o);
11381 if(typeof p == "object"){
11382 p = Roo.urlEncode(o.params);
11384 if(this.extraParams){
11385 var extras = Roo.urlEncode(this.extraParams);
11386 p = p ? (p + '&' + extras) : extras;
11389 var url = o.url || this.url;
11390 if(typeof url == 'function'){
11391 url = url.call(o.scope||window, o);
11395 var form = Roo.getDom(o.form);
11396 url = url || form.action;
11398 var enctype = form.getAttribute("enctype");
11399 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11400 return this.doFormUpload(o, p, url);
11402 var f = Roo.lib.Ajax.serializeForm(form);
11403 p = p ? (p + '&' + f) : f;
11406 var hs = o.headers;
11407 if(this.defaultHeaders){
11408 hs = Roo.apply(hs || {}, this.defaultHeaders);
11415 success: this.handleResponse,
11416 failure: this.handleFailure,
11418 argument: {options: o},
11419 timeout : o.timeout || this.timeout
11422 var method = o.method||this.method||(p ? "POST" : "GET");
11424 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11425 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11428 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11432 }else if(this.autoAbort !== false){
11436 if((method == 'GET' && p) || o.xmlData){
11437 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11440 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11441 return this.transId;
11443 Roo.callback(o.callback, o.scope, [o, null, null]);
11449 * Determine whether this object has a request outstanding.
11450 * @param {Number} transactionId (Optional) defaults to the last transaction
11451 * @return {Boolean} True if there is an outstanding request.
11453 isLoading : function(transId){
11455 return Roo.lib.Ajax.isCallInProgress(transId);
11457 return this.transId ? true : false;
11462 * Aborts any outstanding request.
11463 * @param {Number} transactionId (Optional) defaults to the last transaction
11465 abort : function(transId){
11466 if(transId || this.isLoading()){
11467 Roo.lib.Ajax.abort(transId || this.transId);
11472 handleResponse : function(response){
11473 this.transId = false;
11474 var options = response.argument.options;
11475 response.argument = options ? options.argument : null;
11476 this.fireEvent("requestcomplete", this, response, options);
11477 Roo.callback(options.success, options.scope, [response, options]);
11478 Roo.callback(options.callback, options.scope, [options, true, response]);
11482 handleFailure : function(response, e){
11483 this.transId = false;
11484 var options = response.argument.options;
11485 response.argument = options ? options.argument : null;
11486 this.fireEvent("requestexception", this, response, options, e);
11487 Roo.callback(options.failure, options.scope, [response, options]);
11488 Roo.callback(options.callback, options.scope, [options, false, response]);
11492 doFormUpload : function(o, ps, url){
11494 var frame = document.createElement('iframe');
11497 frame.className = 'x-hidden';
11499 frame.src = Roo.SSL_SECURE_URL;
11501 document.body.appendChild(frame);
11504 document.frames[id].name = id;
11507 var form = Roo.getDom(o.form);
11509 form.method = 'POST';
11510 form.enctype = form.encoding = 'multipart/form-data';
11516 if(ps){ // add dynamic params
11518 ps = Roo.urlDecode(ps, false);
11520 if(ps.hasOwnProperty(k)){
11521 hd = document.createElement('input');
11522 hd.type = 'hidden';
11525 form.appendChild(hd);
11532 var r = { // bogus response object
11537 r.argument = o ? o.argument : null;
11542 doc = frame.contentWindow.document;
11544 doc = (frame.contentDocument || window.frames[id].document);
11546 if(doc && doc.body){
11547 r.responseText = doc.body.innerHTML;
11549 if(doc && doc.XMLDocument){
11550 r.responseXML = doc.XMLDocument;
11552 r.responseXML = doc;
11559 Roo.EventManager.removeListener(frame, 'load', cb, this);
11561 this.fireEvent("requestcomplete", this, r, o);
11562 Roo.callback(o.success, o.scope, [r, o]);
11563 Roo.callback(o.callback, o.scope, [o, true, r]);
11565 setTimeout(function(){document.body.removeChild(frame);}, 100);
11568 Roo.EventManager.on(frame, 'load', cb, this);
11571 if(hiddens){ // remove dynamic params
11572 for(var i = 0, len = hiddens.length; i < len; i++){
11573 form.removeChild(hiddens[i]);
11580 * Ext JS Library 1.1.1
11581 * Copyright(c) 2006-2007, Ext JS, LLC.
11583 * Originally Released Under LGPL - original licence link has changed is not relivant.
11586 * <script type="text/javascript">
11590 * Global Ajax request class.
11593 * @extends Roo.data.Connection
11596 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11597 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11598 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11599 * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11600 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11601 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11602 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11604 Roo.Ajax = new Roo.data.Connection({
11613 * Serialize the passed form into a url encoded string
11615 * @param {String/HTMLElement} form
11618 serializeForm : function(form){
11619 return Roo.lib.Ajax.serializeForm(form);
11623 * Ext JS Library 1.1.1
11624 * Copyright(c) 2006-2007, Ext JS, LLC.
11626 * Originally Released Under LGPL - original licence link has changed is not relivant.
11629 * <script type="text/javascript">
11634 * @class Roo.UpdateManager
11635 * @extends Roo.util.Observable
11636 * Provides AJAX-style update for Element object.<br><br>
11639 * // Get it from a Roo.Element object
11640 * var el = Roo.get("foo");
11641 * var mgr = el.getUpdateManager();
11642 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11644 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11646 * // or directly (returns the same UpdateManager instance)
11647 * var mgr = new Roo.UpdateManager("myElementId");
11648 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11649 * mgr.on("update", myFcnNeedsToKnow);
11651 // short handed call directly from the element object
11652 Roo.get("foo").load({
11656 text: "Loading Foo..."
11660 * Create new UpdateManager directly.
11661 * @param {String/HTMLElement/Roo.Element} el The element to update
11662 * @param {Boolean} forceNew (optional) By default the constructor checks to see if the passed element already has an UpdateManager and if it does it returns the same instance. This will skip that check (useful for extending this class).
11664 Roo.UpdateManager = function(el, forceNew){
11666 if(!forceNew && el.updateManager){
11667 return el.updateManager;
11670 * The Element object
11671 * @type Roo.Element
11675 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11678 this.defaultUrl = null;
11682 * @event beforeupdate
11683 * Fired before an update is made, return false from your handler and the update is cancelled.
11684 * @param {Roo.Element} el
11685 * @param {String/Object/Function} url
11686 * @param {String/Object} params
11688 "beforeupdate": true,
11691 * Fired after successful update is made.
11692 * @param {Roo.Element} el
11693 * @param {Object} oResponseObject The response Object
11698 * Fired on update failure.
11699 * @param {Roo.Element} el
11700 * @param {Object} oResponseObject The response Object
11704 var d = Roo.UpdateManager.defaults;
11706 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11709 this.sslBlankUrl = d.sslBlankUrl;
11711 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11714 this.disableCaching = d.disableCaching;
11716 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11719 this.indicatorText = d.indicatorText;
11721 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11724 this.showLoadIndicator = d.showLoadIndicator;
11726 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11729 this.timeout = d.timeout;
11732 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11735 this.loadScripts = d.loadScripts;
11738 * Transaction object of current executing transaction
11740 this.transaction = null;
11745 this.autoRefreshProcId = null;
11747 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11750 this.refreshDelegate = this.refresh.createDelegate(this);
11752 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11755 this.updateDelegate = this.update.createDelegate(this);
11757 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11760 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11764 this.successDelegate = this.processSuccess.createDelegate(this);
11768 this.failureDelegate = this.processFailure.createDelegate(this);
11770 if(!this.renderer){
11772 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11774 this.renderer = new Roo.UpdateManager.BasicRenderer();
11777 Roo.UpdateManager.superclass.constructor.call(this);
11780 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11782 * Get the Element this UpdateManager is bound to
11783 * @return {Roo.Element} The element
11785 getEl : function(){
11789 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11790 * @param {Object/String/Function} url The url for this request or a function to call to get the url or a config object containing any of the following options:
11793 url: "your-url.php",<br/>
11794 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11795 callback: yourFunction,<br/>
11796 scope: yourObject, //(optional scope) <br/>
11797 discardUrl: false, <br/>
11798 nocache: false,<br/>
11799 text: "Loading...",<br/>
11801 scripts: false<br/>
11804 * The only required property is url. The optional properties nocache, text and scripts
11805 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11806 * @param {String/Object} params (optional) The parameters to pass as either a url encoded string "param1=1&param2=2" or an object {param1: 1, param2: 2}
11807 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11808 * @param {Boolean} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used url. If true, it will not store the url.
11810 update : function(url, params, callback, discardUrl){
11811 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11812 var method = this.method,
11814 if(typeof url == "object"){ // must be config object
11817 params = params || cfg.params;
11818 callback = callback || cfg.callback;
11819 discardUrl = discardUrl || cfg.discardUrl;
11820 if(callback && cfg.scope){
11821 callback = callback.createDelegate(cfg.scope);
11823 if(typeof cfg.method != "undefined"){method = cfg.method;};
11824 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11825 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11826 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11827 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11829 this.showLoading();
11831 this.defaultUrl = url;
11833 if(typeof url == "function"){
11834 url = url.call(this);
11837 method = method || (params ? "POST" : "GET");
11838 if(method == "GET"){
11839 url = this.prepareUrl(url);
11842 var o = Roo.apply(cfg ||{}, {
11845 success: this.successDelegate,
11846 failure: this.failureDelegate,
11847 callback: undefined,
11848 timeout: (this.timeout*1000),
11849 argument: {"url": url, "form": null, "callback": callback, "params": params}
11851 Roo.log("updated manager called with timeout of " + o.timeout);
11852 this.transaction = Roo.Ajax.request(o);
11857 * Performs an async form post, updating this element with the response. If the form has the attribute enctype="multipart/form-data", it assumes it's a file upload.
11858 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11859 * @param {String/HTMLElement} form The form Id or form element
11860 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11861 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11862 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11864 formUpdate : function(form, url, reset, callback){
11865 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11866 if(typeof url == "function"){
11867 url = url.call(this);
11869 form = Roo.getDom(form);
11870 this.transaction = Roo.Ajax.request({
11873 success: this.successDelegate,
11874 failure: this.failureDelegate,
11875 timeout: (this.timeout*1000),
11876 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11878 this.showLoading.defer(1, this);
11883 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11884 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11886 refresh : function(callback){
11887 if(this.defaultUrl == null){
11890 this.update(this.defaultUrl, null, callback, true);
11894 * Set this element to auto refresh.
11895 * @param {Number} interval How often to update (in seconds).
11896 * @param {String/Function} url (optional) The url for this request or a function to call to get the url (Defaults to the last used url)
11897 * @param {String/Object} params (optional) The parameters to pass as either a url encoded string "¶m1=1¶m2=2" or as an object {param1: 1, param2: 2}
11898 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11899 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11901 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11903 this.update(url || this.defaultUrl, params, callback, true);
11905 if(this.autoRefreshProcId){
11906 clearInterval(this.autoRefreshProcId);
11908 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11912 * Stop auto refresh on this element.
11914 stopAutoRefresh : function(){
11915 if(this.autoRefreshProcId){
11916 clearInterval(this.autoRefreshProcId);
11917 delete this.autoRefreshProcId;
11921 isAutoRefreshing : function(){
11922 return this.autoRefreshProcId ? true : false;
11925 * Called to update the element to "Loading" state. Override to perform custom action.
11927 showLoading : function(){
11928 if(this.showLoadIndicator){
11929 this.el.update(this.indicatorText);
11934 * Adds unique parameter to query string if disableCaching = true
11937 prepareUrl : function(url){
11938 if(this.disableCaching){
11939 var append = "_dc=" + (new Date().getTime());
11940 if(url.indexOf("?") !== -1){
11941 url += "&" + append;
11943 url += "?" + append;
11952 processSuccess : function(response){
11953 this.transaction = null;
11954 if(response.argument.form && response.argument.reset){
11955 try{ // put in try/catch since some older FF releases had problems with this
11956 response.argument.form.reset();
11959 if(this.loadScripts){
11960 this.renderer.render(this.el, response, this,
11961 this.updateComplete.createDelegate(this, [response]));
11963 this.renderer.render(this.el, response, this);
11964 this.updateComplete(response);
11968 updateComplete : function(response){
11969 this.fireEvent("update", this.el, response);
11970 if(typeof response.argument.callback == "function"){
11971 response.argument.callback(this.el, true, response);
11978 processFailure : function(response){
11979 this.transaction = null;
11980 this.fireEvent("failure", this.el, response);
11981 if(typeof response.argument.callback == "function"){
11982 response.argument.callback(this.el, false, response);
11987 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11988 * @param {Object} renderer The object implementing the render() method
11990 setRenderer : function(renderer){
11991 this.renderer = renderer;
11994 getRenderer : function(){
11995 return this.renderer;
11999 * Set the defaultUrl used for updates
12000 * @param {String/Function} defaultUrl The url or a function to call to get the url
12002 setDefaultUrl : function(defaultUrl){
12003 this.defaultUrl = defaultUrl;
12007 * Aborts the executing transaction
12009 abort : function(){
12010 if(this.transaction){
12011 Roo.Ajax.abort(this.transaction);
12016 * Returns true if an update is in progress
12017 * @return {Boolean}
12019 isUpdating : function(){
12020 if(this.transaction){
12021 return Roo.Ajax.isLoading(this.transaction);
12028 * @class Roo.UpdateManager.defaults
12029 * @static (not really - but it helps the doc tool)
12030 * The defaults collection enables customizing the default properties of UpdateManager
12032 Roo.UpdateManager.defaults = {
12034 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12040 * True to process scripts by default (Defaults to false).
12043 loadScripts : false,
12046 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12049 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12051 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12054 disableCaching : false,
12056 * Whether to show indicatorText when loading (Defaults to true).
12059 showLoadIndicator : true,
12061 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12064 indicatorText : '<div class="loading-indicator">Loading...</div>'
12068 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12070 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12071 * @param {String/HTMLElement/Roo.Element} el The element to update
12072 * @param {String} url The url
12073 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12074 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12077 * @member Roo.UpdateManager
12079 Roo.UpdateManager.updateElement = function(el, url, params, options){
12080 var um = Roo.get(el, true).getUpdateManager();
12081 Roo.apply(um, options);
12082 um.update(url, params, options ? options.callback : null);
12084 // alias for backwards compat
12085 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12087 * @class Roo.UpdateManager.BasicRenderer
12088 * Default Content renderer. Updates the elements innerHTML with the responseText.
12090 Roo.UpdateManager.BasicRenderer = function(){};
12092 Roo.UpdateManager.BasicRenderer.prototype = {
12094 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12095 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12096 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12097 * @param {Roo.Element} el The element being rendered
12098 * @param {Object} response The YUI Connect response object
12099 * @param {UpdateManager} updateManager The calling update manager
12100 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12102 render : function(el, response, updateManager, callback){
12103 el.update(response.responseText, updateManager.loadScripts, callback);
12109 * (c)) Alan Knowles
12115 * @class Roo.DomTemplate
12116 * @extends Roo.Template
12117 * An effort at a dom based template engine..
12119 * Similar to XTemplate, except it uses dom parsing to create the template..
12121 * Supported features:
12126 {a_variable} - output encoded.
12127 {a_variable.format:("Y-m-d")} - call a method on the variable
12128 {a_variable:raw} - unencoded output
12129 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12130 {a_variable:this.method_on_template(...)} - call a method on the template object.
12135 <div roo-for="a_variable or condition.."></div>
12136 <div roo-if="a_variable or condition"></div>
12137 <div roo-exec="some javascript"></div>
12138 <div roo-name="named_template"></div>
12143 Roo.DomTemplate = function()
12145 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12152 Roo.extend(Roo.DomTemplate, Roo.Template, {
12154 * id counter for sub templates.
12158 * flag to indicate if dom parser is inside a pre,
12159 * it will strip whitespace if not.
12164 * The various sub templates
12172 * basic tag replacing syntax
12175 * // you can fake an object call by doing this
12179 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12180 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12182 iterChild : function (node, method) {
12184 var oldPre = this.inPre;
12185 if (node.tagName == 'PRE') {
12188 for( var i = 0; i < node.childNodes.length; i++) {
12189 method.call(this, node.childNodes[i]);
12191 this.inPre = oldPre;
12197 * compile the template
12199 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12202 compile: function()
12206 // covert the html into DOM...
12210 doc = document.implementation.createHTMLDocument("");
12211 doc.documentElement.innerHTML = this.html ;
12212 div = doc.documentElement;
12214 // old IE... - nasty -- it causes all sorts of issues.. with
12215 // images getting pulled from server..
12216 div = document.createElement('div');
12217 div.innerHTML = this.html;
12219 //doc.documentElement.innerHTML = htmlBody
12225 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12227 var tpls = this.tpls;
12229 // create a top level template from the snippet..
12231 //Roo.log(div.innerHTML);
12238 body : div.innerHTML,
12251 Roo.each(tpls, function(tp){
12252 this.compileTpl(tp);
12253 this.tpls[tp.id] = tp;
12256 this.master = tpls[0];
12262 compileNode : function(node, istop) {
12267 // skip anything not a tag..
12268 if (node.nodeType != 1) {
12269 if (node.nodeType == 3 && !this.inPre) {
12270 // reduce white space..
12271 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12294 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12295 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12296 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12297 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12303 // just itterate children..
12304 this.iterChild(node,this.compileNode);
12307 tpl.uid = this.id++;
12308 tpl.value = node.getAttribute('roo-' + tpl.attr);
12309 node.removeAttribute('roo-'+ tpl.attr);
12310 if (tpl.attr != 'name') {
12311 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12312 node.parentNode.replaceChild(placeholder, node);
12315 var placeholder = document.createElement('span');
12316 placeholder.className = 'roo-tpl-' + tpl.value;
12317 node.parentNode.replaceChild(placeholder, node);
12320 // parent now sees '{domtplXXXX}
12321 this.iterChild(node,this.compileNode);
12323 // we should now have node body...
12324 var div = document.createElement('div');
12325 div.appendChild(node);
12327 // this has the unfortunate side effect of converting tagged attributes
12328 // eg. href="{...}" into %7C...%7D
12329 // this has been fixed by searching for those combo's although it's a bit hacky..
12332 tpl.body = div.innerHTML;
12339 switch (tpl.value) {
12340 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12341 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12342 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12347 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12351 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12355 tpl.id = tpl.value; // replace non characters???
12361 this.tpls.push(tpl);
12371 * Compile a segment of the template into a 'sub-template'
12377 compileTpl : function(tpl)
12379 var fm = Roo.util.Format;
12380 var useF = this.disableFormats !== true;
12382 var sep = Roo.isGecko ? "+\n" : ",\n";
12384 var undef = function(str) {
12385 Roo.debug && Roo.log("Property not found :" + str);
12389 //Roo.log(tpl.body);
12393 var fn = function(m, lbrace, name, format, args)
12396 //Roo.log(arguments);
12397 args = args ? args.replace(/\\'/g,"'") : args;
12398 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12399 if (typeof(format) == 'undefined') {
12400 format = 'htmlEncode';
12402 if (format == 'raw' ) {
12406 if(name.substr(0, 6) == 'domtpl'){
12407 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12410 // build an array of options to determine if value is undefined..
12412 // basically get 'xxxx.yyyy' then do
12413 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12414 // (function () { Roo.log("Property not found"); return ''; })() :
12419 Roo.each(name.split('.'), function(st) {
12420 lookfor += (lookfor.length ? '.': '') + st;
12421 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12424 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12427 if(format && useF){
12429 args = args ? ',' + args : "";
12431 if(format.substr(0, 5) != "this."){
12432 format = "fm." + format + '(';
12434 format = 'this.call("'+ format.substr(5) + '", ';
12438 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12441 if (args && args.length) {
12442 // called with xxyx.yuu:(test,test)
12444 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12446 // raw.. - :raw modifier..
12447 return "'"+ sep + udef_st + name + ")"+sep+"'";
12451 // branched to use + in gecko and [].join() in others
12453 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12454 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12457 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12458 body.push(tpl.body.replace(/(\r\n|\n)/g,
12459 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12460 body.push("'].join('');};};");
12461 body = body.join('');
12464 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12466 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12473 * same as applyTemplate, except it's done to one of the subTemplates
12474 * when using named templates, you can do:
12476 * var str = pl.applySubTemplate('your-name', values);
12479 * @param {Number} id of the template
12480 * @param {Object} values to apply to template
12481 * @param {Object} parent (normaly the instance of this object)
12483 applySubTemplate : function(id, values, parent)
12487 var t = this.tpls[id];
12491 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12492 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12496 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12503 if(t.execCall && t.execCall.call(this, values, parent)){
12507 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12513 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12514 parent = t.target ? values : parent;
12515 if(t.forCall && vs instanceof Array){
12517 for(var i = 0, len = vs.length; i < len; i++){
12519 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12521 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12523 //Roo.log(t.compiled);
12527 return buf.join('');
12530 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12535 return t.compiled.call(this, vs, parent);
12537 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12539 //Roo.log(t.compiled);
12547 applyTemplate : function(values){
12548 return this.master.compiled.call(this, values, {});
12549 //var s = this.subs;
12552 apply : function(){
12553 return this.applyTemplate.apply(this, arguments);
12558 Roo.DomTemplate.from = function(el){
12559 el = Roo.getDom(el);
12560 return new Roo.Domtemplate(el.value || el.innerHTML);
12563 * Ext JS Library 1.1.1
12564 * Copyright(c) 2006-2007, Ext JS, LLC.
12566 * Originally Released Under LGPL - original licence link has changed is not relivant.
12569 * <script type="text/javascript">
12573 * @class Roo.util.DelayedTask
12574 * Provides a convenient method of performing setTimeout where a new
12575 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12576 * You can use this class to buffer
12577 * the keypress events for a certain number of milliseconds, and perform only if they stop
12578 * for that amount of time.
12579 * @constructor The parameters to this constructor serve as defaults and are not required.
12580 * @param {Function} fn (optional) The default function to timeout
12581 * @param {Object} scope (optional) The default scope of that timeout
12582 * @param {Array} args (optional) The default Array of arguments
12584 Roo.util.DelayedTask = function(fn, scope, args){
12585 var id = null, d, t;
12587 var call = function(){
12588 var now = new Date().getTime();
12592 fn.apply(scope, args || []);
12596 * Cancels any pending timeout and queues a new one
12597 * @param {Number} delay The milliseconds to delay
12598 * @param {Function} newFn (optional) Overrides function passed to constructor
12599 * @param {Object} newScope (optional) Overrides scope passed to constructor
12600 * @param {Array} newArgs (optional) Overrides args passed to constructor
12602 this.delay = function(delay, newFn, newScope, newArgs){
12603 if(id && delay != d){
12607 t = new Date().getTime();
12609 scope = newScope || scope;
12610 args = newArgs || args;
12612 id = setInterval(call, d);
12617 * Cancel the last queued timeout
12619 this.cancel = function(){
12627 * Ext JS Library 1.1.1
12628 * Copyright(c) 2006-2007, Ext JS, LLC.
12630 * Originally Released Under LGPL - original licence link has changed is not relivant.
12633 * <script type="text/javascript">
12637 Roo.util.TaskRunner = function(interval){
12638 interval = interval || 10;
12639 var tasks = [], removeQueue = [];
12641 var running = false;
12643 var stopThread = function(){
12649 var startThread = function(){
12652 id = setInterval(runTasks, interval);
12656 var removeTask = function(task){
12657 removeQueue.push(task);
12663 var runTasks = function(){
12664 if(removeQueue.length > 0){
12665 for(var i = 0, len = removeQueue.length; i < len; i++){
12666 tasks.remove(removeQueue[i]);
12669 if(tasks.length < 1){
12674 var now = new Date().getTime();
12675 for(var i = 0, len = tasks.length; i < len; ++i){
12677 var itime = now - t.taskRunTime;
12678 if(t.interval <= itime){
12679 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12680 t.taskRunTime = now;
12681 if(rt === false || t.taskRunCount === t.repeat){
12686 if(t.duration && t.duration <= (now - t.taskStartTime)){
12693 * Queues a new task.
12694 * @param {Object} task
12696 this.start = function(task){
12698 task.taskStartTime = new Date().getTime();
12699 task.taskRunTime = 0;
12700 task.taskRunCount = 0;
12705 this.stop = function(task){
12710 this.stopAll = function(){
12712 for(var i = 0, len = tasks.length; i < len; i++){
12713 if(tasks[i].onStop){
12722 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12724 * Ext JS Library 1.1.1
12725 * Copyright(c) 2006-2007, Ext JS, LLC.
12727 * Originally Released Under LGPL - original licence link has changed is not relivant.
12730 * <script type="text/javascript">
12735 * @class Roo.util.MixedCollection
12736 * @extends Roo.util.Observable
12737 * A Collection class that maintains both numeric indexes and keys and exposes events.
12739 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12740 * collection (defaults to false)
12741 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12742 * and return the key value for that item. This is used when available to look up the key on items that
12743 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12744 * equivalent to providing an implementation for the {@link #getKey} method.
12746 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12754 * Fires when the collection is cleared.
12759 * Fires when an item is added to the collection.
12760 * @param {Number} index The index at which the item was added.
12761 * @param {Object} o The item added.
12762 * @param {String} key The key associated with the added item.
12767 * Fires when an item is replaced in the collection.
12768 * @param {String} key he key associated with the new added.
12769 * @param {Object} old The item being replaced.
12770 * @param {Object} new The new item.
12775 * Fires when an item is removed from the collection.
12776 * @param {Object} o The item being removed.
12777 * @param {String} key (optional) The key associated with the removed item.
12782 this.allowFunctions = allowFunctions === true;
12784 this.getKey = keyFn;
12786 Roo.util.MixedCollection.superclass.constructor.call(this);
12789 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12790 allowFunctions : false,
12793 * Adds an item to the collection.
12794 * @param {String} key The key to associate with the item
12795 * @param {Object} o The item to add.
12796 * @return {Object} The item added.
12798 add : function(key, o){
12799 if(arguments.length == 1){
12801 key = this.getKey(o);
12803 if(typeof key == "undefined" || key === null){
12805 this.items.push(o);
12806 this.keys.push(null);
12808 var old = this.map[key];
12810 return this.replace(key, o);
12813 this.items.push(o);
12815 this.keys.push(key);
12817 this.fireEvent("add", this.length-1, o, key);
12822 * MixedCollection has a generic way to fetch keys if you implement getKey.
12825 var mc = new Roo.util.MixedCollection();
12826 mc.add(someEl.dom.id, someEl);
12827 mc.add(otherEl.dom.id, otherEl);
12831 var mc = new Roo.util.MixedCollection();
12832 mc.getKey = function(el){
12838 // or via the constructor
12839 var mc = new Roo.util.MixedCollection(false, function(el){
12845 * @param o {Object} The item for which to find the key.
12846 * @return {Object} The key for the passed item.
12848 getKey : function(o){
12853 * Replaces an item in the collection.
12854 * @param {String} key The key associated with the item to replace, or the item to replace.
12855 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12856 * @return {Object} The new item.
12858 replace : function(key, o){
12859 if(arguments.length == 1){
12861 key = this.getKey(o);
12863 var old = this.item(key);
12864 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12865 return this.add(key, o);
12867 var index = this.indexOfKey(key);
12868 this.items[index] = o;
12870 this.fireEvent("replace", key, old, o);
12875 * Adds all elements of an Array or an Object to the collection.
12876 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12877 * an Array of values, each of which are added to the collection.
12879 addAll : function(objs){
12880 if(arguments.length > 1 || objs instanceof Array){
12881 var args = arguments.length > 1 ? arguments : objs;
12882 for(var i = 0, len = args.length; i < len; i++){
12886 for(var key in objs){
12887 if(this.allowFunctions || typeof objs[key] != "function"){
12888 this.add(key, objs[key]);
12895 * Executes the specified function once for every item in the collection, passing each
12896 * item as the first and only parameter. returning false from the function will stop the iteration.
12897 * @param {Function} fn The function to execute for each item.
12898 * @param {Object} scope (optional) The scope in which to execute the function.
12900 each : function(fn, scope){
12901 var items = [].concat(this.items); // each safe for removal
12902 for(var i = 0, len = items.length; i < len; i++){
12903 if(fn.call(scope || items[i], items[i], i, len) === false){
12910 * Executes the specified function once for every key in the collection, passing each
12911 * key, and its associated item as the first two parameters.
12912 * @param {Function} fn The function to execute for each item.
12913 * @param {Object} scope (optional) The scope in which to execute the function.
12915 eachKey : function(fn, scope){
12916 for(var i = 0, len = this.keys.length; i < len; i++){
12917 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12922 * Returns the first item in the collection which elicits a true return value from the
12923 * passed selection function.
12924 * @param {Function} fn The selection function to execute for each item.
12925 * @param {Object} scope (optional) The scope in which to execute the function.
12926 * @return {Object} The first item in the collection which returned true from the selection function.
12928 find : function(fn, scope){
12929 for(var i = 0, len = this.items.length; i < len; i++){
12930 if(fn.call(scope || window, this.items[i], this.keys[i])){
12931 return this.items[i];
12938 * Inserts an item at the specified index in the collection.
12939 * @param {Number} index The index to insert the item at.
12940 * @param {String} key The key to associate with the new item, or the item itself.
12941 * @param {Object} o (optional) If the second parameter was a key, the new item.
12942 * @return {Object} The item inserted.
12944 insert : function(index, key, o){
12945 if(arguments.length == 2){
12947 key = this.getKey(o);
12949 if(index >= this.length){
12950 return this.add(key, o);
12953 this.items.splice(index, 0, o);
12954 if(typeof key != "undefined" && key != null){
12957 this.keys.splice(index, 0, key);
12958 this.fireEvent("add", index, o, key);
12963 * Removed an item from the collection.
12964 * @param {Object} o The item to remove.
12965 * @return {Object} The item removed.
12967 remove : function(o){
12968 return this.removeAt(this.indexOf(o));
12972 * Remove an item from a specified index in the collection.
12973 * @param {Number} index The index within the collection of the item to remove.
12975 removeAt : function(index){
12976 if(index < this.length && index >= 0){
12978 var o = this.items[index];
12979 this.items.splice(index, 1);
12980 var key = this.keys[index];
12981 if(typeof key != "undefined"){
12982 delete this.map[key];
12984 this.keys.splice(index, 1);
12985 this.fireEvent("remove", o, key);
12990 * Removed an item associated with the passed key fom the collection.
12991 * @param {String} key The key of the item to remove.
12993 removeKey : function(key){
12994 return this.removeAt(this.indexOfKey(key));
12998 * Returns the number of items in the collection.
12999 * @return {Number} the number of items in the collection.
13001 getCount : function(){
13002 return this.length;
13006 * Returns index within the collection of the passed Object.
13007 * @param {Object} o The item to find the index of.
13008 * @return {Number} index of the item.
13010 indexOf : function(o){
13011 if(!this.items.indexOf){
13012 for(var i = 0, len = this.items.length; i < len; i++){
13013 if(this.items[i] == o) return i;
13017 return this.items.indexOf(o);
13022 * Returns index within the collection of the passed key.
13023 * @param {String} key The key to find the index of.
13024 * @return {Number} index of the key.
13026 indexOfKey : function(key){
13027 if(!this.keys.indexOf){
13028 for(var i = 0, len = this.keys.length; i < len; i++){
13029 if(this.keys[i] == key) return i;
13033 return this.keys.indexOf(key);
13038 * Returns the item associated with the passed key OR index. Key has priority over index.
13039 * @param {String/Number} key The key or index of the item.
13040 * @return {Object} The item associated with the passed key.
13042 item : function(key){
13043 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13044 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13048 * Returns the item at the specified index.
13049 * @param {Number} index The index of the item.
13052 itemAt : function(index){
13053 return this.items[index];
13057 * Returns the item associated with the passed key.
13058 * @param {String/Number} key The key of the item.
13059 * @return {Object} The item associated with the passed key.
13061 key : function(key){
13062 return this.map[key];
13066 * Returns true if the collection contains the passed Object as an item.
13067 * @param {Object} o The Object to look for in the collection.
13068 * @return {Boolean} True if the collection contains the Object as an item.
13070 contains : function(o){
13071 return this.indexOf(o) != -1;
13075 * Returns true if the collection contains the passed Object as a key.
13076 * @param {String} key The key to look for in the collection.
13077 * @return {Boolean} True if the collection contains the Object as a key.
13079 containsKey : function(key){
13080 return typeof this.map[key] != "undefined";
13084 * Removes all items from the collection.
13086 clear : function(){
13091 this.fireEvent("clear");
13095 * Returns the first item in the collection.
13096 * @return {Object} the first item in the collection..
13098 first : function(){
13099 return this.items[0];
13103 * Returns the last item in the collection.
13104 * @return {Object} the last item in the collection..
13107 return this.items[this.length-1];
13110 _sort : function(property, dir, fn){
13111 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13112 fn = fn || function(a, b){
13115 var c = [], k = this.keys, items = this.items;
13116 for(var i = 0, len = items.length; i < len; i++){
13117 c[c.length] = {key: k[i], value: items[i], index: i};
13119 c.sort(function(a, b){
13120 var v = fn(a[property], b[property]) * dsc;
13122 v = (a.index < b.index ? -1 : 1);
13126 for(var i = 0, len = c.length; i < len; i++){
13127 items[i] = c[i].value;
13130 this.fireEvent("sort", this);
13134 * Sorts this collection with the passed comparison function
13135 * @param {String} direction (optional) "ASC" or "DESC"
13136 * @param {Function} fn (optional) comparison function
13138 sort : function(dir, fn){
13139 this._sort("value", dir, fn);
13143 * Sorts this collection by keys
13144 * @param {String} direction (optional) "ASC" or "DESC"
13145 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13147 keySort : function(dir, fn){
13148 this._sort("key", dir, fn || function(a, b){
13149 return String(a).toUpperCase()-String(b).toUpperCase();
13154 * Returns a range of items in this collection
13155 * @param {Number} startIndex (optional) defaults to 0
13156 * @param {Number} endIndex (optional) default to the last item
13157 * @return {Array} An array of items
13159 getRange : function(start, end){
13160 var items = this.items;
13161 if(items.length < 1){
13164 start = start || 0;
13165 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13168 for(var i = start; i <= end; i++) {
13169 r[r.length] = items[i];
13172 for(var i = start; i >= end; i--) {
13173 r[r.length] = items[i];
13180 * Filter the <i>objects</i> in this collection by a specific property.
13181 * Returns a new collection that has been filtered.
13182 * @param {String} property A property on your objects
13183 * @param {String/RegExp} value Either string that the property values
13184 * should start with or a RegExp to test against the property
13185 * @return {MixedCollection} The new filtered collection
13187 filter : function(property, value){
13188 if(!value.exec){ // not a regex
13189 value = String(value);
13190 if(value.length == 0){
13191 return this.clone();
13193 value = new RegExp("^" + Roo.escapeRe(value), "i");
13195 return this.filterBy(function(o){
13196 return o && value.test(o[property]);
13201 * Filter by a function. * Returns a new collection that has been filtered.
13202 * The passed function will be called with each
13203 * object in the collection. If the function returns true, the value is included
13204 * otherwise it is filtered.
13205 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13206 * @param {Object} scope (optional) The scope of the function (defaults to this)
13207 * @return {MixedCollection} The new filtered collection
13209 filterBy : function(fn, scope){
13210 var r = new Roo.util.MixedCollection();
13211 r.getKey = this.getKey;
13212 var k = this.keys, it = this.items;
13213 for(var i = 0, len = it.length; i < len; i++){
13214 if(fn.call(scope||this, it[i], k[i])){
13215 r.add(k[i], it[i]);
13222 * Creates a duplicate of this collection
13223 * @return {MixedCollection}
13225 clone : function(){
13226 var r = new Roo.util.MixedCollection();
13227 var k = this.keys, it = this.items;
13228 for(var i = 0, len = it.length; i < len; i++){
13229 r.add(k[i], it[i]);
13231 r.getKey = this.getKey;
13236 * Returns the item associated with the passed key or index.
13238 * @param {String/Number} key The key or index of the item.
13239 * @return {Object} The item associated with the passed key.
13241 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13243 * Ext JS Library 1.1.1
13244 * Copyright(c) 2006-2007, Ext JS, LLC.
13246 * Originally Released Under LGPL - original licence link has changed is not relivant.
13249 * <script type="text/javascript">
13252 * @class Roo.util.JSON
13253 * Modified version of Douglas Crockford"s json.js that doesn"t
13254 * mess with the Object prototype
13255 * http://www.json.org/js.html
13258 Roo.util.JSON = new (function(){
13259 var useHasOwn = {}.hasOwnProperty ? true : false;
13261 // crashes Safari in some instances
13262 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13264 var pad = function(n) {
13265 return n < 10 ? "0" + n : n;
13278 var encodeString = function(s){
13279 if (/["\\\x00-\x1f]/.test(s)) {
13280 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13285 c = b.charCodeAt();
13287 Math.floor(c / 16).toString(16) +
13288 (c % 16).toString(16);
13291 return '"' + s + '"';
13294 var encodeArray = function(o){
13295 var a = ["["], b, i, l = o.length, v;
13296 for (i = 0; i < l; i += 1) {
13298 switch (typeof v) {
13307 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13315 var encodeDate = function(o){
13316 return '"' + o.getFullYear() + "-" +
13317 pad(o.getMonth() + 1) + "-" +
13318 pad(o.getDate()) + "T" +
13319 pad(o.getHours()) + ":" +
13320 pad(o.getMinutes()) + ":" +
13321 pad(o.getSeconds()) + '"';
13325 * Encodes an Object, Array or other value
13326 * @param {Mixed} o The variable to encode
13327 * @return {String} The JSON string
13329 this.encode = function(o)
13331 // should this be extended to fully wrap stringify..
13333 if(typeof o == "undefined" || o === null){
13335 }else if(o instanceof Array){
13336 return encodeArray(o);
13337 }else if(o instanceof Date){
13338 return encodeDate(o);
13339 }else if(typeof o == "string"){
13340 return encodeString(o);
13341 }else if(typeof o == "number"){
13342 return isFinite(o) ? String(o) : "null";
13343 }else if(typeof o == "boolean"){
13346 var a = ["{"], b, i, v;
13348 if(!useHasOwn || o.hasOwnProperty(i)) {
13350 switch (typeof v) {
13359 a.push(this.encode(i), ":",
13360 v === null ? "null" : this.encode(v));
13371 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13372 * @param {String} json The JSON string
13373 * @return {Object} The resulting object
13375 this.decode = function(json){
13377 return /** eval:var:json */ eval("(" + json + ')');
13381 * Shorthand for {@link Roo.util.JSON#encode}
13382 * @member Roo encode
13384 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13386 * Shorthand for {@link Roo.util.JSON#decode}
13387 * @member Roo decode
13389 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13392 * Ext JS Library 1.1.1
13393 * Copyright(c) 2006-2007, Ext JS, LLC.
13395 * Originally Released Under LGPL - original licence link has changed is not relivant.
13398 * <script type="text/javascript">
13402 * @class Roo.util.Format
13403 * Reusable data formatting functions
13406 Roo.util.Format = function(){
13407 var trimRe = /^\s+|\s+$/g;
13410 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13411 * @param {String} value The string to truncate
13412 * @param {Number} length The maximum length to allow before truncating
13413 * @return {String} The converted text
13415 ellipsis : function(value, len){
13416 if(value && value.length > len){
13417 return value.substr(0, len-3)+"...";
13423 * Checks a reference and converts it to empty string if it is undefined
13424 * @param {Mixed} value Reference to check
13425 * @return {Mixed} Empty string if converted, otherwise the original value
13427 undef : function(value){
13428 return typeof value != "undefined" ? value : "";
13432 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13433 * @param {String} value The string to encode
13434 * @return {String} The encoded text
13436 htmlEncode : function(value){
13437 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13441 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13442 * @param {String} value The string to decode
13443 * @return {String} The decoded text
13445 htmlDecode : function(value){
13446 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13450 * Trims any whitespace from either side of a string
13451 * @param {String} value The text to trim
13452 * @return {String} The trimmed text
13454 trim : function(value){
13455 return String(value).replace(trimRe, "");
13459 * Returns a substring from within an original string
13460 * @param {String} value The original text
13461 * @param {Number} start The start index of the substring
13462 * @param {Number} length The length of the substring
13463 * @return {String} The substring
13465 substr : function(value, start, length){
13466 return String(value).substr(start, length);
13470 * Converts a string to all lower case letters
13471 * @param {String} value The text to convert
13472 * @return {String} The converted text
13474 lowercase : function(value){
13475 return String(value).toLowerCase();
13479 * Converts a string to all upper case letters
13480 * @param {String} value The text to convert
13481 * @return {String} The converted text
13483 uppercase : function(value){
13484 return String(value).toUpperCase();
13488 * Converts the first character only of a string to upper case
13489 * @param {String} value The text to convert
13490 * @return {String} The converted text
13492 capitalize : function(value){
13493 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13497 call : function(value, fn){
13498 if(arguments.length > 2){
13499 var args = Array.prototype.slice.call(arguments, 2);
13500 args.unshift(value);
13502 return /** eval:var:value */ eval(fn).apply(window, args);
13504 /** eval:var:value */
13505 return /** eval:var:value */ eval(fn).call(window, value);
13511 * safer version of Math.toFixed..??/
13512 * @param {Number/String} value The numeric value to format
13513 * @param {Number/String} value Decimal places
13514 * @return {String} The formatted currency string
13516 toFixed : function(v, n)
13518 // why not use to fixed - precision is buggered???
13520 return Math.round(v-0);
13522 var fact = Math.pow(10,n+1);
13523 v = (Math.round((v-0)*fact))/fact;
13524 var z = (''+fact).substring(2);
13525 if (v == Math.floor(v)) {
13526 return Math.floor(v) + '.' + z;
13529 // now just padd decimals..
13530 var ps = String(v).split('.');
13531 var fd = (ps[1] + z);
13532 var r = fd.substring(0,n);
13533 var rm = fd.substring(n);
13535 return ps[0] + '.' + r;
13537 r*=1; // turn it into a number;
13539 if (String(r).length != n) {
13542 r = String(r).substring(1); // chop the end off.
13545 return ps[0] + '.' + r;
13550 * Format a number as US currency
13551 * @param {Number/String} value The numeric value to format
13552 * @return {String} The formatted currency string
13554 usMoney : function(v){
13555 return '$' + Roo.util.Format.number(v);
13560 * eventually this should probably emulate php's number_format
13561 * @param {Number/String} value The numeric value to format
13562 * @param {Number} decimals number of decimal places
13563 * @return {String} The formatted currency string
13565 number : function(v,decimals)
13567 // multiply and round.
13568 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13569 var mul = Math.pow(10, decimals);
13570 var zero = String(mul).substring(1);
13571 v = (Math.round((v-0)*mul))/mul;
13573 // if it's '0' number.. then
13575 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13577 var ps = v.split('.');
13581 var r = /(\d+)(\d{3})/;
13583 while (r.test(whole)) {
13584 whole = whole.replace(r, '$1' + ',' + '$2');
13590 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13591 // does not have decimals
13592 (decimals ? ('.' + zero) : '');
13595 return whole + sub ;
13599 * Parse a value into a formatted date using the specified format pattern.
13600 * @param {Mixed} value The value to format
13601 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13602 * @return {String} The formatted date string
13604 date : function(v, format){
13608 if(!(v instanceof Date)){
13609 v = new Date(Date.parse(v));
13611 return v.dateFormat(format || Roo.util.Format.defaults.date);
13615 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13616 * @param {String} format Any valid date format string
13617 * @return {Function} The date formatting function
13619 dateRenderer : function(format){
13620 return function(v){
13621 return Roo.util.Format.date(v, format);
13626 stripTagsRE : /<\/?[^>]+>/gi,
13629 * Strips all HTML tags
13630 * @param {Mixed} value The text from which to strip tags
13631 * @return {String} The stripped text
13633 stripTags : function(v){
13634 return !v ? v : String(v).replace(this.stripTagsRE, "");
13638 Roo.util.Format.defaults = {
13642 * Ext JS Library 1.1.1
13643 * Copyright(c) 2006-2007, Ext JS, LLC.
13645 * Originally Released Under LGPL - original licence link has changed is not relivant.
13648 * <script type="text/javascript">
13655 * @class Roo.MasterTemplate
13656 * @extends Roo.Template
13657 * Provides a template that can have child templates. The syntax is:
13659 var t = new Roo.MasterTemplate(
13660 '<select name="{name}">',
13661 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13664 t.add('options', {value: 'foo', text: 'bar'});
13665 // or you can add multiple child elements in one shot
13666 t.addAll('options', [
13667 {value: 'foo', text: 'bar'},
13668 {value: 'foo2', text: 'bar2'},
13669 {value: 'foo3', text: 'bar3'}
13671 // then append, applying the master template values
13672 t.append('my-form', {name: 'my-select'});
13674 * A name attribute for the child template is not required if you have only one child
13675 * template or you want to refer to them by index.
13677 Roo.MasterTemplate = function(){
13678 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13679 this.originalHtml = this.html;
13681 var m, re = this.subTemplateRe;
13684 while(m = re.exec(this.html)){
13685 var name = m[1], content = m[2];
13690 tpl : new Roo.Template(content)
13693 st[name] = st[subIndex];
13695 st[subIndex].tpl.compile();
13696 st[subIndex].tpl.call = this.call.createDelegate(this);
13699 this.subCount = subIndex;
13702 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13704 * The regular expression used to match sub templates
13708 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13711 * Applies the passed values to a child template.
13712 * @param {String/Number} name (optional) The name or index of the child template
13713 * @param {Array/Object} values The values to be applied to the template
13714 * @return {MasterTemplate} this
13716 add : function(name, values){
13717 if(arguments.length == 1){
13718 values = arguments[0];
13721 var s = this.subs[name];
13722 s.buffer[s.buffer.length] = s.tpl.apply(values);
13727 * Applies all the passed values to a child template.
13728 * @param {String/Number} name (optional) The name or index of the child template
13729 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13730 * @param {Boolean} reset (optional) True to reset the template first
13731 * @return {MasterTemplate} this
13733 fill : function(name, values, reset){
13735 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13743 for(var i = 0, len = values.length; i < len; i++){
13744 this.add(name, values[i]);
13750 * Resets the template for reuse
13751 * @return {MasterTemplate} this
13753 reset : function(){
13755 for(var i = 0; i < this.subCount; i++){
13761 applyTemplate : function(values){
13763 var replaceIndex = -1;
13764 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13765 return s[++replaceIndex].buffer.join("");
13767 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13770 apply : function(){
13771 return this.applyTemplate.apply(this, arguments);
13774 compile : function(){return this;}
13778 * Alias for fill().
13781 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13783 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13784 * var tpl = Roo.MasterTemplate.from('element-id');
13785 * @param {String/HTMLElement} el
13786 * @param {Object} config
13789 Roo.MasterTemplate.from = function(el, config){
13790 el = Roo.getDom(el);
13791 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13794 * Ext JS Library 1.1.1
13795 * Copyright(c) 2006-2007, Ext JS, LLC.
13797 * Originally Released Under LGPL - original licence link has changed is not relivant.
13800 * <script type="text/javascript">
13805 * @class Roo.util.CSS
13806 * Utility class for manipulating CSS rules
13809 Roo.util.CSS = function(){
13811 var doc = document;
13813 var camelRe = /(-[a-z])/gi;
13814 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13818 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13819 * tag and appended to the HEAD of the document.
13820 * @param {String|Object} cssText The text containing the css rules
13821 * @param {String} id An id to add to the stylesheet for later removal
13822 * @return {StyleSheet}
13824 createStyleSheet : function(cssText, id){
13826 var head = doc.getElementsByTagName("head")[0];
13827 var nrules = doc.createElement("style");
13828 nrules.setAttribute("type", "text/css");
13830 nrules.setAttribute("id", id);
13832 if (typeof(cssText) != 'string') {
13833 // support object maps..
13834 // not sure if this a good idea..
13835 // perhaps it should be merged with the general css handling
13836 // and handle js style props.
13837 var cssTextNew = [];
13838 for(var n in cssText) {
13840 for(var k in cssText[n]) {
13841 citems.push( k + ' : ' +cssText[n][k] + ';' );
13843 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13846 cssText = cssTextNew.join("\n");
13852 head.appendChild(nrules);
13853 ss = nrules.styleSheet;
13854 ss.cssText = cssText;
13857 nrules.appendChild(doc.createTextNode(cssText));
13859 nrules.cssText = cssText;
13861 head.appendChild(nrules);
13862 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13864 this.cacheStyleSheet(ss);
13869 * Removes a style or link tag by id
13870 * @param {String} id The id of the tag
13872 removeStyleSheet : function(id){
13873 var existing = doc.getElementById(id);
13875 existing.parentNode.removeChild(existing);
13880 * Dynamically swaps an existing stylesheet reference for a new one
13881 * @param {String} id The id of an existing link tag to remove
13882 * @param {String} url The href of the new stylesheet to include
13884 swapStyleSheet : function(id, url){
13885 this.removeStyleSheet(id);
13886 var ss = doc.createElement("link");
13887 ss.setAttribute("rel", "stylesheet");
13888 ss.setAttribute("type", "text/css");
13889 ss.setAttribute("id", id);
13890 ss.setAttribute("href", url);
13891 doc.getElementsByTagName("head")[0].appendChild(ss);
13895 * Refresh the rule cache if you have dynamically added stylesheets
13896 * @return {Object} An object (hash) of rules indexed by selector
13898 refreshCache : function(){
13899 return this.getRules(true);
13903 cacheStyleSheet : function(stylesheet){
13907 try{// try catch for cross domain access issue
13908 var ssRules = stylesheet.cssRules || stylesheet.rules;
13909 for(var j = ssRules.length-1; j >= 0; --j){
13910 rules[ssRules[j].selectorText] = ssRules[j];
13916 * Gets all css rules for the document
13917 * @param {Boolean} refreshCache true to refresh the internal cache
13918 * @return {Object} An object (hash) of rules indexed by selector
13920 getRules : function(refreshCache){
13921 if(rules == null || refreshCache){
13923 var ds = doc.styleSheets;
13924 for(var i =0, len = ds.length; i < len; i++){
13926 this.cacheStyleSheet(ds[i]);
13934 * Gets an an individual CSS rule by selector(s)
13935 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13936 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13937 * @return {CSSRule} The CSS rule or null if one is not found
13939 getRule : function(selector, refreshCache){
13940 var rs = this.getRules(refreshCache);
13941 if(!(selector instanceof Array)){
13942 return rs[selector];
13944 for(var i = 0; i < selector.length; i++){
13945 if(rs[selector[i]]){
13946 return rs[selector[i]];
13954 * Updates a rule property
13955 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13956 * @param {String} property The css property
13957 * @param {String} value The new value for the property
13958 * @return {Boolean} true If a rule was found and updated
13960 updateRule : function(selector, property, value){
13961 if(!(selector instanceof Array)){
13962 var rule = this.getRule(selector);
13964 rule.style[property.replace(camelRe, camelFn)] = value;
13968 for(var i = 0; i < selector.length; i++){
13969 if(this.updateRule(selector[i], property, value)){
13979 * Ext JS Library 1.1.1
13980 * Copyright(c) 2006-2007, Ext JS, LLC.
13982 * Originally Released Under LGPL - original licence link has changed is not relivant.
13985 * <script type="text/javascript">
13991 * @class Roo.util.ClickRepeater
13992 * @extends Roo.util.Observable
13994 * A wrapper class which can be applied to any element. Fires a "click" event while the
13995 * mouse is pressed. The interval between firings may be specified in the config but
13996 * defaults to 10 milliseconds.
13998 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14000 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14001 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14002 * Similar to an autorepeat key delay.
14003 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14004 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14005 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14006 * "interval" and "delay" are ignored. "immediate" is honored.
14007 * @cfg {Boolean} preventDefault True to prevent the default click event
14008 * @cfg {Boolean} stopDefault True to stop the default click event
14011 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14012 * 2007-02-02 jvs Renamed to ClickRepeater
14013 * 2007-02-03 jvs Modifications for FF Mac and Safari
14016 * @param {String/HTMLElement/Element} el The element to listen on
14017 * @param {Object} config
14019 Roo.util.ClickRepeater = function(el, config)
14021 this.el = Roo.get(el);
14022 this.el.unselectable();
14024 Roo.apply(this, config);
14029 * Fires when the mouse button is depressed.
14030 * @param {Roo.util.ClickRepeater} this
14032 "mousedown" : true,
14035 * Fires on a specified interval during the time the element is pressed.
14036 * @param {Roo.util.ClickRepeater} this
14041 * Fires when the mouse key is released.
14042 * @param {Roo.util.ClickRepeater} this
14047 this.el.on("mousedown", this.handleMouseDown, this);
14048 if(this.preventDefault || this.stopDefault){
14049 this.el.on("click", function(e){
14050 if(this.preventDefault){
14051 e.preventDefault();
14053 if(this.stopDefault){
14059 // allow inline handler
14061 this.on("click", this.handler, this.scope || this);
14064 Roo.util.ClickRepeater.superclass.constructor.call(this);
14067 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14070 preventDefault : true,
14071 stopDefault : false,
14075 handleMouseDown : function(){
14076 clearTimeout(this.timer);
14078 if(this.pressClass){
14079 this.el.addClass(this.pressClass);
14081 this.mousedownTime = new Date();
14083 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14084 this.el.on("mouseout", this.handleMouseOut, this);
14086 this.fireEvent("mousedown", this);
14087 this.fireEvent("click", this);
14089 this.timer = this.click.defer(this.delay || this.interval, this);
14093 click : function(){
14094 this.fireEvent("click", this);
14095 this.timer = this.click.defer(this.getInterval(), this);
14099 getInterval: function(){
14100 if(!this.accelerate){
14101 return this.interval;
14103 var pressTime = this.mousedownTime.getElapsed();
14104 if(pressTime < 500){
14106 }else if(pressTime < 1700){
14108 }else if(pressTime < 2600){
14110 }else if(pressTime < 3500){
14112 }else if(pressTime < 4400){
14114 }else if(pressTime < 5300){
14116 }else if(pressTime < 6200){
14124 handleMouseOut : function(){
14125 clearTimeout(this.timer);
14126 if(this.pressClass){
14127 this.el.removeClass(this.pressClass);
14129 this.el.on("mouseover", this.handleMouseReturn, this);
14133 handleMouseReturn : function(){
14134 this.el.un("mouseover", this.handleMouseReturn);
14135 if(this.pressClass){
14136 this.el.addClass(this.pressClass);
14142 handleMouseUp : function(){
14143 clearTimeout(this.timer);
14144 this.el.un("mouseover", this.handleMouseReturn);
14145 this.el.un("mouseout", this.handleMouseOut);
14146 Roo.get(document).un("mouseup", this.handleMouseUp);
14147 this.el.removeClass(this.pressClass);
14148 this.fireEvent("mouseup", this);
14152 * Ext JS Library 1.1.1
14153 * Copyright(c) 2006-2007, Ext JS, LLC.
14155 * Originally Released Under LGPL - original licence link has changed is not relivant.
14158 * <script type="text/javascript">
14163 * @class Roo.KeyNav
14164 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14165 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14166 * way to implement custom navigation schemes for any UI component.</p>
14167 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14168 * pageUp, pageDown, del, home, end. Usage:</p>
14170 var nav = new Roo.KeyNav("my-element", {
14171 "left" : function(e){
14172 this.moveLeft(e.ctrlKey);
14174 "right" : function(e){
14175 this.moveRight(e.ctrlKey);
14177 "enter" : function(e){
14184 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14185 * @param {Object} config The config
14187 Roo.KeyNav = function(el, config){
14188 this.el = Roo.get(el);
14189 Roo.apply(this, config);
14190 if(!this.disabled){
14191 this.disabled = true;
14196 Roo.KeyNav.prototype = {
14198 * @cfg {Boolean} disabled
14199 * True to disable this KeyNav instance (defaults to false)
14203 * @cfg {String} defaultEventAction
14204 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14205 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14206 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14208 defaultEventAction: "stopEvent",
14210 * @cfg {Boolean} forceKeyDown
14211 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14212 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14213 * handle keydown instead of keypress.
14215 forceKeyDown : false,
14218 prepareEvent : function(e){
14219 var k = e.getKey();
14220 var h = this.keyToHandler[k];
14221 //if(h && this[h]){
14222 // e.stopPropagation();
14224 if(Roo.isSafari && h && k >= 37 && k <= 40){
14230 relay : function(e){
14231 var k = e.getKey();
14232 var h = this.keyToHandler[k];
14234 if(this.doRelay(e, this[h], h) !== true){
14235 e[this.defaultEventAction]();
14241 doRelay : function(e, h, hname){
14242 return h.call(this.scope || this, e);
14245 // possible handlers
14259 // quick lookup hash
14276 * Enable this KeyNav
14278 enable: function(){
14280 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14281 // the EventObject will normalize Safari automatically
14282 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14283 this.el.on("keydown", this.relay, this);
14285 this.el.on("keydown", this.prepareEvent, this);
14286 this.el.on("keypress", this.relay, this);
14288 this.disabled = false;
14293 * Disable this KeyNav
14295 disable: function(){
14296 if(!this.disabled){
14297 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14298 this.el.un("keydown", this.relay);
14300 this.el.un("keydown", this.prepareEvent);
14301 this.el.un("keypress", this.relay);
14303 this.disabled = true;
14308 * Ext JS Library 1.1.1
14309 * Copyright(c) 2006-2007, Ext JS, LLC.
14311 * Originally Released Under LGPL - original licence link has changed is not relivant.
14314 * <script type="text/javascript">
14319 * @class Roo.KeyMap
14320 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14321 * The constructor accepts the same config object as defined by {@link #addBinding}.
14322 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14323 * combination it will call the function with this signature (if the match is a multi-key
14324 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14325 * A KeyMap can also handle a string representation of keys.<br />
14328 // map one key by key code
14329 var map = new Roo.KeyMap("my-element", {
14330 key: 13, // or Roo.EventObject.ENTER
14335 // map multiple keys to one action by string
14336 var map = new Roo.KeyMap("my-element", {
14342 // map multiple keys to multiple actions by strings and array of codes
14343 var map = new Roo.KeyMap("my-element", [
14346 fn: function(){ alert("Return was pressed"); }
14349 fn: function(){ alert('a, b or c was pressed'); }
14354 fn: function(){ alert('Control + shift + tab was pressed.'); }
14358 * <b>Note: A KeyMap starts enabled</b>
14360 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14361 * @param {Object} config The config (see {@link #addBinding})
14362 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14364 Roo.KeyMap = function(el, config, eventName){
14365 this.el = Roo.get(el);
14366 this.eventName = eventName || "keydown";
14367 this.bindings = [];
14369 this.addBinding(config);
14374 Roo.KeyMap.prototype = {
14376 * True to stop the event from bubbling and prevent the default browser action if the
14377 * key was handled by the KeyMap (defaults to false)
14383 * Add a new binding to this KeyMap. The following config object properties are supported:
14385 Property Type Description
14386 ---------- --------------- ----------------------------------------------------------------------
14387 key String/Array A single keycode or an array of keycodes to handle
14388 shift Boolean True to handle key only when shift is pressed (defaults to false)
14389 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14390 alt Boolean True to handle key only when alt is pressed (defaults to false)
14391 fn Function The function to call when KeyMap finds the expected key combination
14392 scope Object The scope of the callback function
14398 var map = new Roo.KeyMap(document, {
14399 key: Roo.EventObject.ENTER,
14404 //Add a new binding to the existing KeyMap later
14412 * @param {Object/Array} config A single KeyMap config or an array of configs
14414 addBinding : function(config){
14415 if(config instanceof Array){
14416 for(var i = 0, len = config.length; i < len; i++){
14417 this.addBinding(config[i]);
14421 var keyCode = config.key,
14422 shift = config.shift,
14423 ctrl = config.ctrl,
14426 scope = config.scope;
14427 if(typeof keyCode == "string"){
14429 var keyString = keyCode.toUpperCase();
14430 for(var j = 0, len = keyString.length; j < len; j++){
14431 ks.push(keyString.charCodeAt(j));
14435 var keyArray = keyCode instanceof Array;
14436 var handler = function(e){
14437 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14438 var k = e.getKey();
14440 for(var i = 0, len = keyCode.length; i < len; i++){
14441 if(keyCode[i] == k){
14442 if(this.stopEvent){
14445 fn.call(scope || window, k, e);
14451 if(this.stopEvent){
14454 fn.call(scope || window, k, e);
14459 this.bindings.push(handler);
14463 * Shorthand for adding a single key listener
14464 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14465 * following options:
14466 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14467 * @param {Function} fn The function to call
14468 * @param {Object} scope (optional) The scope of the function
14470 on : function(key, fn, scope){
14471 var keyCode, shift, ctrl, alt;
14472 if(typeof key == "object" && !(key instanceof Array)){
14491 handleKeyDown : function(e){
14492 if(this.enabled){ //just in case
14493 var b = this.bindings;
14494 for(var i = 0, len = b.length; i < len; i++){
14495 b[i].call(this, e);
14501 * Returns true if this KeyMap is enabled
14502 * @return {Boolean}
14504 isEnabled : function(){
14505 return this.enabled;
14509 * Enables this KeyMap
14511 enable: function(){
14513 this.el.on(this.eventName, this.handleKeyDown, this);
14514 this.enabled = true;
14519 * Disable this KeyMap
14521 disable: function(){
14523 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14524 this.enabled = false;
14529 * Ext JS Library 1.1.1
14530 * Copyright(c) 2006-2007, Ext JS, LLC.
14532 * Originally Released Under LGPL - original licence link has changed is not relivant.
14535 * <script type="text/javascript">
14540 * @class Roo.util.TextMetrics
14541 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14542 * wide, in pixels, a given block of text will be.
14545 Roo.util.TextMetrics = function(){
14549 * Measures the size of the specified text
14550 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14551 * that can affect the size of the rendered text
14552 * @param {String} text The text to measure
14553 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14554 * in order to accurately measure the text height
14555 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14557 measure : function(el, text, fixedWidth){
14559 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14562 shared.setFixedWidth(fixedWidth || 'auto');
14563 return shared.getSize(text);
14567 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14568 * the overhead of multiple calls to initialize the style properties on each measurement.
14569 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14570 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14571 * in order to accurately measure the text height
14572 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14574 createInstance : function(el, fixedWidth){
14575 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14582 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14583 var ml = new Roo.Element(document.createElement('div'));
14584 document.body.appendChild(ml.dom);
14585 ml.position('absolute');
14586 ml.setLeftTop(-1000, -1000);
14590 ml.setWidth(fixedWidth);
14595 * Returns the size of the specified text based on the internal element's style and width properties
14596 * @memberOf Roo.util.TextMetrics.Instance#
14597 * @param {String} text The text to measure
14598 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14600 getSize : function(text){
14602 var s = ml.getSize();
14608 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14609 * that can affect the size of the rendered text
14610 * @memberOf Roo.util.TextMetrics.Instance#
14611 * @param {String/HTMLElement} el The element, dom node or id
14613 bind : function(el){
14615 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14620 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14621 * to set a fixed width in order to accurately measure the text height.
14622 * @memberOf Roo.util.TextMetrics.Instance#
14623 * @param {Number} width The width to set on the element
14625 setFixedWidth : function(width){
14626 ml.setWidth(width);
14630 * Returns the measured width of the specified text
14631 * @memberOf Roo.util.TextMetrics.Instance#
14632 * @param {String} text The text to measure
14633 * @return {Number} width The width in pixels
14635 getWidth : function(text){
14636 ml.dom.style.width = 'auto';
14637 return this.getSize(text).width;
14641 * Returns the measured height of the specified text. For multiline text, be sure to call
14642 * {@link #setFixedWidth} if necessary.
14643 * @memberOf Roo.util.TextMetrics.Instance#
14644 * @param {String} text The text to measure
14645 * @return {Number} height The height in pixels
14647 getHeight : function(text){
14648 return this.getSize(text).height;
14652 instance.bind(bindTo);
14657 // backwards compat
14658 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14660 * Ext JS Library 1.1.1
14661 * Copyright(c) 2006-2007, Ext JS, LLC.
14663 * Originally Released Under LGPL - original licence link has changed is not relivant.
14666 * <script type="text/javascript">
14670 * @class Roo.state.Provider
14671 * Abstract base class for state provider implementations. This class provides methods
14672 * for encoding and decoding <b>typed</b> variables including dates and defines the
14673 * Provider interface.
14675 Roo.state.Provider = function(){
14677 * @event statechange
14678 * Fires when a state change occurs.
14679 * @param {Provider} this This state provider
14680 * @param {String} key The state key which was changed
14681 * @param {String} value The encoded value for the state
14684 "statechange": true
14687 Roo.state.Provider.superclass.constructor.call(this);
14689 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14691 * Returns the current value for a key
14692 * @param {String} name The key name
14693 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14694 * @return {Mixed} The state data
14696 get : function(name, defaultValue){
14697 return typeof this.state[name] == "undefined" ?
14698 defaultValue : this.state[name];
14702 * Clears a value from the state
14703 * @param {String} name The key name
14705 clear : function(name){
14706 delete this.state[name];
14707 this.fireEvent("statechange", this, name, null);
14711 * Sets the value for a key
14712 * @param {String} name The key name
14713 * @param {Mixed} value The value to set
14715 set : function(name, value){
14716 this.state[name] = value;
14717 this.fireEvent("statechange", this, name, value);
14721 * Decodes a string previously encoded with {@link #encodeValue}.
14722 * @param {String} value The value to decode
14723 * @return {Mixed} The decoded value
14725 decodeValue : function(cookie){
14726 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14727 var matches = re.exec(unescape(cookie));
14728 if(!matches || !matches[1]) return; // non state cookie
14729 var type = matches[1];
14730 var v = matches[2];
14733 return parseFloat(v);
14735 return new Date(Date.parse(v));
14740 var values = v.split("^");
14741 for(var i = 0, len = values.length; i < len; i++){
14742 all.push(this.decodeValue(values[i]));
14747 var values = v.split("^");
14748 for(var i = 0, len = values.length; i < len; i++){
14749 var kv = values[i].split("=");
14750 all[kv[0]] = this.decodeValue(kv[1]);
14759 * Encodes a value including type information. Decode with {@link #decodeValue}.
14760 * @param {Mixed} value The value to encode
14761 * @return {String} The encoded value
14763 encodeValue : function(v){
14765 if(typeof v == "number"){
14767 }else if(typeof v == "boolean"){
14768 enc = "b:" + (v ? "1" : "0");
14769 }else if(v instanceof Date){
14770 enc = "d:" + v.toGMTString();
14771 }else if(v instanceof Array){
14773 for(var i = 0, len = v.length; i < len; i++){
14774 flat += this.encodeValue(v[i]);
14775 if(i != len-1) flat += "^";
14778 }else if(typeof v == "object"){
14781 if(typeof v[key] != "function"){
14782 flat += key + "=" + this.encodeValue(v[key]) + "^";
14785 enc = "o:" + flat.substring(0, flat.length-1);
14789 return escape(enc);
14795 * Ext JS Library 1.1.1
14796 * Copyright(c) 2006-2007, Ext JS, LLC.
14798 * Originally Released Under LGPL - original licence link has changed is not relivant.
14801 * <script type="text/javascript">
14804 * @class Roo.state.Manager
14805 * This is the global state manager. By default all components that are "state aware" check this class
14806 * for state information if you don't pass them a custom state provider. In order for this class
14807 * to be useful, it must be initialized with a provider when your application initializes.
14809 // in your initialization function
14811 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14813 // supposed you have a {@link Roo.BorderLayout}
14814 var layout = new Roo.BorderLayout(...);
14815 layout.restoreState();
14816 // or a {Roo.BasicDialog}
14817 var dialog = new Roo.BasicDialog(...);
14818 dialog.restoreState();
14822 Roo.state.Manager = function(){
14823 var provider = new Roo.state.Provider();
14827 * Configures the default state provider for your application
14828 * @param {Provider} stateProvider The state provider to set
14830 setProvider : function(stateProvider){
14831 provider = stateProvider;
14835 * Returns the current value for a key
14836 * @param {String} name The key name
14837 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14838 * @return {Mixed} The state data
14840 get : function(key, defaultValue){
14841 return provider.get(key, defaultValue);
14845 * Sets the value for a key
14846 * @param {String} name The key name
14847 * @param {Mixed} value The state data
14849 set : function(key, value){
14850 provider.set(key, value);
14854 * Clears a value from the state
14855 * @param {String} name The key name
14857 clear : function(key){
14858 provider.clear(key);
14862 * Gets the currently configured state provider
14863 * @return {Provider} The state provider
14865 getProvider : function(){
14872 * Ext JS Library 1.1.1
14873 * Copyright(c) 2006-2007, Ext JS, LLC.
14875 * Originally Released Under LGPL - original licence link has changed is not relivant.
14878 * <script type="text/javascript">
14881 * @class Roo.state.CookieProvider
14882 * @extends Roo.state.Provider
14883 * The default Provider implementation which saves state via cookies.
14886 var cp = new Roo.state.CookieProvider({
14888 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14889 domain: "roojs.com"
14891 Roo.state.Manager.setProvider(cp);
14893 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14894 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14895 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14896 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14897 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14898 * domain the page is running on including the 'www' like 'www.roojs.com')
14899 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14901 * Create a new CookieProvider
14902 * @param {Object} config The configuration object
14904 Roo.state.CookieProvider = function(config){
14905 Roo.state.CookieProvider.superclass.constructor.call(this);
14907 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14908 this.domain = null;
14909 this.secure = false;
14910 Roo.apply(this, config);
14911 this.state = this.readCookies();
14914 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14916 set : function(name, value){
14917 if(typeof value == "undefined" || value === null){
14921 this.setCookie(name, value);
14922 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14926 clear : function(name){
14927 this.clearCookie(name);
14928 Roo.state.CookieProvider.superclass.clear.call(this, name);
14932 readCookies : function(){
14934 var c = document.cookie + ";";
14935 var re = /\s?(.*?)=(.*?);/g;
14937 while((matches = re.exec(c)) != null){
14938 var name = matches[1];
14939 var value = matches[2];
14940 if(name && name.substring(0,3) == "ys-"){
14941 cookies[name.substr(3)] = this.decodeValue(value);
14948 setCookie : function(name, value){
14949 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14950 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14951 ((this.path == null) ? "" : ("; path=" + this.path)) +
14952 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14953 ((this.secure == true) ? "; secure" : "");
14957 clearCookie : function(name){
14958 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14959 ((this.path == null) ? "" : ("; path=" + this.path)) +
14960 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14961 ((this.secure == true) ? "; secure" : "");
14965 * Ext JS Library 1.1.1
14966 * Copyright(c) 2006-2007, Ext JS, LLC.
14968 * Originally Released Under LGPL - original licence link has changed is not relivant.
14971 * <script type="text/javascript">
14976 * @class Roo.ComponentMgr
14977 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
14980 Roo.ComponentMgr = function(){
14981 var all = new Roo.util.MixedCollection();
14985 * Registers a component.
14986 * @param {Roo.Component} c The component
14988 register : function(c){
14993 * Unregisters a component.
14994 * @param {Roo.Component} c The component
14996 unregister : function(c){
15001 * Returns a component by id
15002 * @param {String} id The component id
15004 get : function(id){
15005 return all.get(id);
15009 * Registers a function that will be called when a specified component is added to ComponentMgr
15010 * @param {String} id The component id
15011 * @param {Funtction} fn The callback function
15012 * @param {Object} scope The scope of the callback
15014 onAvailable : function(id, fn, scope){
15015 all.on("add", function(index, o){
15017 fn.call(scope || o, o);
15018 all.un("add", fn, scope);
15025 * Ext JS Library 1.1.1
15026 * Copyright(c) 2006-2007, Ext JS, LLC.
15028 * Originally Released Under LGPL - original licence link has changed is not relivant.
15031 * <script type="text/javascript">
15035 * @class Roo.Component
15036 * @extends Roo.util.Observable
15037 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15038 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15039 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15040 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15041 * All visual components (widgets) that require rendering into a layout should subclass Component.
15043 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15044 * element and its id used as the component id. If a string is passed, it is assumed to be the id of an existing element
15045 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15047 Roo.Component = function(config){
15048 config = config || {};
15049 if(config.tagName || config.dom || typeof config == "string"){ // element object
15050 config = {el: config, id: config.id || config};
15052 this.initialConfig = config;
15054 Roo.apply(this, config);
15058 * Fires after the component is disabled.
15059 * @param {Roo.Component} this
15064 * Fires after the component is enabled.
15065 * @param {Roo.Component} this
15069 * @event beforeshow
15070 * Fires before the component is shown. Return false to stop the show.
15071 * @param {Roo.Component} this
15076 * Fires after the component is shown.
15077 * @param {Roo.Component} this
15081 * @event beforehide
15082 * Fires before the component is hidden. Return false to stop the hide.
15083 * @param {Roo.Component} this
15088 * Fires after the component is hidden.
15089 * @param {Roo.Component} this
15093 * @event beforerender
15094 * Fires before the component is rendered. Return false to stop the render.
15095 * @param {Roo.Component} this
15097 beforerender : true,
15100 * Fires after the component is rendered.
15101 * @param {Roo.Component} this
15105 * @event beforedestroy
15106 * Fires before the component is destroyed. Return false to stop the destroy.
15107 * @param {Roo.Component} this
15109 beforedestroy : true,
15112 * Fires after the component is destroyed.
15113 * @param {Roo.Component} this
15118 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
15120 Roo.ComponentMgr.register(this);
15121 Roo.Component.superclass.constructor.call(this);
15122 this.initComponent();
15123 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15124 this.render(this.renderTo);
15125 delete this.renderTo;
15130 Roo.Component.AUTO_ID = 1000;
15132 Roo.extend(Roo.Component, Roo.util.Observable, {
15134 * @scope Roo.Component.prototype
15136 * true if this component is hidden. Read-only.
15141 * true if this component is disabled. Read-only.
15146 * true if this component has been rendered. Read-only.
15150 /** @cfg {String} disableClass
15151 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15153 disabledClass : "x-item-disabled",
15154 /** @cfg {Boolean} allowDomMove
15155 * Whether the component can move the Dom node when rendering (defaults to true).
15157 allowDomMove : true,
15158 /** @cfg {String} hideMode
15159 * How this component should hidden. Supported values are
15160 * "visibility" (css visibility), "offsets" (negative offset position) and
15161 * "display" (css display) - defaults to "display".
15163 hideMode: 'display',
15166 ctype : "Roo.Component",
15169 * @cfg {String} actionMode
15170 * which property holds the element that used for hide() / show() / disable() / enable()
15176 getActionEl : function(){
15177 return this[this.actionMode];
15180 initComponent : Roo.emptyFn,
15182 * If this is a lazy rendering component, render it to its container element.
15183 * @param {String/HTMLElement/Element} container (optional) The element this component should be rendered into. If it is being applied to existing markup, this should be left off.
15185 render : function(container, position){
15186 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15187 if(!container && this.el){
15188 this.el = Roo.get(this.el);
15189 container = this.el.dom.parentNode;
15190 this.allowDomMove = false;
15192 this.container = Roo.get(container);
15193 this.rendered = true;
15194 if(position !== undefined){
15195 if(typeof position == 'number'){
15196 position = this.container.dom.childNodes[position];
15198 position = Roo.getDom(position);
15201 this.onRender(this.container, position || null);
15203 this.el.addClass(this.cls);
15207 this.el.applyStyles(this.style);
15210 this.fireEvent("render", this);
15211 this.afterRender(this.container);
15223 // default function is not really useful
15224 onRender : function(ct, position){
15226 this.el = Roo.get(this.el);
15227 if(this.allowDomMove !== false){
15228 ct.dom.insertBefore(this.el.dom, position);
15234 getAutoCreate : function(){
15235 var cfg = typeof this.autoCreate == "object" ?
15236 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15237 if(this.id && !cfg.id){
15244 afterRender : Roo.emptyFn,
15247 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15248 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15250 destroy : function(){
15251 if(this.fireEvent("beforedestroy", this) !== false){
15252 this.purgeListeners();
15253 this.beforeDestroy();
15255 this.el.removeAllListeners();
15257 if(this.actionMode == "container"){
15258 this.container.remove();
15262 Roo.ComponentMgr.unregister(this);
15263 this.fireEvent("destroy", this);
15268 beforeDestroy : function(){
15273 onDestroy : function(){
15278 * Returns the underlying {@link Roo.Element}.
15279 * @return {Roo.Element} The element
15281 getEl : function(){
15286 * Returns the id of this component.
15289 getId : function(){
15294 * Try to focus this component.
15295 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15296 * @return {Roo.Component} this
15298 focus : function(selectText){
15301 if(selectText === true){
15302 this.el.dom.select();
15317 * Disable this component.
15318 * @return {Roo.Component} this
15320 disable : function(){
15324 this.disabled = true;
15325 this.fireEvent("disable", this);
15330 onDisable : function(){
15331 this.getActionEl().addClass(this.disabledClass);
15332 this.el.dom.disabled = true;
15336 * Enable this component.
15337 * @return {Roo.Component} this
15339 enable : function(){
15343 this.disabled = false;
15344 this.fireEvent("enable", this);
15349 onEnable : function(){
15350 this.getActionEl().removeClass(this.disabledClass);
15351 this.el.dom.disabled = false;
15355 * Convenience function for setting disabled/enabled by boolean.
15356 * @param {Boolean} disabled
15358 setDisabled : function(disabled){
15359 this[disabled ? "disable" : "enable"]();
15363 * Show this component.
15364 * @return {Roo.Component} this
15367 if(this.fireEvent("beforeshow", this) !== false){
15368 this.hidden = false;
15372 this.fireEvent("show", this);
15378 onShow : function(){
15379 var ae = this.getActionEl();
15380 if(this.hideMode == 'visibility'){
15381 ae.dom.style.visibility = "visible";
15382 }else if(this.hideMode == 'offsets'){
15383 ae.removeClass('x-hidden');
15385 ae.dom.style.display = "";
15390 * Hide this component.
15391 * @return {Roo.Component} this
15394 if(this.fireEvent("beforehide", this) !== false){
15395 this.hidden = true;
15399 this.fireEvent("hide", this);
15405 onHide : function(){
15406 var ae = this.getActionEl();
15407 if(this.hideMode == 'visibility'){
15408 ae.dom.style.visibility = "hidden";
15409 }else if(this.hideMode == 'offsets'){
15410 ae.addClass('x-hidden');
15412 ae.dom.style.display = "none";
15417 * Convenience function to hide or show this component by boolean.
15418 * @param {Boolean} visible True to show, false to hide
15419 * @return {Roo.Component} this
15421 setVisible: function(visible){
15431 * Returns true if this component is visible.
15433 isVisible : function(){
15434 return this.getActionEl().isVisible();
15437 cloneConfig : function(overrides){
15438 overrides = overrides || {};
15439 var id = overrides.id || Roo.id();
15440 var cfg = Roo.applyIf(overrides, this.initialConfig);
15441 cfg.id = id; // prevent dup id
15442 return new this.constructor(cfg);
15446 * Ext JS Library 1.1.1
15447 * Copyright(c) 2006-2007, Ext JS, LLC.
15449 * Originally Released Under LGPL - original licence link has changed is not relivant.
15452 * <script type="text/javascript">
15456 * @class Roo.BoxComponent
15457 * @extends Roo.Component
15458 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15459 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15460 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15461 * layout containers.
15463 * @param {Roo.Element/String/Object} config The configuration options.
15465 Roo.BoxComponent = function(config){
15466 Roo.Component.call(this, config);
15470 * Fires after the component is resized.
15471 * @param {Roo.Component} this
15472 * @param {Number} adjWidth The box-adjusted width that was set
15473 * @param {Number} adjHeight The box-adjusted height that was set
15474 * @param {Number} rawWidth The width that was originally specified
15475 * @param {Number} rawHeight The height that was originally specified
15480 * Fires after the component is moved.
15481 * @param {Roo.Component} this
15482 * @param {Number} x The new x position
15483 * @param {Number} y The new y position
15489 Roo.extend(Roo.BoxComponent, Roo.Component, {
15490 // private, set in afterRender to signify that the component has been rendered
15492 // private, used to defer height settings to subclasses
15493 deferHeight: false,
15494 /** @cfg {Number} width
15495 * width (optional) size of component
15497 /** @cfg {Number} height
15498 * height (optional) size of component
15502 * Sets the width and height of the component. This method fires the resize event. This method can accept
15503 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15504 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15505 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15506 * @return {Roo.BoxComponent} this
15508 setSize : function(w, h){
15509 // support for standard size objects
15510 if(typeof w == 'object'){
15515 if(!this.boxReady){
15521 // prevent recalcs when not needed
15522 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15525 this.lastSize = {width: w, height: h};
15527 var adj = this.adjustSize(w, h);
15528 var aw = adj.width, ah = adj.height;
15529 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15530 var rz = this.getResizeEl();
15531 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15532 rz.setSize(aw, ah);
15533 }else if(!this.deferHeight && ah !== undefined){
15535 }else if(aw !== undefined){
15538 this.onResize(aw, ah, w, h);
15539 this.fireEvent('resize', this, aw, ah, w, h);
15545 * Gets the current size of the component's underlying element.
15546 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15548 getSize : function(){
15549 return this.el.getSize();
15553 * Gets the current XY position of the component's underlying element.
15554 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15555 * @return {Array} The XY position of the element (e.g., [100, 200])
15557 getPosition : function(local){
15558 if(local === true){
15559 return [this.el.getLeft(true), this.el.getTop(true)];
15561 return this.xy || this.el.getXY();
15565 * Gets the current box measurements of the component's underlying element.
15566 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15567 * @returns {Object} box An object in the format {x, y, width, height}
15569 getBox : function(local){
15570 var s = this.el.getSize();
15572 s.x = this.el.getLeft(true);
15573 s.y = this.el.getTop(true);
15575 var xy = this.xy || this.el.getXY();
15583 * Sets the current box measurements of the component's underlying element.
15584 * @param {Object} box An object in the format {x, y, width, height}
15585 * @returns {Roo.BoxComponent} this
15587 updateBox : function(box){
15588 this.setSize(box.width, box.height);
15589 this.setPagePosition(box.x, box.y);
15594 getResizeEl : function(){
15595 return this.resizeEl || this.el;
15599 getPositionEl : function(){
15600 return this.positionEl || this.el;
15604 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15605 * This method fires the move event.
15606 * @param {Number} left The new left
15607 * @param {Number} top The new top
15608 * @returns {Roo.BoxComponent} this
15610 setPosition : function(x, y){
15613 if(!this.boxReady){
15616 var adj = this.adjustPosition(x, y);
15617 var ax = adj.x, ay = adj.y;
15619 var el = this.getPositionEl();
15620 if(ax !== undefined || ay !== undefined){
15621 if(ax !== undefined && ay !== undefined){
15622 el.setLeftTop(ax, ay);
15623 }else if(ax !== undefined){
15625 }else if(ay !== undefined){
15628 this.onPosition(ax, ay);
15629 this.fireEvent('move', this, ax, ay);
15635 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15636 * This method fires the move event.
15637 * @param {Number} x The new x position
15638 * @param {Number} y The new y position
15639 * @returns {Roo.BoxComponent} this
15641 setPagePosition : function(x, y){
15644 if(!this.boxReady){
15647 if(x === undefined || y === undefined){ // cannot translate undefined points
15650 var p = this.el.translatePoints(x, y);
15651 this.setPosition(p.left, p.top);
15656 onRender : function(ct, position){
15657 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15659 this.resizeEl = Roo.get(this.resizeEl);
15661 if(this.positionEl){
15662 this.positionEl = Roo.get(this.positionEl);
15667 afterRender : function(){
15668 Roo.BoxComponent.superclass.afterRender.call(this);
15669 this.boxReady = true;
15670 this.setSize(this.width, this.height);
15671 if(this.x || this.y){
15672 this.setPosition(this.x, this.y);
15674 if(this.pageX || this.pageY){
15675 this.setPagePosition(this.pageX, this.pageY);
15680 * Force the component's size to recalculate based on the underlying element's current height and width.
15681 * @returns {Roo.BoxComponent} this
15683 syncSize : function(){
15684 delete this.lastSize;
15685 this.setSize(this.el.getWidth(), this.el.getHeight());
15690 * Called after the component is resized, this method is empty by default but can be implemented by any
15691 * subclass that needs to perform custom logic after a resize occurs.
15692 * @param {Number} adjWidth The box-adjusted width that was set
15693 * @param {Number} adjHeight The box-adjusted height that was set
15694 * @param {Number} rawWidth The width that was originally specified
15695 * @param {Number} rawHeight The height that was originally specified
15697 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15702 * Called after the component is moved, this method is empty by default but can be implemented by any
15703 * subclass that needs to perform custom logic after a move occurs.
15704 * @param {Number} x The new x position
15705 * @param {Number} y The new y position
15707 onPosition : function(x, y){
15712 adjustSize : function(w, h){
15713 if(this.autoWidth){
15716 if(this.autoHeight){
15719 return {width : w, height: h};
15723 adjustPosition : function(x, y){
15724 return {x : x, y: y};
15727 * Original code for Roojs - LGPL
15728 * <script type="text/javascript">
15732 * @class Roo.XComponent
15733 * A delayed Element creator...
15734 * Or a way to group chunks of interface together.
15736 * Mypart.xyx = new Roo.XComponent({
15738 parent : 'Mypart.xyz', // empty == document.element.!!
15742 disabled : function() {}
15744 tree : function() { // return an tree of xtype declared components
15748 xtype : 'NestedLayoutPanel',
15755 * It can be used to build a big heiracy, with parent etc.
15756 * or you can just use this to render a single compoent to a dom element
15757 * MYPART.render(Roo.Element | String(id) | dom_element )
15759 * @extends Roo.util.Observable
15761 * @param cfg {Object} configuration of component
15764 Roo.XComponent = function(cfg) {
15765 Roo.apply(this, cfg);
15769 * Fires when this the componnt is built
15770 * @param {Roo.XComponent} c the component
15775 this.region = this.region || 'center'; // default..
15776 Roo.XComponent.register(this);
15777 this.modules = false;
15778 this.el = false; // where the layout goes..
15782 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15785 * The created element (with Roo.factory())
15786 * @type {Roo.Layout}
15792 * for BC - use el in new code
15793 * @type {Roo.Layout}
15799 * for BC - use el in new code
15800 * @type {Roo.Layout}
15805 * @cfg {Function|boolean} disabled
15806 * If this module is disabled by some rule, return true from the funtion
15811 * @cfg {String} parent
15812 * Name of parent element which it get xtype added to..
15817 * @cfg {String} order
15818 * Used to set the order in which elements are created (usefull for multiple tabs)
15823 * @cfg {String} name
15824 * String to display while loading.
15828 * @cfg {String} region
15829 * Region to render component to (defaults to center)
15834 * @cfg {Array} items
15835 * A single item array - the first element is the root of the tree..
15836 * It's done this way to stay compatible with the Xtype system...
15842 * The method that retuns the tree of parts that make up this compoennt
15849 * render element to dom or tree
15850 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
15853 render : function(el)
15857 var hp = this.parent ? 1 : 0;
15859 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
15860 // if parent is a '#.....' string, then let's use that..
15861 var ename = this.parent.substr(1)
15862 this.parent = (this.parent == '#bootstrap') ? { el : true} : false; // flags it as a top module...
15863 el = Roo.get(ename);
15864 if (!el && !this.parent) {
15865 Roo.log("Warning - element can not be found :#" + ename );
15871 if (!this.parent) {
15873 el = el ? Roo.get(el) : false;
15875 // it's a top level one..
15877 el : new Roo.BorderLayout(el || document.body, {
15883 tabPosition: 'top',
15884 //resizeTabs: true,
15885 alwaysShowTabs: el && hp? false : true,
15886 hideTabs: el || !hp ? true : false,
15893 if (!this.parent.el) {
15894 // probably an old style ctor, which has been disabled.
15898 // The 'tree' method is '_tree now'
15900 var tree = this._tree ? this._tree() : this.tree();
15901 tree.region = tree.region || this.region;
15903 if (this.parent.el === true) {
15904 // bootstrap... - body..
15905 this.parent.el = Roo.factory(tree);
15908 this.el = this.parent.el.addxtype(tree);
15909 this.fireEvent('built', this);
15911 this.panel = this.el;
15912 this.layout = this.panel.layout;
15913 this.parentLayout = this.parent.layout || false;
15919 Roo.apply(Roo.XComponent, {
15921 * @property hideProgress
15922 * true to disable the building progress bar.. usefull on single page renders.
15925 hideProgress : false,
15927 * @property buildCompleted
15928 * True when the builder has completed building the interface.
15931 buildCompleted : false,
15934 * @property topModule
15935 * the upper most module - uses document.element as it's constructor.
15942 * @property modules
15943 * array of modules to be created by registration system.
15944 * @type {Array} of Roo.XComponent
15949 * @property elmodules
15950 * array of modules to be created by which use #ID
15951 * @type {Array} of Roo.XComponent
15957 * @property build_from_html
15958 * Build elements from html - used by bootstrap HTML stuff
15959 * - this is cleared after build is completed
15960 * @type {boolean} true (default false)
15963 build_from_html : false,
15966 * Register components to be built later.
15968 * This solves the following issues
15969 * - Building is not done on page load, but after an authentication process has occured.
15970 * - Interface elements are registered on page load
15971 * - Parent Interface elements may not be loaded before child, so this handles that..
15978 module : 'Pman.Tab.projectMgr',
15980 parent : 'Pman.layout',
15981 disabled : false, // or use a function..
15984 * * @param {Object} details about module
15986 register : function(obj) {
15988 Roo.XComponent.event.fireEvent('register', obj);
15989 switch(typeof(obj.disabled) ) {
15995 if ( obj.disabled() ) {
16001 if (obj.disabled) {
16007 this.modules.push(obj);
16011 * convert a string to an object..
16012 * eg. 'AAA.BBB' -> finds AAA.BBB
16016 toObject : function(str)
16018 if (!str || typeof(str) == 'object') {
16021 if (str.substring(0,1) == '#') {
16025 var ar = str.split('.');
16030 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16032 throw "Module not found : " + str;
16036 throw "Module not found : " + str;
16038 Roo.each(ar, function(e) {
16039 if (typeof(o[e]) == 'undefined') {
16040 throw "Module not found : " + str;
16051 * move modules into their correct place in the tree..
16054 preBuild : function ()
16057 Roo.each(this.modules , function (obj)
16059 Roo.XComponent.event.fireEvent('beforebuild', obj);
16061 var opar = obj.parent;
16063 obj.parent = this.toObject(opar);
16065 Roo.log("parent:toObject failed: " + e.toString());
16070 Roo.debug && Roo.log("GOT top level module");
16071 Roo.debug && Roo.log(obj);
16072 obj.modules = new Roo.util.MixedCollection(false,
16073 function(o) { return o.order + '' }
16075 this.topModule = obj;
16078 // parent is a string (usually a dom element name..)
16079 if (typeof(obj.parent) == 'string') {
16080 this.elmodules.push(obj);
16083 if (obj.parent.constructor != Roo.XComponent) {
16084 Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16086 if (!obj.parent.modules) {
16087 obj.parent.modules = new Roo.util.MixedCollection(false,
16088 function(o) { return o.order + '' }
16091 if (obj.parent.disabled) {
16092 obj.disabled = true;
16094 obj.parent.modules.add(obj);
16099 * make a list of modules to build.
16100 * @return {Array} list of modules.
16103 buildOrder : function()
16106 var cmp = function(a,b) {
16107 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16109 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16110 throw "No top level modules to build";
16113 // make a flat list in order of modules to build.
16114 var mods = this.topModule ? [ this.topModule ] : [];
16117 // elmodules (is a list of DOM based modules )
16118 Roo.each(this.elmodules, function(e) {
16120 if (!this.topModule &&
16121 typeof(e.parent) == 'string' &&
16122 e.parent.substring(0,1) == '#' &&
16123 Roo.get(e.parent.substr(1))
16126 _this.topModule = e;
16132 // add modules to their parents..
16133 var addMod = function(m) {
16134 Roo.debug && Roo.log("build Order: add: " + m.name);
16137 if (m.modules && !m.disabled) {
16138 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16139 m.modules.keySort('ASC', cmp );
16140 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16142 m.modules.each(addMod);
16144 Roo.debug && Roo.log("build Order: no child modules");
16146 // not sure if this is used any more..
16148 m.finalize.name = m.name + " (clean up) ";
16149 mods.push(m.finalize);
16153 if (this.topModule && this.topModule.modules) {
16154 this.topModule.modules.keySort('ASC', cmp );
16155 this.topModule.modules.each(addMod);
16161 * Build the registered modules.
16162 * @param {Object} parent element.
16163 * @param {Function} optional method to call after module has been added.
16167 build : function(opts)
16170 if (typeof(opts) != 'undefined') {
16171 Roo.apply(this,opts);
16175 var mods = this.buildOrder();
16177 //this.allmods = mods;
16178 //Roo.debug && Roo.log(mods);
16180 if (!mods.length) { // should not happen
16181 throw "NO modules!!!";
16185 var msg = "Building Interface...";
16186 // flash it up as modal - so we store the mask!?
16187 if (!this.hideProgress && Roo.MessageBox) {
16188 Roo.MessageBox.show({ title: 'loading' });
16189 Roo.MessageBox.show({
16190 title: "Please wait...",
16199 var total = mods.length;
16202 var progressRun = function() {
16203 if (!mods.length) {
16204 Roo.debug && Roo.log('hide?');
16205 if (!this.hideProgress && Roo.MessageBox) {
16206 Roo.MessageBox.hide();
16208 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16210 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16216 var m = mods.shift();
16219 Roo.debug && Roo.log(m);
16220 // not sure if this is supported any more.. - modules that are are just function
16221 if (typeof(m) == 'function') {
16223 return progressRun.defer(10, _this);
16227 msg = "Building Interface " + (total - mods.length) +
16229 (m.name ? (' - ' + m.name) : '');
16230 Roo.debug && Roo.log(msg);
16231 if (!this.hideProgress && Roo.MessageBox) {
16232 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16236 // is the module disabled?
16237 var disabled = (typeof(m.disabled) == 'function') ?
16238 m.disabled.call(m.module.disabled) : m.disabled;
16242 return progressRun(); // we do not update the display!
16250 // it's 10 on top level, and 1 on others??? why...
16251 return progressRun.defer(10, _this);
16254 progressRun.defer(1, _this);
16268 * wrapper for event.on - aliased later..
16269 * Typically use to register a event handler for register:
16271 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16280 Roo.XComponent.event = new Roo.util.Observable({
16284 * Fires when an Component is registered,
16285 * set the disable property on the Component to stop registration.
16286 * @param {Roo.XComponent} c the component being registerd.
16291 * @event beforebuild
16292 * Fires before each Component is built
16293 * can be used to apply permissions.
16294 * @param {Roo.XComponent} c the component being registerd.
16297 'beforebuild' : true,
16299 * @event buildcomplete
16300 * Fires on the top level element when all elements have been built
16301 * @param {Roo.XComponent} the top level component.
16303 'buildcomplete' : true
16308 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);