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..
302 if (c.constructor == ns[c.xtype]) {// already created...
306 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
307 var ret = new ns[c.xtype](c);
311 c.xns = false; // prevent recursion..
315 * Logs to console if it can.
317 * @param {String|Object} string
322 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
329 * 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.
333 urlEncode : function(o){
339 var ov = o[key], k = Roo.encodeURIComponent(key);
340 var type = typeof ov;
341 if(type == 'undefined'){
343 }else if(type != "function" && type != "object"){
344 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
345 }else if(ov instanceof Array){
347 for(var i = 0, len = ov.length; i < len; i++) {
348 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
359 * Safe version of encodeURIComponent
360 * @param {String} data
364 encodeURIComponent : function (data)
367 return encodeURIComponent(data);
368 } catch(e) {} // should be an uri encode error.
370 if (data == '' || data == null){
373 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
374 function nibble_to_hex(nibble){
375 var chars = '0123456789ABCDEF';
376 return chars.charAt(nibble);
378 data = data.toString();
380 for(var i=0; i<data.length; i++){
381 var c = data.charCodeAt(i);
382 var bs = new Array();
385 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
386 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
387 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
388 bs[3] = 0x80 | (c & 0x3F);
389 }else if (c > 0x800){
391 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
392 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
393 bs[2] = 0x80 | (c & 0x3F);
396 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
397 bs[1] = 0x80 | (c & 0x3F);
402 for(var j=0; j<bs.length; j++){
404 var hex = nibble_to_hex((b & 0xF0) >>> 4)
405 + nibble_to_hex(b &0x0F);
414 * 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]}.
415 * @param {String} string
416 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
417 * @return {Object} A literal with members
419 urlDecode : function(string, overwrite){
420 if(!string || !string.length){
424 var pairs = string.split('&');
425 var pair, name, value;
426 for(var i = 0, len = pairs.length; i < len; i++){
427 pair = pairs[i].split('=');
428 name = decodeURIComponent(pair[0]);
429 value = decodeURIComponent(pair[1]);
430 if(overwrite !== true){
431 if(typeof obj[name] == "undefined"){
433 }else if(typeof obj[name] == "string"){
434 obj[name] = [obj[name]];
435 obj[name].push(value);
437 obj[name].push(value);
447 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
448 * passed array is not really an array, your function is called once with it.
449 * The supplied function is called with (Object item, Number index, Array allItems).
450 * @param {Array/NodeList/Mixed} array
451 * @param {Function} fn
452 * @param {Object} scope
454 each : function(array, fn, scope){
455 if(typeof array.length == "undefined" || typeof array == "string"){
458 for(var i = 0, len = array.length; i < len; i++){
459 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
464 combine : function(){
465 var as = arguments, l = as.length, r = [];
466 for(var i = 0; i < l; i++){
468 if(a instanceof Array){
470 }else if(a.length !== undefined && !a.substr){
471 r = r.concat(Array.prototype.slice.call(a, 0));
480 * Escapes the passed string for use in a regular expression
481 * @param {String} str
484 escapeRe : function(s) {
485 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
489 callback : function(cb, scope, args, delay){
490 if(typeof cb == "function"){
492 cb.defer(delay, scope, args || []);
494 cb.apply(scope, args || []);
500 * Return the dom node for the passed string (id), dom node, or Roo.Element
501 * @param {String/HTMLElement/Roo.Element} el
502 * @return HTMLElement
504 getDom : function(el){
508 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
512 * Shorthand for {@link Roo.ComponentMgr#get}
514 * @return Roo.Component
516 getCmp : function(id){
517 return Roo.ComponentMgr.get(id);
520 num : function(v, defaultValue){
521 if(typeof v != 'number'){
527 destroy : function(){
528 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
532 as.removeAllListeners();
536 if(typeof as.purgeListeners == 'function'){
539 if(typeof as.destroy == 'function'){
546 // inpired by a similar function in mootools library
548 * Returns the type of object that is passed in. If the object passed in is null or undefined it
549 * return false otherwise it returns one of the following values:<ul>
550 * <li><b>string</b>: If the object passed is a string</li>
551 * <li><b>number</b>: If the object passed is a number</li>
552 * <li><b>boolean</b>: If the object passed is a boolean value</li>
553 * <li><b>function</b>: If the object passed is a function reference</li>
554 * <li><b>object</b>: If the object passed is an object</li>
555 * <li><b>array</b>: If the object passed is an array</li>
556 * <li><b>regexp</b>: If the object passed is a regular expression</li>
557 * <li><b>element</b>: If the object passed is a DOM Element</li>
558 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
559 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
560 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
561 * @param {Mixed} object
565 if(o === undefined || o === null){
572 if(t == 'object' && o.nodeName) {
574 case 1: return 'element';
575 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
578 if(t == 'object' || t == 'function') {
579 switch(o.constructor) {
580 case Array: return 'array';
581 case RegExp: return 'regexp';
583 if(typeof o.length == 'number' && typeof o.item == 'function') {
591 * Returns true if the passed value is null, undefined or an empty string (optional).
592 * @param {Mixed} value The value to test
593 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
596 isEmpty : function(v, allowBlank){
597 return v === null || v === undefined || (!allowBlank ? v === '' : false);
611 isBorderBox : isBorderBox,
613 isWindows : isWindows,
622 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
623 * you may want to set this to true.
626 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
631 * Selects a single element as a Roo Element
632 * This is about as close as you can get to jQuery's $('do crazy stuff')
633 * @param {String} selector The selector/xpath query
634 * @param {Node} root (optional) The start of the query (defaults to document).
635 * @return {Roo.Element}
637 selectNode : function(selector, root)
639 var node = Roo.DomQuery.selectNode(selector,root);
640 return node ? Roo.get(node) : new Roo.Element(false);
648 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
649 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
652 * Ext JS Library 1.1.1
653 * Copyright(c) 2006-2007, Ext JS, LLC.
655 * Originally Released Under LGPL - original licence link has changed is not relivant.
658 * <script type="text/javascript">
662 // wrappedn so fnCleanup is not in global scope...
664 function fnCleanUp() {
665 var p = Function.prototype;
666 delete p.createSequence;
668 delete p.createDelegate;
669 delete p.createCallback;
670 delete p.createInterceptor;
672 window.detachEvent("onunload", fnCleanUp);
674 window.attachEvent("onunload", fnCleanUp);
681 * These functions are available on every Function object (any JavaScript function).
683 Roo.apply(Function.prototype, {
685 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
686 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
687 * Will create a function that is bound to those 2 args.
688 * @return {Function} The new function
690 createCallback : function(/*args...*/){
691 // make args available, in function below
692 var args = arguments;
695 return method.apply(window, args);
700 * Creates a delegate (callback) that sets the scope to obj.
701 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
702 * Will create a function that is automatically scoped to this.
703 * @param {Object} obj (optional) The object for which the scope is set
704 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
705 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
706 * if a number the args are inserted at the specified position
707 * @return {Function} The new function
709 createDelegate : function(obj, args, appendArgs){
712 var callArgs = args || arguments;
713 if(appendArgs === true){
714 callArgs = Array.prototype.slice.call(arguments, 0);
715 callArgs = callArgs.concat(args);
716 }else if(typeof appendArgs == "number"){
717 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
718 var applyArgs = [appendArgs, 0].concat(args); // create method call params
719 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
721 return method.apply(obj || window, callArgs);
726 * Calls this function after the number of millseconds specified.
727 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
728 * @param {Object} obj (optional) The object for which the scope is set
729 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
730 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
731 * if a number the args are inserted at the specified position
732 * @return {Number} The timeout id that can be used with clearTimeout
734 defer : function(millis, obj, args, appendArgs){
735 var fn = this.createDelegate(obj, args, appendArgs);
737 return setTimeout(fn, millis);
743 * Create a combined function call sequence of the original function + the passed function.
744 * The resulting function returns the results of the original function.
745 * The passed fcn is called with the parameters of the original function
746 * @param {Function} fcn The function to sequence
747 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
748 * @return {Function} The new function
750 createSequence : function(fcn, scope){
751 if(typeof fcn != "function"){
756 var retval = method.apply(this || window, arguments);
757 fcn.apply(scope || this || window, arguments);
763 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
764 * The resulting function returns the results of the original function.
765 * The passed fcn is called with the parameters of the original function.
767 * @param {Function} fcn The function to call before the original
768 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
769 * @return {Function} The new function
771 createInterceptor : function(fcn, scope){
772 if(typeof fcn != "function"){
779 if(fcn.apply(scope || this || window, arguments) === false){
782 return method.apply(this || window, arguments);
788 * Ext JS Library 1.1.1
789 * Copyright(c) 2006-2007, Ext JS, LLC.
791 * Originally Released Under LGPL - original licence link has changed is not relivant.
794 * <script type="text/javascript">
797 Roo.applyIf(String, {
802 * Escapes the passed string for ' and \
803 * @param {String} string The string to escape
804 * @return {String} The escaped string
807 escape : function(string) {
808 return string.replace(/('|\\)/g, "\\$1");
812 * Pads the left side of a string with a specified character. This is especially useful
813 * for normalizing number and date strings. Example usage:
815 var s = String.leftPad('123', 5, '0');
816 // s now contains the string: '00123'
818 * @param {String} string The original string
819 * @param {Number} size The total length of the output string
820 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
821 * @return {String} The padded string
824 leftPad : function (val, size, ch) {
825 var result = new String(val);
826 if(ch === null || ch === undefined || ch === '') {
829 while (result.length < size) {
830 result = ch + result;
836 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
837 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
839 var cls = 'my-class', text = 'Some text';
840 var s = String.format('<div class="{0}">{1}</div>', cls, text);
841 // s now contains the string: '<div class="my-class">Some text</div>'
843 * @param {String} string The tokenized string to be formatted
844 * @param {String} value1 The value to replace token {0}
845 * @param {String} value2 Etc...
846 * @return {String} The formatted string
849 format : function(format){
850 var args = Array.prototype.slice.call(arguments, 1);
851 return format.replace(/\{(\d+)\}/g, function(m, i){
852 return Roo.util.Format.htmlEncode(args[i]);
858 * Utility function that allows you to easily switch a string between two alternating values. The passed value
859 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
860 * they are already different, the first value passed in is returned. Note that this method returns the new value
861 * but does not change the current string.
863 // alternate sort directions
864 sort = sort.toggle('ASC', 'DESC');
866 // instead of conditional logic:
867 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
869 * @param {String} value The value to compare to the current string
870 * @param {String} other The new value to use if the string already equals the first value passed in
871 * @return {String} The new value
874 String.prototype.toggle = function(value, other){
875 return this == value ? other : value;
878 * Ext JS Library 1.1.1
879 * Copyright(c) 2006-2007, Ext JS, LLC.
881 * Originally Released Under LGPL - original licence link has changed is not relivant.
884 * <script type="text/javascript">
890 Roo.applyIf(Number.prototype, {
892 * Checks whether or not the current number is within a desired range. If the number is already within the
893 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
894 * exceeded. Note that this method returns the constrained value but does not change the current number.
895 * @param {Number} min The minimum number in the range
896 * @param {Number} max The maximum number in the range
897 * @return {Number} The constrained value if outside the range, otherwise the current value
899 constrain : function(min, max){
900 return Math.min(Math.max(this, min), max);
904 * Ext JS Library 1.1.1
905 * Copyright(c) 2006-2007, Ext JS, LLC.
907 * Originally Released Under LGPL - original licence link has changed is not relivant.
910 * <script type="text/javascript">
915 Roo.applyIf(Array.prototype, {
917 * Checks whether or not the specified object exists in the array.
918 * @param {Object} o The object to check for
919 * @return {Number} The index of o in the array (or -1 if it is not found)
921 indexOf : function(o){
922 for (var i = 0, len = this.length; i < len; i++){
923 if(this[i] == o) return i;
929 * Removes the specified object from the array. If the object is not found nothing happens.
930 * @param {Object} o The object to remove
932 remove : function(o){
933 var index = this.indexOf(o);
935 this.splice(index, 1);
939 * Map (JS 1.6 compatibility)
940 * @param {Function} function to call
944 var len = this.length >>> 0;
945 if (typeof fun != "function")
946 throw new TypeError();
948 var res = new Array(len);
949 var thisp = arguments[1];
950 for (var i = 0; i < len; i++)
953 res[i] = fun.call(thisp, this[i], i, this);
964 * Ext JS Library 1.1.1
965 * Copyright(c) 2006-2007, Ext JS, LLC.
967 * Originally Released Under LGPL - original licence link has changed is not relivant.
970 * <script type="text/javascript">
976 * The date parsing and format syntax is a subset of
977 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
978 * supported will provide results equivalent to their PHP versions.
980 * Following is the list of all currently supported formats:
983 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
985 Format Output Description
986 ------ ---------- --------------------------------------------------------------
987 d 10 Day of the month, 2 digits with leading zeros
988 D Wed A textual representation of a day, three letters
989 j 10 Day of the month without leading zeros
990 l Wednesday A full textual representation of the day of the week
991 S th English ordinal day of month suffix, 2 chars (use with j)
992 w 3 Numeric representation of the day of the week
993 z 9 The julian date, or day of the year (0-365)
994 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
995 F January A full textual representation of the month
996 m 01 Numeric representation of a month, with leading zeros
997 M Jan Month name abbreviation, three letters
998 n 1 Numeric representation of a month, without leading zeros
999 t 31 Number of days in the given month
1000 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1001 Y 2007 A full numeric representation of a year, 4 digits
1002 y 07 A two digit representation of a year
1003 a pm Lowercase Ante meridiem and Post meridiem
1004 A PM Uppercase Ante meridiem and Post meridiem
1005 g 3 12-hour format of an hour without leading zeros
1006 G 15 24-hour format of an hour without leading zeros
1007 h 03 12-hour format of an hour with leading zeros
1008 H 15 24-hour format of an hour with leading zeros
1009 i 05 Minutes with leading zeros
1010 s 01 Seconds, with leading zeros
1011 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1012 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1013 T CST Timezone setting of the machine running the code
1014 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1017 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1019 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1020 document.write(dt.format('Y-m-d')); //2007-01-10
1021 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1022 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
1025 * Here are some standard date/time patterns that you might find helpful. They
1026 * are not part of the source of Date.js, but to use them you can simply copy this
1027 * block of code into any script that is included after Date.js and they will also become
1028 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1031 ISO8601Long:"Y-m-d H:i:s",
1032 ISO8601Short:"Y-m-d",
1034 LongDate: "l, F d, Y",
1035 FullDateTime: "l, F d, Y g:i:s A",
1038 LongTime: "g:i:s A",
1039 SortableDateTime: "Y-m-d\\TH:i:s",
1040 UniversalSortableDateTime: "Y-m-d H:i:sO",
1047 var dt = new Date();
1048 document.write(dt.format(Date.patterns.ShortDate));
1053 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1054 * They generate precompiled functions from date formats instead of parsing and
1055 * processing the pattern every time you format a date. These functions are available
1056 * on every Date object (any javascript function).
1058 * The original article and download are here:
1059 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1066 Returns the number of milliseconds between this date and date
1067 @param {Date} date (optional) Defaults to now
1068 @return {Number} The diff in milliseconds
1069 @member Date getElapsed
1071 Date.prototype.getElapsed = function(date) {
1072 return Math.abs((date || new Date()).getTime()-this.getTime());
1074 // was in date file..
1078 Date.parseFunctions = {count:0};
1080 Date.parseRegexes = [];
1082 Date.formatFunctions = {count:0};
1085 Date.prototype.dateFormat = function(format) {
1086 if (Date.formatFunctions[format] == null) {
1087 Date.createNewFormat(format);
1089 var func = Date.formatFunctions[format];
1090 return this[func]();
1095 * Formats a date given the supplied format string
1096 * @param {String} format The format string
1097 * @return {String} The formatted date
1100 Date.prototype.format = Date.prototype.dateFormat;
1103 Date.createNewFormat = function(format) {
1104 var funcName = "format" + Date.formatFunctions.count++;
1105 Date.formatFunctions[format] = funcName;
1106 var code = "Date.prototype." + funcName + " = function(){return ";
1107 var special = false;
1109 for (var i = 0; i < format.length; ++i) {
1110 ch = format.charAt(i);
1111 if (!special && ch == "\\") {
1116 code += "'" + String.escape(ch) + "' + ";
1119 code += Date.getFormatCode(ch);
1122 /** eval:var:zzzzzzzzzzzzz */
1123 eval(code.substring(0, code.length - 3) + ";}");
1127 Date.getFormatCode = function(character) {
1128 switch (character) {
1130 return "String.leftPad(this.getDate(), 2, '0') + ";
1132 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1134 return "this.getDate() + ";
1136 return "Date.dayNames[this.getDay()] + ";
1138 return "this.getSuffix() + ";
1140 return "this.getDay() + ";
1142 return "this.getDayOfYear() + ";
1144 return "this.getWeekOfYear() + ";
1146 return "Date.monthNames[this.getMonth()] + ";
1148 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1150 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1152 return "(this.getMonth() + 1) + ";
1154 return "this.getDaysInMonth() + ";
1156 return "(this.isLeapYear() ? 1 : 0) + ";
1158 return "this.getFullYear() + ";
1160 return "('' + this.getFullYear()).substring(2, 4) + ";
1162 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1164 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1166 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1168 return "this.getHours() + ";
1170 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1172 return "String.leftPad(this.getHours(), 2, '0') + ";
1174 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1176 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1178 return "this.getGMTOffset() + ";
1180 return "this.getGMTColonOffset() + ";
1182 return "this.getTimezone() + ";
1184 return "(this.getTimezoneOffset() * -60) + ";
1186 return "'" + String.escape(character) + "' + ";
1191 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1192 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1193 * the date format that is not specified will default to the current date value for that part. Time parts can also
1194 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1195 * string or the parse operation will fail.
1198 //dt = Fri May 25 2007 (current date)
1199 var dt = new Date();
1201 //dt = Thu May 25 2006 (today's month/day in 2006)
1202 dt = Date.parseDate("2006", "Y");
1204 //dt = Sun Jan 15 2006 (all date parts specified)
1205 dt = Date.parseDate("2006-1-15", "Y-m-d");
1207 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1208 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1210 * @param {String} input The unparsed date as a string
1211 * @param {String} format The format the date is in
1212 * @return {Date} The parsed date
1215 Date.parseDate = function(input, format) {
1216 if (Date.parseFunctions[format] == null) {
1217 Date.createParser(format);
1219 var func = Date.parseFunctions[format];
1220 return Date[func](input);
1225 Date.createParser = function(format) {
1226 var funcName = "parse" + Date.parseFunctions.count++;
1227 var regexNum = Date.parseRegexes.length;
1228 var currentGroup = 1;
1229 Date.parseFunctions[format] = funcName;
1231 var code = "Date." + funcName + " = function(input){\n"
1232 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1233 + "var d = new Date();\n"
1234 + "y = d.getFullYear();\n"
1235 + "m = d.getMonth();\n"
1236 + "d = d.getDate();\n"
1237 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1238 + "if (results && results.length > 0) {";
1241 var special = false;
1243 for (var i = 0; i < format.length; ++i) {
1244 ch = format.charAt(i);
1245 if (!special && ch == "\\") {
1250 regex += String.escape(ch);
1253 var obj = Date.formatCodeToRegex(ch, currentGroup);
1254 currentGroup += obj.g;
1256 if (obj.g && obj.c) {
1262 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1263 + "{v = new Date(y, m, d, h, i, s);}\n"
1264 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1265 + "{v = new Date(y, m, d, h, i);}\n"
1266 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1267 + "{v = new Date(y, m, d, h);}\n"
1268 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1269 + "{v = new Date(y, m, d);}\n"
1270 + "else if (y >= 0 && m >= 0)\n"
1271 + "{v = new Date(y, m);}\n"
1272 + "else if (y >= 0)\n"
1273 + "{v = new Date(y);}\n"
1274 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1275 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1276 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1279 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1280 /** eval:var:zzzzzzzzzzzzz */
1285 Date.formatCodeToRegex = function(character, currentGroup) {
1286 switch (character) {
1290 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1293 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1294 s:"(\\d{1,2})"}; // day of month without leading zeroes
1297 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1298 s:"(\\d{2})"}; // day of month with leading zeroes
1302 s:"(?:" + Date.dayNames.join("|") + ")"};
1306 s:"(?:st|nd|rd|th)"};
1321 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1322 s:"(" + Date.monthNames.join("|") + ")"};
1325 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1326 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1329 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1330 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1333 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1334 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1345 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1349 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1350 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1354 c:"if (results[" + currentGroup + "] == 'am') {\n"
1355 + "if (h == 12) { h = 0; }\n"
1356 + "} else { if (h < 12) { h += 12; }}",
1360 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1361 + "if (h == 12) { h = 0; }\n"
1362 + "} else { if (h < 12) { h += 12; }}",
1367 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1368 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1372 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1373 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1376 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1380 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1385 "o = results[", currentGroup, "];\n",
1386 "var sn = o.substring(0,1);\n", // get + / - sign
1387 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1388 "var mn = o.substring(3,5) % 60;\n", // get minutes
1389 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1390 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1392 s:"([+\-]\\d{2,4})"};
1398 "o = results[", currentGroup, "];\n",
1399 "var sn = o.substring(0,1);\n",
1400 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1401 "var mn = o.substring(4,6) % 60;\n",
1402 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1403 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1409 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1412 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1413 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1414 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1418 s:String.escape(character)};
1423 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1424 * @return {String} The abbreviated timezone name (e.g. 'CST')
1426 Date.prototype.getTimezone = function() {
1427 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1431 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1432 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1434 Date.prototype.getGMTOffset = function() {
1435 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1436 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1437 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1441 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1442 * @return {String} 2-characters representing hours and 2-characters representing minutes
1443 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1445 Date.prototype.getGMTColonOffset = function() {
1446 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1447 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1449 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1453 * Get the numeric day number of the year, adjusted for leap year.
1454 * @return {Number} 0 through 364 (365 in leap years)
1456 Date.prototype.getDayOfYear = function() {
1458 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1459 for (var i = 0; i < this.getMonth(); ++i) {
1460 num += Date.daysInMonth[i];
1462 return num + this.getDate() - 1;
1466 * Get the string representation of the numeric week number of the year
1467 * (equivalent to the format specifier 'W').
1468 * @return {String} '00' through '52'
1470 Date.prototype.getWeekOfYear = function() {
1471 // Skip to Thursday of this week
1472 var now = this.getDayOfYear() + (4 - this.getDay());
1473 // Find the first Thursday of the year
1474 var jan1 = new Date(this.getFullYear(), 0, 1);
1475 var then = (7 - jan1.getDay() + 4);
1476 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1480 * Whether or not the current date is in a leap year.
1481 * @return {Boolean} True if the current date is in a leap year, else false
1483 Date.prototype.isLeapYear = function() {
1484 var year = this.getFullYear();
1485 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1489 * Get the first day of the current month, adjusted for leap year. The returned value
1490 * is the numeric day index within the week (0-6) which can be used in conjunction with
1491 * the {@link #monthNames} array to retrieve the textual day name.
1494 var dt = new Date('1/10/2007');
1495 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1497 * @return {Number} The day number (0-6)
1499 Date.prototype.getFirstDayOfMonth = function() {
1500 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1501 return (day < 0) ? (day + 7) : day;
1505 * Get the last day of the current month, adjusted for leap year. The returned value
1506 * is the numeric day index within the week (0-6) which can be used in conjunction with
1507 * the {@link #monthNames} array to retrieve the textual day name.
1510 var dt = new Date('1/10/2007');
1511 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1513 * @return {Number} The day number (0-6)
1515 Date.prototype.getLastDayOfMonth = function() {
1516 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1517 return (day < 0) ? (day + 7) : day;
1522 * Get the first date of this date's month
1525 Date.prototype.getFirstDateOfMonth = function() {
1526 return new Date(this.getFullYear(), this.getMonth(), 1);
1530 * Get the last date of this date's month
1533 Date.prototype.getLastDateOfMonth = function() {
1534 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1537 * Get the number of days in the current month, adjusted for leap year.
1538 * @return {Number} The number of days in the month
1540 Date.prototype.getDaysInMonth = function() {
1541 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1542 return Date.daysInMonth[this.getMonth()];
1546 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1547 * @return {String} 'st, 'nd', 'rd' or 'th'
1549 Date.prototype.getSuffix = function() {
1550 switch (this.getDate()) {
1567 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1570 * An array of textual month names.
1571 * Override these values for international dates, for example...
1572 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1591 * An array of textual day names.
1592 * Override these values for international dates, for example...
1593 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1609 Date.monthNumbers = {
1624 * Creates and returns a new Date instance with the exact same date value as the called instance.
1625 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1626 * variable will also be changed. When the intention is to create a new variable that will not
1627 * modify the original instance, you should create a clone.
1629 * Example of correctly cloning a date:
1632 var orig = new Date('10/1/2006');
1635 document.write(orig); //returns 'Thu Oct 05 2006'!
1638 var orig = new Date('10/1/2006');
1639 var copy = orig.clone();
1641 document.write(orig); //returns 'Thu Oct 01 2006'
1643 * @return {Date} The new Date instance
1645 Date.prototype.clone = function() {
1646 return new Date(this.getTime());
1650 * Clears any time information from this date
1651 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1652 @return {Date} this or the clone
1654 Date.prototype.clearTime = function(clone){
1656 return this.clone().clearTime();
1661 this.setMilliseconds(0);
1666 // safari setMonth is broken
1668 Date.brokenSetMonth = Date.prototype.setMonth;
1669 Date.prototype.setMonth = function(num){
1671 var n = Math.ceil(-num);
1672 var back_year = Math.ceil(n/12);
1673 var month = (n % 12) ? 12 - n % 12 : 0 ;
1674 this.setFullYear(this.getFullYear() - back_year);
1675 return Date.brokenSetMonth.call(this, month);
1677 return Date.brokenSetMonth.apply(this, arguments);
1682 /** Date interval constant
1686 /** Date interval constant
1690 /** Date interval constant
1694 /** Date interval constant
1698 /** Date interval constant
1702 /** Date interval constant
1706 /** Date interval constant
1712 * Provides a convenient method of performing basic date arithmetic. This method
1713 * does not modify the Date instance being called - it creates and returns
1714 * a new Date instance containing the resulting date value.
1719 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1720 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1722 //Negative values will subtract correctly:
1723 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1724 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1726 //You can even chain several calls together in one line!
1727 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1728 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1731 * @param {String} interval A valid date interval enum value
1732 * @param {Number} value The amount to add to the current date
1733 * @return {Date} The new Date instance
1735 Date.prototype.add = function(interval, value){
1736 var d = this.clone();
1737 if (!interval || value === 0) return d;
1738 switch(interval.toLowerCase()){
1740 d.setMilliseconds(this.getMilliseconds() + value);
1743 d.setSeconds(this.getSeconds() + value);
1746 d.setMinutes(this.getMinutes() + value);
1749 d.setHours(this.getHours() + value);
1752 d.setDate(this.getDate() + value);
1755 var day = this.getDate();
1757 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1760 d.setMonth(this.getMonth() + value);
1763 d.setFullYear(this.getFullYear() + value);
1770 * Ext JS Library 1.1.1
1771 * Copyright(c) 2006-2007, Ext JS, LLC.
1773 * Originally Released Under LGPL - original licence link has changed is not relivant.
1776 * <script type="text/javascript">
1780 * @class Roo.lib.Dom
1783 * Dom utils (from YIU afaik)
1788 * Get the view width
1789 * @param {Boolean} full True will get the full document, otherwise it's the view width
1790 * @return {Number} The width
1793 getViewWidth : function(full) {
1794 return full ? this.getDocumentWidth() : this.getViewportWidth();
1797 * Get the view height
1798 * @param {Boolean} full True will get the full document, otherwise it's the view height
1799 * @return {Number} The height
1801 getViewHeight : function(full) {
1802 return full ? this.getDocumentHeight() : this.getViewportHeight();
1805 getDocumentHeight: function() {
1806 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1807 return Math.max(scrollHeight, this.getViewportHeight());
1810 getDocumentWidth: function() {
1811 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1812 return Math.max(scrollWidth, this.getViewportWidth());
1815 getViewportHeight: function() {
1816 var height = self.innerHeight;
1817 var mode = document.compatMode;
1819 if ((mode || Roo.isIE) && !Roo.isOpera) {
1820 height = (mode == "CSS1Compat") ?
1821 document.documentElement.clientHeight :
1822 document.body.clientHeight;
1828 getViewportWidth: function() {
1829 var width = self.innerWidth;
1830 var mode = document.compatMode;
1832 if (mode || Roo.isIE) {
1833 width = (mode == "CSS1Compat") ?
1834 document.documentElement.clientWidth :
1835 document.body.clientWidth;
1840 isAncestor : function(p, c) {
1847 if (p.contains && !Roo.isSafari) {
1848 return p.contains(c);
1849 } else if (p.compareDocumentPosition) {
1850 return !!(p.compareDocumentPosition(c) & 16);
1852 var parent = c.parentNode;
1857 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1860 parent = parent.parentNode;
1866 getRegion : function(el) {
1867 return Roo.lib.Region.getRegion(el);
1870 getY : function(el) {
1871 return this.getXY(el)[1];
1874 getX : function(el) {
1875 return this.getXY(el)[0];
1878 getXY : function(el) {
1879 var p, pe, b, scroll, bd = document.body;
1880 el = Roo.getDom(el);
1881 var fly = Roo.lib.AnimBase.fly;
1882 if (el.getBoundingClientRect) {
1883 b = el.getBoundingClientRect();
1884 scroll = fly(document).getScroll();
1885 return [b.left + scroll.left, b.top + scroll.top];
1891 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1898 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1905 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1906 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1913 if (p != el && pe.getStyle('overflow') != 'visible') {
1921 if (Roo.isSafari && hasAbsolute) {
1926 if (Roo.isGecko && !hasAbsolute) {
1928 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1929 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1933 while (p && p != bd) {
1934 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1946 setXY : function(el, xy) {
1947 el = Roo.fly(el, '_setXY');
1949 var pts = el.translatePoints(xy);
1950 if (xy[0] !== false) {
1951 el.dom.style.left = pts.left + "px";
1953 if (xy[1] !== false) {
1954 el.dom.style.top = pts.top + "px";
1958 setX : function(el, x) {
1959 this.setXY(el, [x, false]);
1962 setY : function(el, y) {
1963 this.setXY(el, [false, y]);
1967 * Portions of this file are based on pieces of Yahoo User Interface Library
1968 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1969 * YUI licensed under the BSD License:
1970 * http://developer.yahoo.net/yui/license.txt
1971 * <script type="text/javascript">
1975 Roo.lib.Event = function() {
1976 var loadComplete = false;
1978 var unloadListeners = [];
1980 var onAvailStack = [];
1982 var lastError = null;
1995 startInterval: function() {
1996 if (!this._interval) {
1998 var callback = function() {
1999 self._tryPreloadAttach();
2001 this._interval = setInterval(callback, this.POLL_INTERVAL);
2006 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2007 onAvailStack.push({ id: p_id,
2010 override: p_override,
2011 checkReady: false });
2013 retryCount = this.POLL_RETRYS;
2014 this.startInterval();
2018 addListener: function(el, eventName, fn) {
2019 el = Roo.getDom(el);
2024 if ("unload" == eventName) {
2025 unloadListeners[unloadListeners.length] =
2026 [el, eventName, fn];
2030 var wrappedFn = function(e) {
2031 return fn(Roo.lib.Event.getEvent(e));
2034 var li = [el, eventName, fn, wrappedFn];
2036 var index = listeners.length;
2037 listeners[index] = li;
2039 this.doAdd(el, eventName, wrappedFn, false);
2045 removeListener: function(el, eventName, fn) {
2048 el = Roo.getDom(el);
2051 return this.purgeElement(el, false, eventName);
2055 if ("unload" == eventName) {
2057 for (i = 0,len = unloadListeners.length; i < len; i++) {
2058 var li = unloadListeners[i];
2061 li[1] == eventName &&
2063 unloadListeners.splice(i, 1);
2071 var cacheItem = null;
2074 var index = arguments[3];
2076 if ("undefined" == typeof index) {
2077 index = this._getCacheIndex(el, eventName, fn);
2081 cacheItem = listeners[index];
2084 if (!el || !cacheItem) {
2088 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2090 delete listeners[index][this.WFN];
2091 delete listeners[index][this.FN];
2092 listeners.splice(index, 1);
2099 getTarget: function(ev, resolveTextNode) {
2100 ev = ev.browserEvent || ev;
2101 var t = ev.target || ev.srcElement;
2102 return this.resolveTextNode(t);
2106 resolveTextNode: function(node) {
2107 if (Roo.isSafari && node && 3 == node.nodeType) {
2108 return node.parentNode;
2115 getPageX: function(ev) {
2116 ev = ev.browserEvent || ev;
2118 if (!x && 0 !== x) {
2119 x = ev.clientX || 0;
2122 x += this.getScroll()[1];
2130 getPageY: function(ev) {
2131 ev = ev.browserEvent || ev;
2133 if (!y && 0 !== y) {
2134 y = ev.clientY || 0;
2137 y += this.getScroll()[0];
2146 getXY: function(ev) {
2147 ev = ev.browserEvent || ev;
2148 return [this.getPageX(ev), this.getPageY(ev)];
2152 getRelatedTarget: function(ev) {
2153 ev = ev.browserEvent || ev;
2154 var t = ev.relatedTarget;
2156 if (ev.type == "mouseout") {
2158 } else if (ev.type == "mouseover") {
2163 return this.resolveTextNode(t);
2167 getTime: function(ev) {
2168 ev = ev.browserEvent || ev;
2170 var t = new Date().getTime();
2174 this.lastError = ex;
2183 stopEvent: function(ev) {
2184 this.stopPropagation(ev);
2185 this.preventDefault(ev);
2189 stopPropagation: function(ev) {
2190 ev = ev.browserEvent || ev;
2191 if (ev.stopPropagation) {
2192 ev.stopPropagation();
2194 ev.cancelBubble = true;
2199 preventDefault: function(ev) {
2200 ev = ev.browserEvent || ev;
2201 if(ev.preventDefault) {
2202 ev.preventDefault();
2204 ev.returnValue = false;
2209 getEvent: function(e) {
2210 var ev = e || window.event;
2212 var c = this.getEvent.caller;
2214 ev = c.arguments[0];
2215 if (ev && Event == ev.constructor) {
2225 getCharCode: function(ev) {
2226 ev = ev.browserEvent || ev;
2227 return ev.charCode || ev.keyCode || 0;
2231 _getCacheIndex: function(el, eventName, fn) {
2232 for (var i = 0,len = listeners.length; i < len; ++i) {
2233 var li = listeners[i];
2235 li[this.FN] == fn &&
2236 li[this.EL] == el &&
2237 li[this.TYPE] == eventName) {
2249 getEl: function(id) {
2250 return document.getElementById(id);
2254 clearCache: function() {
2258 _load: function(e) {
2259 loadComplete = true;
2260 var EU = Roo.lib.Event;
2264 EU.doRemove(window, "load", EU._load);
2269 _tryPreloadAttach: function() {
2278 var tryAgain = !loadComplete;
2280 tryAgain = (retryCount > 0);
2285 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2286 var item = onAvailStack[i];
2288 var el = this.getEl(item.id);
2291 if (!item.checkReady ||
2294 (document && document.body)) {
2297 if (item.override) {
2298 if (item.override === true) {
2301 scope = item.override;
2304 item.fn.call(scope, item.obj);
2305 onAvailStack[i] = null;
2308 notAvail.push(item);
2313 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2317 this.startInterval();
2319 clearInterval(this._interval);
2320 this._interval = null;
2323 this.locked = false;
2330 purgeElement: function(el, recurse, eventName) {
2331 var elListeners = this.getListeners(el, eventName);
2333 for (var i = 0,len = elListeners.length; i < len; ++i) {
2334 var l = elListeners[i];
2335 this.removeListener(el, l.type, l.fn);
2339 if (recurse && el && el.childNodes) {
2340 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2341 this.purgeElement(el.childNodes[i], recurse, eventName);
2347 getListeners: function(el, eventName) {
2348 var results = [], searchLists;
2350 searchLists = [listeners, unloadListeners];
2351 } else if (eventName == "unload") {
2352 searchLists = [unloadListeners];
2354 searchLists = [listeners];
2357 for (var j = 0; j < searchLists.length; ++j) {
2358 var searchList = searchLists[j];
2359 if (searchList && searchList.length > 0) {
2360 for (var i = 0,len = searchList.length; i < len; ++i) {
2361 var l = searchList[i];
2362 if (l && l[this.EL] === el &&
2363 (!eventName || eventName === l[this.TYPE])) {
2368 adjust: l[this.ADJ_SCOPE],
2376 return (results.length) ? results : null;
2380 _unload: function(e) {
2382 var EU = Roo.lib.Event, i, j, l, len, index;
2384 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2385 l = unloadListeners[i];
2388 if (l[EU.ADJ_SCOPE]) {
2389 if (l[EU.ADJ_SCOPE] === true) {
2392 scope = l[EU.ADJ_SCOPE];
2395 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2396 unloadListeners[i] = null;
2402 unloadListeners = null;
2404 if (listeners && listeners.length > 0) {
2405 j = listeners.length;
2408 l = listeners[index];
2410 EU.removeListener(l[EU.EL], l[EU.TYPE],
2420 EU.doRemove(window, "unload", EU._unload);
2425 getScroll: function() {
2426 var dd = document.documentElement, db = document.body;
2427 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2428 return [dd.scrollTop, dd.scrollLeft];
2430 return [db.scrollTop, db.scrollLeft];
2437 doAdd: function () {
2438 if (window.addEventListener) {
2439 return function(el, eventName, fn, capture) {
2440 el.addEventListener(eventName, fn, (capture));
2442 } else if (window.attachEvent) {
2443 return function(el, eventName, fn, capture) {
2444 el.attachEvent("on" + eventName, fn);
2453 doRemove: function() {
2454 if (window.removeEventListener) {
2455 return function (el, eventName, fn, capture) {
2456 el.removeEventListener(eventName, fn, (capture));
2458 } else if (window.detachEvent) {
2459 return function (el, eventName, fn) {
2460 el.detachEvent("on" + eventName, fn);
2472 var E = Roo.lib.Event;
2473 E.on = E.addListener;
2474 E.un = E.removeListener;
2476 if (document && document.body) {
2479 E.doAdd(window, "load", E._load);
2481 E.doAdd(window, "unload", E._unload);
2482 E._tryPreloadAttach();
2486 * Portions of this file are based on pieces of Yahoo User Interface Library
2487 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2488 * YUI licensed under the BSD License:
2489 * http://developer.yahoo.net/yui/license.txt
2490 * <script type="text/javascript">
2496 * @class Roo.lib.Ajax
2503 request : function(method, uri, cb, data, options) {
2505 var hs = options.headers;
2508 if(hs.hasOwnProperty(h)){
2509 this.initHeader(h, hs[h], false);
2513 if(options.xmlData){
2514 this.initHeader('Content-Type', 'text/xml', false);
2516 data = options.xmlData;
2520 return this.asyncRequest(method, uri, cb, data);
2523 serializeForm : function(form) {
2524 if(typeof form == 'string') {
2525 form = (document.getElementById(form) || document.forms[form]);
2528 var el, name, val, disabled, data = '', hasSubmit = false;
2529 for (var i = 0; i < form.elements.length; i++) {
2530 el = form.elements[i];
2531 disabled = form.elements[i].disabled;
2532 name = form.elements[i].name;
2533 val = form.elements[i].value;
2535 if (!disabled && name){
2539 case 'select-multiple':
2540 for (var j = 0; j < el.options.length; j++) {
2541 if (el.options[j].selected) {
2543 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2546 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2554 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2567 if(hasSubmit == false) {
2568 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2573 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2578 data = data.substr(0, data.length - 1);
2586 useDefaultHeader:true,
2588 defaultPostHeader:'application/x-www-form-urlencoded',
2590 useDefaultXhrHeader:true,
2592 defaultXhrHeader:'XMLHttpRequest',
2594 hasDefaultHeaders:true,
2606 setProgId:function(id)
2608 this.activeX.unshift(id);
2611 setDefaultPostHeader:function(b)
2613 this.useDefaultHeader = b;
2616 setDefaultXhrHeader:function(b)
2618 this.useDefaultXhrHeader = b;
2621 setPollingInterval:function(i)
2623 if (typeof i == 'number' && isFinite(i)) {
2624 this.pollInterval = i;
2628 createXhrObject:function(transactionId)
2634 http = new XMLHttpRequest();
2636 obj = { conn:http, tId:transactionId };
2640 for (var i = 0; i < this.activeX.length; ++i) {
2644 http = new ActiveXObject(this.activeX[i]);
2646 obj = { conn:http, tId:transactionId };
2659 getConnectionObject:function()
2662 var tId = this.transactionId;
2666 o = this.createXhrObject(tId);
2668 this.transactionId++;
2679 asyncRequest:function(method, uri, callback, postData)
2681 var o = this.getConnectionObject();
2687 o.conn.open(method, uri, true);
2689 if (this.useDefaultXhrHeader) {
2690 if (!this.defaultHeaders['X-Requested-With']) {
2691 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2695 if(postData && this.useDefaultHeader){
2696 this.initHeader('Content-Type', this.defaultPostHeader);
2699 if (this.hasDefaultHeaders || this.hasHeaders) {
2703 this.handleReadyState(o, callback);
2704 o.conn.send(postData || null);
2710 handleReadyState:function(o, callback)
2714 if (callback && callback.timeout) {
2716 this.timeout[o.tId] = window.setTimeout(function() {
2717 oConn.abort(o, callback, true);
2718 }, callback.timeout);
2721 this.poll[o.tId] = window.setInterval(
2723 if (o.conn && o.conn.readyState == 4) {
2724 window.clearInterval(oConn.poll[o.tId]);
2725 delete oConn.poll[o.tId];
2727 if(callback && callback.timeout) {
2728 window.clearTimeout(oConn.timeout[o.tId]);
2729 delete oConn.timeout[o.tId];
2732 oConn.handleTransactionResponse(o, callback);
2735 , this.pollInterval);
2738 handleTransactionResponse:function(o, callback, isAbort)
2742 this.releaseObject(o);
2746 var httpStatus, responseObject;
2750 if (o.conn.status !== undefined && o.conn.status != 0) {
2751 httpStatus = o.conn.status;
2763 if (httpStatus >= 200 && httpStatus < 300) {
2764 responseObject = this.createResponseObject(o, callback.argument);
2765 if (callback.success) {
2766 if (!callback.scope) {
2767 callback.success(responseObject);
2772 callback.success.apply(callback.scope, [responseObject]);
2777 switch (httpStatus) {
2785 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2786 if (callback.failure) {
2787 if (!callback.scope) {
2788 callback.failure(responseObject);
2791 callback.failure.apply(callback.scope, [responseObject]);
2796 responseObject = this.createResponseObject(o, callback.argument);
2797 if (callback.failure) {
2798 if (!callback.scope) {
2799 callback.failure(responseObject);
2802 callback.failure.apply(callback.scope, [responseObject]);
2808 this.releaseObject(o);
2809 responseObject = null;
2812 createResponseObject:function(o, callbackArg)
2819 var headerStr = o.conn.getAllResponseHeaders();
2820 var header = headerStr.split('\n');
2821 for (var i = 0; i < header.length; i++) {
2822 var delimitPos = header[i].indexOf(':');
2823 if (delimitPos != -1) {
2824 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2832 obj.status = o.conn.status;
2833 obj.statusText = o.conn.statusText;
2834 obj.getResponseHeader = headerObj;
2835 obj.getAllResponseHeaders = headerStr;
2836 obj.responseText = o.conn.responseText;
2837 obj.responseXML = o.conn.responseXML;
2839 if (typeof callbackArg !== undefined) {
2840 obj.argument = callbackArg;
2846 createExceptionObject:function(tId, callbackArg, isAbort)
2849 var COMM_ERROR = 'communication failure';
2850 var ABORT_CODE = -1;
2851 var ABORT_ERROR = 'transaction aborted';
2857 obj.status = ABORT_CODE;
2858 obj.statusText = ABORT_ERROR;
2861 obj.status = COMM_CODE;
2862 obj.statusText = COMM_ERROR;
2866 obj.argument = callbackArg;
2872 initHeader:function(label, value, isDefault)
2874 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2876 if (headerObj[label] === undefined) {
2877 headerObj[label] = value;
2882 headerObj[label] = value + "," + headerObj[label];
2886 this.hasDefaultHeaders = true;
2889 this.hasHeaders = true;
2894 setHeader:function(o)
2896 if (this.hasDefaultHeaders) {
2897 for (var prop in this.defaultHeaders) {
2898 if (this.defaultHeaders.hasOwnProperty(prop)) {
2899 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2904 if (this.hasHeaders) {
2905 for (var prop in this.headers) {
2906 if (this.headers.hasOwnProperty(prop)) {
2907 o.conn.setRequestHeader(prop, this.headers[prop]);
2911 this.hasHeaders = false;
2915 resetDefaultHeaders:function() {
2916 delete this.defaultHeaders;
2917 this.defaultHeaders = {};
2918 this.hasDefaultHeaders = false;
2921 abort:function(o, callback, isTimeout)
2923 if(this.isCallInProgress(o)) {
2925 window.clearInterval(this.poll[o.tId]);
2926 delete this.poll[o.tId];
2928 delete this.timeout[o.tId];
2931 this.handleTransactionResponse(o, callback, true);
2941 isCallInProgress:function(o)
2944 return o.conn.readyState != 4 && o.conn.readyState != 0;
2953 releaseObject:function(o)
2962 'MSXML2.XMLHTTP.3.0',
2970 * Portions of this file are based on pieces of Yahoo User Interface Library
2971 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2972 * YUI licensed under the BSD License:
2973 * http://developer.yahoo.net/yui/license.txt
2974 * <script type="text/javascript">
2978 Roo.lib.Region = function(t, r, b, l) {
2988 Roo.lib.Region.prototype = {
2989 contains : function(region) {
2990 return ( region.left >= this.left &&
2991 region.right <= this.right &&
2992 region.top >= this.top &&
2993 region.bottom <= this.bottom );
2997 getArea : function() {
2998 return ( (this.bottom - this.top) * (this.right - this.left) );
3001 intersect : function(region) {
3002 var t = Math.max(this.top, region.top);
3003 var r = Math.min(this.right, region.right);
3004 var b = Math.min(this.bottom, region.bottom);
3005 var l = Math.max(this.left, region.left);
3007 if (b >= t && r >= l) {
3008 return new Roo.lib.Region(t, r, b, l);
3013 union : function(region) {
3014 var t = Math.min(this.top, region.top);
3015 var r = Math.max(this.right, region.right);
3016 var b = Math.max(this.bottom, region.bottom);
3017 var l = Math.min(this.left, region.left);
3019 return new Roo.lib.Region(t, r, b, l);
3022 adjust : function(t, l, b, r) {
3031 Roo.lib.Region.getRegion = function(el) {
3032 var p = Roo.lib.Dom.getXY(el);
3035 var r = p[0] + el.offsetWidth;
3036 var b = p[1] + el.offsetHeight;
3039 return new Roo.lib.Region(t, r, b, l);
3042 * Portions of this file are based on pieces of Yahoo User Interface Library
3043 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3044 * YUI licensed under the BSD License:
3045 * http://developer.yahoo.net/yui/license.txt
3046 * <script type="text/javascript">
3049 //@@dep Roo.lib.Region
3052 Roo.lib.Point = function(x, y) {
3053 if (x instanceof Array) {
3057 this.x = this.right = this.left = this[0] = x;
3058 this.y = this.top = this.bottom = this[1] = y;
3061 Roo.lib.Point.prototype = new Roo.lib.Region();
3063 * Portions of this file are based on pieces of Yahoo User Interface Library
3064 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3065 * YUI licensed under the BSD License:
3066 * http://developer.yahoo.net/yui/license.txt
3067 * <script type="text/javascript">
3074 scroll : function(el, args, duration, easing, cb, scope) {
3075 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3078 motion : function(el, args, duration, easing, cb, scope) {
3079 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3082 color : function(el, args, duration, easing, cb, scope) {
3083 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3086 run : function(el, args, duration, easing, cb, scope, type) {
3087 type = type || Roo.lib.AnimBase;
3088 if (typeof easing == "string") {
3089 easing = Roo.lib.Easing[easing];
3091 var anim = new type(el, args, duration, easing);
3092 anim.animateX(function() {
3093 Roo.callback(cb, scope);
3099 * Portions of this file are based on pieces of Yahoo User Interface Library
3100 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3101 * YUI licensed under the BSD License:
3102 * http://developer.yahoo.net/yui/license.txt
3103 * <script type="text/javascript">
3111 if (!libFlyweight) {
3112 libFlyweight = new Roo.Element.Flyweight();
3114 libFlyweight.dom = el;
3115 return libFlyweight;
3118 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3122 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3124 this.init(el, attributes, duration, method);
3128 Roo.lib.AnimBase.fly = fly;
3132 Roo.lib.AnimBase.prototype = {
3134 toString: function() {
3135 var el = this.getEl();
3136 var id = el.id || el.tagName;
3137 return ("Anim " + id);
3141 noNegatives: /width|height|opacity|padding/i,
3142 offsetAttribute: /^((width|height)|(top|left))$/,
3143 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3144 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3148 doMethod: function(attr, start, end) {
3149 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3153 setAttribute: function(attr, val, unit) {
3154 if (this.patterns.noNegatives.test(attr)) {
3155 val = (val > 0) ? val : 0;
3158 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3162 getAttribute: function(attr) {
3163 var el = this.getEl();
3164 var val = fly(el).getStyle(attr);
3166 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3167 return parseFloat(val);
3170 var a = this.patterns.offsetAttribute.exec(attr) || [];
3171 var pos = !!( a[3] );
3172 var box = !!( a[2] );
3175 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3176 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3185 getDefaultUnit: function(attr) {
3186 if (this.patterns.defaultUnit.test(attr)) {
3193 animateX : function(callback, scope) {
3194 var f = function() {
3195 this.onComplete.removeListener(f);
3196 if (typeof callback == "function") {
3197 callback.call(scope || this, this);
3200 this.onComplete.addListener(f, this);
3205 setRuntimeAttribute: function(attr) {
3208 var attributes = this.attributes;
3210 this.runtimeAttributes[attr] = {};
3212 var isset = function(prop) {
3213 return (typeof prop !== 'undefined');
3216 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3220 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3223 if (isset(attributes[attr]['to'])) {
3224 end = attributes[attr]['to'];
3225 } else if (isset(attributes[attr]['by'])) {
3226 if (start.constructor == Array) {
3228 for (var i = 0, len = start.length; i < len; ++i) {
3229 end[i] = start[i] + attributes[attr]['by'][i];
3232 end = start + attributes[attr]['by'];
3236 this.runtimeAttributes[attr].start = start;
3237 this.runtimeAttributes[attr].end = end;
3240 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3244 init: function(el, attributes, duration, method) {
3246 var isAnimated = false;
3249 var startTime = null;
3252 var actualFrames = 0;
3255 el = Roo.getDom(el);
3258 this.attributes = attributes || {};
3261 this.duration = duration || 1;
3264 this.method = method || Roo.lib.Easing.easeNone;
3267 this.useSeconds = true;
3270 this.currentFrame = 0;
3273 this.totalFrames = Roo.lib.AnimMgr.fps;
3276 this.getEl = function() {
3281 this.isAnimated = function() {
3286 this.getStartTime = function() {
3290 this.runtimeAttributes = {};
3293 this.animate = function() {
3294 if (this.isAnimated()) {
3298 this.currentFrame = 0;
3300 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3302 Roo.lib.AnimMgr.registerElement(this);
3306 this.stop = function(finish) {
3308 this.currentFrame = this.totalFrames;
3309 this._onTween.fire();
3311 Roo.lib.AnimMgr.stop(this);
3314 var onStart = function() {
3315 this.onStart.fire();
3317 this.runtimeAttributes = {};
3318 for (var attr in this.attributes) {
3319 this.setRuntimeAttribute(attr);
3324 startTime = new Date();
3328 var onTween = function() {
3330 duration: new Date() - this.getStartTime(),
3331 currentFrame: this.currentFrame
3334 data.toString = function() {
3336 'duration: ' + data.duration +
3337 ', currentFrame: ' + data.currentFrame
3341 this.onTween.fire(data);
3343 var runtimeAttributes = this.runtimeAttributes;
3345 for (var attr in runtimeAttributes) {
3346 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3352 var onComplete = function() {
3353 var actual_duration = (new Date() - startTime) / 1000 ;
3356 duration: actual_duration,
3357 frames: actualFrames,
3358 fps: actualFrames / actual_duration
3361 data.toString = function() {
3363 'duration: ' + data.duration +
3364 ', frames: ' + data.frames +
3365 ', fps: ' + data.fps
3371 this.onComplete.fire(data);
3375 this._onStart = new Roo.util.Event(this);
3376 this.onStart = new Roo.util.Event(this);
3377 this.onTween = new Roo.util.Event(this);
3378 this._onTween = new Roo.util.Event(this);
3379 this.onComplete = new Roo.util.Event(this);
3380 this._onComplete = new Roo.util.Event(this);
3381 this._onStart.addListener(onStart);
3382 this._onTween.addListener(onTween);
3383 this._onComplete.addListener(onComplete);
3388 * Portions of this file are based on pieces of Yahoo User Interface Library
3389 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3390 * YUI licensed under the BSD License:
3391 * http://developer.yahoo.net/yui/license.txt
3392 * <script type="text/javascript">
3396 Roo.lib.AnimMgr = new function() {
3413 this.registerElement = function(tween) {
3414 queue[queue.length] = tween;
3416 tween._onStart.fire();
3421 this.unRegister = function(tween, index) {
3422 tween._onComplete.fire();
3423 index = index || getIndex(tween);
3425 queue.splice(index, 1);
3429 if (tweenCount <= 0) {
3435 this.start = function() {
3436 if (thread === null) {
3437 thread = setInterval(this.run, this.delay);
3442 this.stop = function(tween) {
3444 clearInterval(thread);
3446 for (var i = 0, len = queue.length; i < len; ++i) {
3447 if (queue[0].isAnimated()) {
3448 this.unRegister(queue[0], 0);
3457 this.unRegister(tween);
3462 this.run = function() {
3463 for (var i = 0, len = queue.length; i < len; ++i) {
3464 var tween = queue[i];
3465 if (!tween || !tween.isAnimated()) {
3469 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3471 tween.currentFrame += 1;
3473 if (tween.useSeconds) {
3474 correctFrame(tween);
3476 tween._onTween.fire();
3479 Roo.lib.AnimMgr.stop(tween, i);
3484 var getIndex = function(anim) {
3485 for (var i = 0, len = queue.length; i < len; ++i) {
3486 if (queue[i] == anim) {
3494 var correctFrame = function(tween) {
3495 var frames = tween.totalFrames;
3496 var frame = tween.currentFrame;
3497 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3498 var elapsed = (new Date() - tween.getStartTime());
3501 if (elapsed < tween.duration * 1000) {
3502 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3504 tweak = frames - (frame + 1);
3506 if (tweak > 0 && isFinite(tweak)) {
3507 if (tween.currentFrame + tweak >= frames) {
3508 tweak = frames - (frame + 1);
3511 tween.currentFrame += tweak;
3515 * Portions of this file are based on pieces of Yahoo User Interface Library
3516 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3517 * YUI licensed under the BSD License:
3518 * http://developer.yahoo.net/yui/license.txt
3519 * <script type="text/javascript">
3522 Roo.lib.Bezier = new function() {
3524 this.getPosition = function(points, t) {
3525 var n = points.length;
3528 for (var i = 0; i < n; ++i) {
3529 tmp[i] = [points[i][0], points[i][1]];
3532 for (var j = 1; j < n; ++j) {
3533 for (i = 0; i < n - j; ++i) {
3534 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3535 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3539 return [ tmp[0][0], tmp[0][1] ];
3543 * Portions of this file are based on pieces of Yahoo User Interface Library
3544 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3545 * YUI licensed under the BSD License:
3546 * http://developer.yahoo.net/yui/license.txt
3547 * <script type="text/javascript">
3552 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3553 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3556 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3558 var fly = Roo.lib.AnimBase.fly;
3560 var superclass = Y.ColorAnim.superclass;
3561 var proto = Y.ColorAnim.prototype;
3563 proto.toString = function() {
3564 var el = this.getEl();
3565 var id = el.id || el.tagName;
3566 return ("ColorAnim " + id);
3569 proto.patterns.color = /color$/i;
3570 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3571 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3572 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3573 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3576 proto.parseColor = function(s) {
3577 if (s.length == 3) {
3581 var c = this.patterns.hex.exec(s);
3582 if (c && c.length == 4) {
3583 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3586 c = this.patterns.rgb.exec(s);
3587 if (c && c.length == 4) {
3588 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3591 c = this.patterns.hex3.exec(s);
3592 if (c && c.length == 4) {
3593 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3598 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3599 proto.getAttribute = function(attr) {
3600 var el = this.getEl();
3601 if (this.patterns.color.test(attr)) {
3602 var val = fly(el).getStyle(attr);
3604 if (this.patterns.transparent.test(val)) {
3605 var parent = el.parentNode;
3606 val = fly(parent).getStyle(attr);
3608 while (parent && this.patterns.transparent.test(val)) {
3609 parent = parent.parentNode;
3610 val = fly(parent).getStyle(attr);
3611 if (parent.tagName.toUpperCase() == 'HTML') {
3617 val = superclass.getAttribute.call(this, attr);
3622 proto.getAttribute = function(attr) {
3623 var el = this.getEl();
3624 if (this.patterns.color.test(attr)) {
3625 var val = fly(el).getStyle(attr);
3627 if (this.patterns.transparent.test(val)) {
3628 var parent = el.parentNode;
3629 val = fly(parent).getStyle(attr);
3631 while (parent && this.patterns.transparent.test(val)) {
3632 parent = parent.parentNode;
3633 val = fly(parent).getStyle(attr);
3634 if (parent.tagName.toUpperCase() == 'HTML') {
3640 val = superclass.getAttribute.call(this, attr);
3646 proto.doMethod = function(attr, start, end) {
3649 if (this.patterns.color.test(attr)) {
3651 for (var i = 0, len = start.length; i < len; ++i) {
3652 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3655 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3658 val = superclass.doMethod.call(this, attr, start, end);
3664 proto.setRuntimeAttribute = function(attr) {
3665 superclass.setRuntimeAttribute.call(this, attr);
3667 if (this.patterns.color.test(attr)) {
3668 var attributes = this.attributes;
3669 var start = this.parseColor(this.runtimeAttributes[attr].start);
3670 var end = this.parseColor(this.runtimeAttributes[attr].end);
3672 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3673 end = this.parseColor(attributes[attr].by);
3675 for (var i = 0, len = start.length; i < len; ++i) {
3676 end[i] = start[i] + end[i];
3680 this.runtimeAttributes[attr].start = start;
3681 this.runtimeAttributes[attr].end = end;
3687 * Portions of this file are based on pieces of Yahoo User Interface Library
3688 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3689 * YUI licensed under the BSD License:
3690 * http://developer.yahoo.net/yui/license.txt
3691 * <script type="text/javascript">
3697 easeNone: function (t, b, c, d) {
3698 return c * t / d + b;
3702 easeIn: function (t, b, c, d) {
3703 return c * (t /= d) * t + b;
3707 easeOut: function (t, b, c, d) {
3708 return -c * (t /= d) * (t - 2) + b;
3712 easeBoth: function (t, b, c, d) {
3713 if ((t /= d / 2) < 1) {
3714 return c / 2 * t * t + b;
3717 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3721 easeInStrong: function (t, b, c, d) {
3722 return c * (t /= d) * t * t * t + b;
3726 easeOutStrong: function (t, b, c, d) {
3727 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3731 easeBothStrong: function (t, b, c, d) {
3732 if ((t /= d / 2) < 1) {
3733 return c / 2 * t * t * t * t + b;
3736 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3741 elasticIn: function (t, b, c, d, a, p) {
3745 if ((t /= d) == 1) {
3752 if (!a || a < Math.abs(c)) {
3757 var s = p / (2 * Math.PI) * Math.asin(c / a);
3760 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3764 elasticOut: function (t, b, c, d, a, p) {
3768 if ((t /= d) == 1) {
3775 if (!a || a < Math.abs(c)) {
3780 var s = p / (2 * Math.PI) * Math.asin(c / a);
3783 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3787 elasticBoth: function (t, b, c, d, a, p) {
3792 if ((t /= d / 2) == 2) {
3800 if (!a || a < Math.abs(c)) {
3805 var s = p / (2 * Math.PI) * Math.asin(c / a);
3809 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3810 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3812 return a * Math.pow(2, -10 * (t -= 1)) *
3813 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3818 backIn: function (t, b, c, d, s) {
3819 if (typeof s == 'undefined') {
3822 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3826 backOut: function (t, b, c, d, s) {
3827 if (typeof s == 'undefined') {
3830 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3834 backBoth: function (t, b, c, d, s) {
3835 if (typeof s == 'undefined') {
3839 if ((t /= d / 2 ) < 1) {
3840 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3842 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3846 bounceIn: function (t, b, c, d) {
3847 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3851 bounceOut: function (t, b, c, d) {
3852 if ((t /= d) < (1 / 2.75)) {
3853 return c * (7.5625 * t * t) + b;
3854 } else if (t < (2 / 2.75)) {
3855 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3856 } else if (t < (2.5 / 2.75)) {
3857 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3859 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3863 bounceBoth: function (t, b, c, d) {
3865 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3867 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3870 * Portions of this file are based on pieces of Yahoo User Interface Library
3871 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3872 * YUI licensed under the BSD License:
3873 * http://developer.yahoo.net/yui/license.txt
3874 * <script type="text/javascript">
3878 Roo.lib.Motion = function(el, attributes, duration, method) {
3880 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3884 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3888 var superclass = Y.Motion.superclass;
3889 var proto = Y.Motion.prototype;
3891 proto.toString = function() {
3892 var el = this.getEl();
3893 var id = el.id || el.tagName;
3894 return ("Motion " + id);
3897 proto.patterns.points = /^points$/i;
3899 proto.setAttribute = function(attr, val, unit) {
3900 if (this.patterns.points.test(attr)) {
3901 unit = unit || 'px';
3902 superclass.setAttribute.call(this, 'left', val[0], unit);
3903 superclass.setAttribute.call(this, 'top', val[1], unit);
3905 superclass.setAttribute.call(this, attr, val, unit);
3909 proto.getAttribute = function(attr) {
3910 if (this.patterns.points.test(attr)) {
3912 superclass.getAttribute.call(this, 'left'),
3913 superclass.getAttribute.call(this, 'top')
3916 val = superclass.getAttribute.call(this, attr);
3922 proto.doMethod = function(attr, start, end) {
3925 if (this.patterns.points.test(attr)) {
3926 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3927 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3929 val = superclass.doMethod.call(this, attr, start, end);
3934 proto.setRuntimeAttribute = function(attr) {
3935 if (this.patterns.points.test(attr)) {
3936 var el = this.getEl();
3937 var attributes = this.attributes;
3939 var control = attributes['points']['control'] || [];
3943 if (control.length > 0 && !(control[0] instanceof Array)) {
3944 control = [control];
3947 for (i = 0,len = control.length; i < len; ++i) {
3948 tmp[i] = control[i];
3953 Roo.fly(el).position();
3955 if (isset(attributes['points']['from'])) {
3956 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3959 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3962 start = this.getAttribute('points');
3965 if (isset(attributes['points']['to'])) {
3966 end = translateValues.call(this, attributes['points']['to'], start);
3968 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3969 for (i = 0,len = control.length; i < len; ++i) {
3970 control[i] = translateValues.call(this, control[i], start);
3974 } else if (isset(attributes['points']['by'])) {
3975 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3977 for (i = 0,len = control.length; i < len; ++i) {
3978 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3982 this.runtimeAttributes[attr] = [start];
3984 if (control.length > 0) {
3985 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3988 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3991 superclass.setRuntimeAttribute.call(this, attr);
3995 var translateValues = function(val, start) {
3996 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3997 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4002 var isset = function(prop) {
4003 return (typeof prop !== 'undefined');
4007 * Portions of this file are based on pieces of Yahoo User Interface Library
4008 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4009 * YUI licensed under the BSD License:
4010 * http://developer.yahoo.net/yui/license.txt
4011 * <script type="text/javascript">
4015 Roo.lib.Scroll = function(el, attributes, duration, method) {
4017 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4021 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4025 var superclass = Y.Scroll.superclass;
4026 var proto = Y.Scroll.prototype;
4028 proto.toString = function() {
4029 var el = this.getEl();
4030 var id = el.id || el.tagName;
4031 return ("Scroll " + id);
4034 proto.doMethod = function(attr, start, end) {
4037 if (attr == 'scroll') {
4039 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4040 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4044 val = superclass.doMethod.call(this, attr, start, end);
4049 proto.getAttribute = function(attr) {
4051 var el = this.getEl();
4053 if (attr == 'scroll') {
4054 val = [ el.scrollLeft, el.scrollTop ];
4056 val = superclass.getAttribute.call(this, attr);
4062 proto.setAttribute = function(attr, val, unit) {
4063 var el = this.getEl();
4065 if (attr == 'scroll') {
4066 el.scrollLeft = val[0];
4067 el.scrollTop = val[1];
4069 superclass.setAttribute.call(this, attr, val, unit);
4075 * Ext JS Library 1.1.1
4076 * Copyright(c) 2006-2007, Ext JS, LLC.
4078 * Originally Released Under LGPL - original licence link has changed is not relivant.
4081 * <script type="text/javascript">
4085 // nasty IE9 hack - what a pile of crap that is..
4087 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4088 Range.prototype.createContextualFragment = function (html) {
4089 var doc = window.document;
4090 var container = doc.createElement("div");
4091 container.innerHTML = html;
4092 var frag = doc.createDocumentFragment(), n;
4093 while ((n = container.firstChild)) {
4094 frag.appendChild(n);
4101 * @class Roo.DomHelper
4102 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4103 * 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>.
4106 Roo.DomHelper = function(){
4107 var tempTableEl = null;
4108 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4109 var tableRe = /^table|tbody|tr|td$/i;
4111 // build as innerHTML where available
4113 var createHtml = function(o){
4114 if(typeof o == 'string'){
4123 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4124 if(attr == "style"){
4126 if(typeof s == "function"){
4129 if(typeof s == "string"){
4130 b += ' style="' + s + '"';
4131 }else if(typeof s == "object"){
4134 if(typeof s[key] != "function"){
4135 b += key + ":" + s[key] + ";";
4142 b += ' class="' + o["cls"] + '"';
4143 }else if(attr == "htmlFor"){
4144 b += ' for="' + o["htmlFor"] + '"';
4146 b += " " + attr + '="' + o[attr] + '"';
4150 if(emptyTags.test(o.tag)){
4154 var cn = o.children || o.cn;
4156 //http://bugs.kde.org/show_bug.cgi?id=71506
4157 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4158 for(var i = 0, len = cn.length; i < len; i++) {
4159 b += createHtml(cn[i], b);
4162 b += createHtml(cn, b);
4168 b += "</" + o.tag + ">";
4175 var createDom = function(o, parentNode){
4177 // defininition craeted..
4179 if (o.ns && o.ns != 'html') {
4181 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4182 xmlns[o.ns] = o.xmlns;
4185 if (typeof(xmlns[o.ns]) == 'undefined') {
4186 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4192 if (typeof(o) == 'string') {
4193 return parentNode.appendChild(document.createTextNode(o));
4195 o.tag = o.tag || div;
4196 if (o.ns && Roo.isIE) {
4198 o.tag = o.ns + ':' + o.tag;
4201 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4202 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4205 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4206 attr == "style" || typeof o[attr] == "function") continue;
4208 if(attr=="cls" && Roo.isIE){
4209 el.className = o["cls"];
4211 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4212 else el[attr] = o[attr];
4215 Roo.DomHelper.applyStyles(el, o.style);
4216 var cn = o.children || o.cn;
4218 //http://bugs.kde.org/show_bug.cgi?id=71506
4219 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4220 for(var i = 0, len = cn.length; i < len; i++) {
4221 createDom(cn[i], el);
4228 el.innerHTML = o.html;
4231 parentNode.appendChild(el);
4236 var ieTable = function(depth, s, h, e){
4237 tempTableEl.innerHTML = [s, h, e].join('');
4238 var i = -1, el = tempTableEl;
4245 // kill repeat to save bytes
4249 tbe = '</tbody>'+te,
4255 * Nasty code for IE's broken table implementation
4257 var insertIntoTable = function(tag, where, el, html){
4259 tempTableEl = document.createElement('div');
4264 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4267 if(where == 'beforebegin'){
4271 before = el.nextSibling;
4274 node = ieTable(4, trs, html, tre);
4276 else if(tag == 'tr'){
4277 if(where == 'beforebegin'){
4280 node = ieTable(3, tbs, html, tbe);
4281 } else if(where == 'afterend'){
4282 before = el.nextSibling;
4284 node = ieTable(3, tbs, html, tbe);
4285 } else{ // INTO a TR
4286 if(where == 'afterbegin'){
4287 before = el.firstChild;
4289 node = ieTable(4, trs, html, tre);
4291 } else if(tag == 'tbody'){
4292 if(where == 'beforebegin'){
4295 node = ieTable(2, ts, html, te);
4296 } else if(where == 'afterend'){
4297 before = el.nextSibling;
4299 node = ieTable(2, ts, html, te);
4301 if(where == 'afterbegin'){
4302 before = el.firstChild;
4304 node = ieTable(3, tbs, html, tbe);
4307 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4310 if(where == 'afterbegin'){
4311 before = el.firstChild;
4313 node = ieTable(2, ts, html, te);
4315 el.insertBefore(node, before);
4320 /** True to force the use of DOM instead of html fragments @type Boolean */
4324 * Returns the markup for the passed Element(s) config
4325 * @param {Object} o The Dom object spec (and children)
4328 markup : function(o){
4329 return createHtml(o);
4333 * Applies a style specification to an element
4334 * @param {String/HTMLElement} el The element to apply styles to
4335 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4336 * a function which returns such a specification.
4338 applyStyles : function(el, styles){
4341 if(typeof styles == "string"){
4342 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4344 while ((matches = re.exec(styles)) != null){
4345 el.setStyle(matches[1], matches[2]);
4347 }else if (typeof styles == "object"){
4348 for (var style in styles){
4349 el.setStyle(style, styles[style]);
4351 }else if (typeof styles == "function"){
4352 Roo.DomHelper.applyStyles(el, styles.call());
4358 * Inserts an HTML fragment into the Dom
4359 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4360 * @param {HTMLElement} el The context element
4361 * @param {String} html The HTML fragmenet
4362 * @return {HTMLElement} The new node
4364 insertHtml : function(where, el, html){
4365 where = where.toLowerCase();
4366 if(el.insertAdjacentHTML){
4367 if(tableRe.test(el.tagName)){
4369 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4375 el.insertAdjacentHTML('BeforeBegin', html);
4376 return el.previousSibling;
4378 el.insertAdjacentHTML('AfterBegin', html);
4379 return el.firstChild;
4381 el.insertAdjacentHTML('BeforeEnd', html);
4382 return el.lastChild;
4384 el.insertAdjacentHTML('AfterEnd', html);
4385 return el.nextSibling;
4387 throw 'Illegal insertion point -> "' + where + '"';
4389 var range = el.ownerDocument.createRange();
4393 range.setStartBefore(el);
4394 frag = range.createContextualFragment(html);
4395 el.parentNode.insertBefore(frag, el);
4396 return el.previousSibling;
4399 range.setStartBefore(el.firstChild);
4400 frag = range.createContextualFragment(html);
4401 el.insertBefore(frag, el.firstChild);
4402 return el.firstChild;
4404 el.innerHTML = html;
4405 return el.firstChild;
4409 range.setStartAfter(el.lastChild);
4410 frag = range.createContextualFragment(html);
4411 el.appendChild(frag);
4412 return el.lastChild;
4414 el.innerHTML = html;
4415 return el.lastChild;
4418 range.setStartAfter(el);
4419 frag = range.createContextualFragment(html);
4420 el.parentNode.insertBefore(frag, el.nextSibling);
4421 return el.nextSibling;
4423 throw 'Illegal insertion point -> "' + where + '"';
4427 * Creates new Dom element(s) and inserts them before el
4428 * @param {String/HTMLElement/Element} el The context element
4429 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4430 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4431 * @return {HTMLElement/Roo.Element} The new node
4433 insertBefore : function(el, o, returnElement){
4434 return this.doInsert(el, o, returnElement, "beforeBegin");
4438 * Creates new Dom element(s) and inserts them after el
4439 * @param {String/HTMLElement/Element} el The context element
4440 * @param {Object} o The Dom object spec (and children)
4441 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4442 * @return {HTMLElement/Roo.Element} The new node
4444 insertAfter : function(el, o, returnElement){
4445 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4449 * Creates new Dom element(s) and inserts them as the first child of el
4450 * @param {String/HTMLElement/Element} el The context element
4451 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4452 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4453 * @return {HTMLElement/Roo.Element} The new node
4455 insertFirst : function(el, o, returnElement){
4456 return this.doInsert(el, o, returnElement, "afterBegin");
4460 doInsert : function(el, o, returnElement, pos, sibling){
4461 el = Roo.getDom(el);
4463 if(this.useDom || o.ns){
4464 newNode = createDom(o, null);
4465 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4467 var html = createHtml(o);
4468 newNode = this.insertHtml(pos, el, html);
4470 return returnElement ? Roo.get(newNode, true) : newNode;
4474 * Creates new Dom element(s) and appends them to el
4475 * @param {String/HTMLElement/Element} el The context element
4476 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4477 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4478 * @return {HTMLElement/Roo.Element} The new node
4480 append : function(el, o, returnElement){
4481 el = Roo.getDom(el);
4483 if(this.useDom || o.ns){
4484 newNode = createDom(o, null);
4485 el.appendChild(newNode);
4487 var html = createHtml(o);
4488 newNode = this.insertHtml("beforeEnd", el, html);
4490 return returnElement ? Roo.get(newNode, true) : newNode;
4494 * Creates new Dom element(s) and overwrites the contents of el with them
4495 * @param {String/HTMLElement/Element} el The context element
4496 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4497 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4498 * @return {HTMLElement/Roo.Element} The new node
4500 overwrite : function(el, o, returnElement){
4501 el = Roo.getDom(el);
4504 while (el.childNodes.length) {
4505 el.removeChild(el.firstChild);
4509 el.innerHTML = createHtml(o);
4512 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4516 * Creates a new Roo.DomHelper.Template from the Dom object spec
4517 * @param {Object} o The Dom object spec (and children)
4518 * @return {Roo.DomHelper.Template} The new template
4520 createTemplate : function(o){
4521 var html = createHtml(o);
4522 return new Roo.Template(html);
4528 * Ext JS Library 1.1.1
4529 * Copyright(c) 2006-2007, Ext JS, LLC.
4531 * Originally Released Under LGPL - original licence link has changed is not relivant.
4534 * <script type="text/javascript">
4538 * @class Roo.Template
4539 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4540 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4543 var t = new Roo.Template({
4544 html : '<div name="{id}">' +
4545 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4547 myformat: function (value, allValues) {
4548 return 'XX' + value;
4551 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4553 * For more information see this blog post with examples:
4554 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4555 - Create Elements using DOM, HTML fragments and Templates</a>.
4557 * @param {Object} cfg - Configuration object.
4559 Roo.Template = function(cfg){
4561 if(cfg instanceof Array){
4563 }else if(arguments.length > 1){
4564 cfg = Array.prototype.join.call(arguments, "");
4568 if (typeof(cfg) == 'object') {
4579 Roo.Template.prototype = {
4582 * @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..
4583 * it should be fixed so that template is observable...
4587 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4591 * Returns an HTML fragment of this template with the specified values applied.
4592 * @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'})
4593 * @return {String} The HTML fragment
4595 applyTemplate : function(values){
4599 return this.compiled(values);
4601 var useF = this.disableFormats !== true;
4602 var fm = Roo.util.Format, tpl = this;
4603 var fn = function(m, name, format, args){
4605 if(format.substr(0, 5) == "this."){
4606 return tpl.call(format.substr(5), values[name], values);
4609 // quoted values are required for strings in compiled templates,
4610 // but for non compiled we need to strip them
4611 // quoted reversed for jsmin
4612 var re = /^\s*['"](.*)["']\s*$/;
4613 args = args.split(',');
4614 for(var i = 0, len = args.length; i < len; i++){
4615 args[i] = args[i].replace(re, "$1");
4617 args = [values[name]].concat(args);
4619 args = [values[name]];
4621 return fm[format].apply(fm, args);
4624 return values[name] !== undefined ? values[name] : "";
4627 return this.html.replace(this.re, fn);
4645 this.loading = true;
4646 this.compiled = false;
4648 var cx = new Roo.data.Connection();
4652 success : function (response) {
4654 _t.html = response.responseText;
4658 failure : function(response) {
4659 Roo.log("Template failed to load from " + _t.url);
4666 * Sets the HTML used as the template and optionally compiles it.
4667 * @param {String} html
4668 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4669 * @return {Roo.Template} this
4671 set : function(html, compile){
4673 this.compiled = null;
4681 * True to disable format functions (defaults to false)
4684 disableFormats : false,
4687 * The regular expression used to match template variables
4691 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4694 * Compiles the template into an internal function, eliminating the RegEx overhead.
4695 * @return {Roo.Template} this
4697 compile : function(){
4698 var fm = Roo.util.Format;
4699 var useF = this.disableFormats !== true;
4700 var sep = Roo.isGecko ? "+" : ",";
4701 var fn = function(m, name, format, args){
4703 args = args ? ',' + args : "";
4704 if(format.substr(0, 5) != "this."){
4705 format = "fm." + format + '(';
4707 format = 'this.call("'+ format.substr(5) + '", ';
4711 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4713 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4716 // branched to use + in gecko and [].join() in others
4718 body = "this.compiled = function(values){ return '" +
4719 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4722 body = ["this.compiled = function(values){ return ['"];
4723 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4724 body.push("'].join('');};");
4725 body = body.join('');
4735 // private function used to call members
4736 call : function(fnName, value, allValues){
4737 return this[fnName](value, allValues);
4741 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4742 * @param {String/HTMLElement/Roo.Element} el The context element
4743 * @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'})
4744 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4745 * @return {HTMLElement/Roo.Element} The new node or Element
4747 insertFirst: function(el, values, returnElement){
4748 return this.doInsert('afterBegin', el, values, returnElement);
4752 * Applies the supplied values to the template and inserts the new node(s) before el.
4753 * @param {String/HTMLElement/Roo.Element} el The context element
4754 * @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'})
4755 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4756 * @return {HTMLElement/Roo.Element} The new node or Element
4758 insertBefore: function(el, values, returnElement){
4759 return this.doInsert('beforeBegin', el, values, returnElement);
4763 * Applies the supplied values to the template and inserts the new node(s) after el.
4764 * @param {String/HTMLElement/Roo.Element} el The context element
4765 * @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'})
4766 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4767 * @return {HTMLElement/Roo.Element} The new node or Element
4769 insertAfter : function(el, values, returnElement){
4770 return this.doInsert('afterEnd', el, values, returnElement);
4774 * Applies the supplied values to the template and appends the new node(s) to el.
4775 * @param {String/HTMLElement/Roo.Element} el The context element
4776 * @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'})
4777 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4778 * @return {HTMLElement/Roo.Element} The new node or Element
4780 append : function(el, values, returnElement){
4781 return this.doInsert('beforeEnd', el, values, returnElement);
4784 doInsert : function(where, el, values, returnEl){
4785 el = Roo.getDom(el);
4786 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4787 return returnEl ? Roo.get(newNode, true) : newNode;
4791 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4792 * @param {String/HTMLElement/Roo.Element} el The context element
4793 * @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'})
4794 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4795 * @return {HTMLElement/Roo.Element} The new node or Element
4797 overwrite : function(el, values, returnElement){
4798 el = Roo.getDom(el);
4799 el.innerHTML = this.applyTemplate(values);
4800 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4804 * Alias for {@link #applyTemplate}
4807 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4810 Roo.DomHelper.Template = Roo.Template;
4813 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4814 * @param {String/HTMLElement} el A DOM element or its id
4815 * @returns {Roo.Template} The created template
4818 Roo.Template.from = function(el){
4819 el = Roo.getDom(el);
4820 return new Roo.Template(el.value || el.innerHTML);
4823 * Ext JS Library 1.1.1
4824 * Copyright(c) 2006-2007, Ext JS, LLC.
4826 * Originally Released Under LGPL - original licence link has changed is not relivant.
4829 * <script type="text/javascript">
4834 * This is code is also distributed under MIT license for use
4835 * with jQuery and prototype JavaScript libraries.
4838 * @class Roo.DomQuery
4839 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).
4841 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>
4844 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.
4846 <h4>Element Selectors:</h4>
4848 <li> <b>*</b> any element</li>
4849 <li> <b>E</b> an element with the tag E</li>
4850 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4851 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4852 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4853 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4855 <h4>Attribute Selectors:</h4>
4856 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4858 <li> <b>E[foo]</b> has an attribute "foo"</li>
4859 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4860 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4861 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4862 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4863 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4864 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4866 <h4>Pseudo Classes:</h4>
4868 <li> <b>E:first-child</b> E is the first child of its parent</li>
4869 <li> <b>E:last-child</b> E is the last child of its parent</li>
4870 <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>
4871 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4872 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4873 <li> <b>E:only-child</b> E is the only child of its parent</li>
4874 <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>
4875 <li> <b>E:first</b> the first E in the resultset</li>
4876 <li> <b>E:last</b> the last E in the resultset</li>
4877 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4878 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4879 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4880 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4881 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4882 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4883 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4884 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4885 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4887 <h4>CSS Value Selectors:</h4>
4889 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4890 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4891 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4892 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4893 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4894 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4898 Roo.DomQuery = function(){
4899 var cache = {}, simpleCache = {}, valueCache = {};
4900 var nonSpace = /\S/;
4901 var trimRe = /^\s+|\s+$/g;
4902 var tplRe = /\{(\d+)\}/g;
4903 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4904 var tagTokenRe = /^(#)?([\w-\*]+)/;
4905 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4907 function child(p, index){
4909 var n = p.firstChild;
4911 if(n.nodeType == 1){
4922 while((n = n.nextSibling) && n.nodeType != 1);
4927 while((n = n.previousSibling) && n.nodeType != 1);
4931 function children(d){
4932 var n = d.firstChild, ni = -1;
4934 var nx = n.nextSibling;
4935 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4945 function byClassName(c, a, v){
4949 var r = [], ri = -1, cn;
4950 for(var i = 0, ci; ci = c[i]; i++){
4951 if((' '+ci.className+' ').indexOf(v) != -1){
4958 function attrValue(n, attr){
4959 if(!n.tagName && typeof n.length != "undefined"){
4968 if(attr == "class" || attr == "className"){
4971 return n.getAttribute(attr) || n[attr];
4975 function getNodes(ns, mode, tagName){
4976 var result = [], ri = -1, cs;
4980 tagName = tagName || "*";
4981 if(typeof ns.getElementsByTagName != "undefined"){
4985 for(var i = 0, ni; ni = ns[i]; i++){
4986 cs = ni.getElementsByTagName(tagName);
4987 for(var j = 0, ci; ci = cs[j]; j++){
4991 }else if(mode == "/" || mode == ">"){
4992 var utag = tagName.toUpperCase();
4993 for(var i = 0, ni, cn; ni = ns[i]; i++){
4994 cn = ni.children || ni.childNodes;
4995 for(var j = 0, cj; cj = cn[j]; j++){
4996 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5001 }else if(mode == "+"){
5002 var utag = tagName.toUpperCase();
5003 for(var i = 0, n; n = ns[i]; i++){
5004 while((n = n.nextSibling) && n.nodeType != 1);
5005 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5009 }else if(mode == "~"){
5010 for(var i = 0, n; n = ns[i]; i++){
5011 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5020 function concat(a, b){
5024 for(var i = 0, l = b.length; i < l; i++){
5030 function byTag(cs, tagName){
5031 if(cs.tagName || cs == document){
5037 var r = [], ri = -1;
5038 tagName = tagName.toLowerCase();
5039 for(var i = 0, ci; ci = cs[i]; i++){
5040 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5047 function byId(cs, attr, id){
5048 if(cs.tagName || cs == document){
5054 var r = [], ri = -1;
5055 for(var i = 0,ci; ci = cs[i]; i++){
5056 if(ci && ci.id == id){
5064 function byAttribute(cs, attr, value, op, custom){
5065 var r = [], ri = -1, st = custom=="{";
5066 var f = Roo.DomQuery.operators[op];
5067 for(var i = 0, ci; ci = cs[i]; i++){
5070 a = Roo.DomQuery.getStyle(ci, attr);
5072 else if(attr == "class" || attr == "className"){
5074 }else if(attr == "for"){
5076 }else if(attr == "href"){
5077 a = ci.getAttribute("href", 2);
5079 a = ci.getAttribute(attr);
5081 if((f && f(a, value)) || (!f && a)){
5088 function byPseudo(cs, name, value){
5089 return Roo.DomQuery.pseudos[name](cs, value);
5092 // This is for IE MSXML which does not support expandos.
5093 // IE runs the same speed using setAttribute, however FF slows way down
5094 // and Safari completely fails so they need to continue to use expandos.
5095 var isIE = window.ActiveXObject ? true : false;
5097 // this eval is stop the compressor from
5098 // renaming the variable to something shorter
5100 /** eval:var:batch */
5105 function nodupIEXml(cs){
5107 cs[0].setAttribute("_nodup", d);
5109 for(var i = 1, len = cs.length; i < len; i++){
5111 if(!c.getAttribute("_nodup") != d){
5112 c.setAttribute("_nodup", d);
5116 for(var i = 0, len = cs.length; i < len; i++){
5117 cs[i].removeAttribute("_nodup");
5126 var len = cs.length, c, i, r = cs, cj, ri = -1;
5127 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5130 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5131 return nodupIEXml(cs);
5135 for(i = 1; c = cs[i]; i++){
5140 for(var j = 0; j < i; j++){
5143 for(j = i+1; cj = cs[j]; j++){
5155 function quickDiffIEXml(c1, c2){
5157 for(var i = 0, len = c1.length; i < len; i++){
5158 c1[i].setAttribute("_qdiff", d);
5161 for(var i = 0, len = c2.length; i < len; i++){
5162 if(c2[i].getAttribute("_qdiff") != d){
5163 r[r.length] = c2[i];
5166 for(var i = 0, len = c1.length; i < len; i++){
5167 c1[i].removeAttribute("_qdiff");
5172 function quickDiff(c1, c2){
5173 var len1 = c1.length;
5177 if(isIE && c1[0].selectSingleNode){
5178 return quickDiffIEXml(c1, c2);
5181 for(var i = 0; i < len1; i++){
5185 for(var i = 0, len = c2.length; i < len; i++){
5186 if(c2[i]._qdiff != d){
5187 r[r.length] = c2[i];
5193 function quickId(ns, mode, root, id){
5195 var d = root.ownerDocument || root;
5196 return d.getElementById(id);
5198 ns = getNodes(ns, mode, "*");
5199 return byId(ns, null, id);
5203 getStyle : function(el, name){
5204 return Roo.fly(el).getStyle(name);
5207 * Compiles a selector/xpath query into a reusable function. The returned function
5208 * takes one parameter "root" (optional), which is the context node from where the query should start.
5209 * @param {String} selector The selector/xpath query
5210 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5211 * @return {Function}
5213 compile : function(path, type){
5214 type = type || "select";
5216 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5217 var q = path, mode, lq;
5218 var tk = Roo.DomQuery.matchers;
5219 var tklen = tk.length;
5222 // accept leading mode switch
5223 var lmode = q.match(modeRe);
5224 if(lmode && lmode[1]){
5225 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5226 q = q.replace(lmode[1], "");
5228 // strip leading slashes
5229 while(path.substr(0, 1)=="/"){
5230 path = path.substr(1);
5233 while(q && lq != q){
5235 var tm = q.match(tagTokenRe);
5236 if(type == "select"){
5239 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5241 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5243 q = q.replace(tm[0], "");
5244 }else if(q.substr(0, 1) != '@'){
5245 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5250 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5252 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5254 q = q.replace(tm[0], "");
5257 while(!(mm = q.match(modeRe))){
5258 var matched = false;
5259 for(var j = 0; j < tklen; j++){
5261 var m = q.match(t.re);
5263 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5266 q = q.replace(m[0], "");
5271 // prevent infinite loop on bad selector
5273 throw 'Error parsing selector, parsing failed at "' + q + '"';
5277 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5278 q = q.replace(mm[1], "");
5281 fn[fn.length] = "return nodup(n);\n}";
5284 * list of variables that need from compression as they are used by eval.
5294 * eval:var:byClassName
5296 * eval:var:byAttribute
5297 * eval:var:attrValue
5305 * Selects a group of elements.
5306 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5307 * @param {Node} root (optional) The start of the query (defaults to document).
5310 select : function(path, root, type){
5311 if(!root || root == document){
5314 if(typeof root == "string"){
5315 root = document.getElementById(root);
5317 var paths = path.split(",");
5319 for(var i = 0, len = paths.length; i < len; i++){
5320 var p = paths[i].replace(trimRe, "");
5322 cache[p] = Roo.DomQuery.compile(p);
5324 throw p + " is not a valid selector";
5327 var result = cache[p](root);
5328 if(result && result != document){
5329 results = results.concat(result);
5332 if(paths.length > 1){
5333 return nodup(results);
5339 * Selects a single element.
5340 * @param {String} selector The selector/xpath query
5341 * @param {Node} root (optional) The start of the query (defaults to document).
5344 selectNode : function(path, root){
5345 return Roo.DomQuery.select(path, root)[0];
5349 * Selects the value of a node, optionally replacing null with the defaultValue.
5350 * @param {String} selector The selector/xpath query
5351 * @param {Node} root (optional) The start of the query (defaults to document).
5352 * @param {String} defaultValue
5354 selectValue : function(path, root, defaultValue){
5355 path = path.replace(trimRe, "");
5356 if(!valueCache[path]){
5357 valueCache[path] = Roo.DomQuery.compile(path, "select");
5359 var n = valueCache[path](root);
5360 n = n[0] ? n[0] : n;
5361 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5362 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5366 * Selects the value of a node, parsing integers and floats.
5367 * @param {String} selector The selector/xpath query
5368 * @param {Node} root (optional) The start of the query (defaults to document).
5369 * @param {Number} defaultValue
5372 selectNumber : function(path, root, defaultValue){
5373 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5374 return parseFloat(v);
5378 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5379 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5380 * @param {String} selector The simple selector to test
5383 is : function(el, ss){
5384 if(typeof el == "string"){
5385 el = document.getElementById(el);
5387 var isArray = (el instanceof Array);
5388 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5389 return isArray ? (result.length == el.length) : (result.length > 0);
5393 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5394 * @param {Array} el An array of elements to filter
5395 * @param {String} selector The simple selector to test
5396 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5397 * the selector instead of the ones that match
5400 filter : function(els, ss, nonMatches){
5401 ss = ss.replace(trimRe, "");
5402 if(!simpleCache[ss]){
5403 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5405 var result = simpleCache[ss](els);
5406 return nonMatches ? quickDiff(result, els) : result;
5410 * Collection of matching regular expressions and code snippets.
5414 select: 'n = byClassName(n, null, " {1} ");'
5416 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5417 select: 'n = byPseudo(n, "{1}", "{2}");'
5419 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5420 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5423 select: 'n = byId(n, null, "{1}");'
5426 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5431 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5432 * 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, > <.
5435 "=" : function(a, v){
5438 "!=" : function(a, v){
5441 "^=" : function(a, v){
5442 return a && a.substr(0, v.length) == v;
5444 "$=" : function(a, v){
5445 return a && a.substr(a.length-v.length) == v;
5447 "*=" : function(a, v){
5448 return a && a.indexOf(v) !== -1;
5450 "%=" : function(a, v){
5451 return (a % v) == 0;
5453 "|=" : function(a, v){
5454 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5456 "~=" : function(a, v){
5457 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5462 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5463 * and the argument (if any) supplied in the selector.
5466 "first-child" : function(c){
5467 var r = [], ri = -1, n;
5468 for(var i = 0, ci; ci = n = c[i]; i++){
5469 while((n = n.previousSibling) && n.nodeType != 1);
5477 "last-child" : function(c){
5478 var r = [], ri = -1, n;
5479 for(var i = 0, ci; ci = n = c[i]; i++){
5480 while((n = n.nextSibling) && n.nodeType != 1);
5488 "nth-child" : function(c, a) {
5489 var r = [], ri = -1;
5490 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5491 var f = (m[1] || 1) - 0, l = m[2] - 0;
5492 for(var i = 0, n; n = c[i]; i++){
5493 var pn = n.parentNode;
5494 if (batch != pn._batch) {
5496 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5497 if(cn.nodeType == 1){
5504 if (l == 0 || n.nodeIndex == l){
5507 } else if ((n.nodeIndex + l) % f == 0){
5515 "only-child" : function(c){
5516 var r = [], ri = -1;;
5517 for(var i = 0, ci; ci = c[i]; i++){
5518 if(!prev(ci) && !next(ci)){
5525 "empty" : function(c){
5526 var r = [], ri = -1;
5527 for(var i = 0, ci; ci = c[i]; i++){
5528 var cns = ci.childNodes, j = 0, cn, empty = true;
5531 if(cn.nodeType == 1 || cn.nodeType == 3){
5543 "contains" : function(c, v){
5544 var r = [], ri = -1;
5545 for(var i = 0, ci; ci = c[i]; i++){
5546 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5553 "nodeValue" : function(c, v){
5554 var r = [], ri = -1;
5555 for(var i = 0, ci; ci = c[i]; i++){
5556 if(ci.firstChild && ci.firstChild.nodeValue == v){
5563 "checked" : function(c){
5564 var r = [], ri = -1;
5565 for(var i = 0, ci; ci = c[i]; i++){
5566 if(ci.checked == true){
5573 "not" : function(c, ss){
5574 return Roo.DomQuery.filter(c, ss, true);
5577 "odd" : function(c){
5578 return this["nth-child"](c, "odd");
5581 "even" : function(c){
5582 return this["nth-child"](c, "even");
5585 "nth" : function(c, a){
5586 return c[a-1] || [];
5589 "first" : function(c){
5593 "last" : function(c){
5594 return c[c.length-1] || [];
5597 "has" : function(c, ss){
5598 var s = Roo.DomQuery.select;
5599 var r = [], ri = -1;
5600 for(var i = 0, ci; ci = c[i]; i++){
5601 if(s(ss, ci).length > 0){
5608 "next" : function(c, ss){
5609 var is = Roo.DomQuery.is;
5610 var r = [], ri = -1;
5611 for(var i = 0, ci; ci = c[i]; i++){
5620 "prev" : function(c, ss){
5621 var is = Roo.DomQuery.is;
5622 var r = [], ri = -1;
5623 for(var i = 0, ci; ci = c[i]; i++){
5636 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5637 * @param {String} path The selector/xpath query
5638 * @param {Node} root (optional) The start of the query (defaults to document).
5643 Roo.query = Roo.DomQuery.select;
5646 * Ext JS Library 1.1.1
5647 * Copyright(c) 2006-2007, Ext JS, LLC.
5649 * Originally Released Under LGPL - original licence link has changed is not relivant.
5652 * <script type="text/javascript">
5656 * @class Roo.util.Observable
5657 * Base class that provides a common interface for publishing events. Subclasses are expected to
5658 * to have a property "events" with all the events defined.<br>
5661 Employee = function(name){
5668 Roo.extend(Employee, Roo.util.Observable);
5670 * @param {Object} config properties to use (incuding events / listeners)
5673 Roo.util.Observable = function(cfg){
5676 this.addEvents(cfg.events || {});
5678 delete cfg.events; // make sure
5681 Roo.apply(this, cfg);
5684 this.on(this.listeners);
5685 delete this.listeners;
5688 Roo.util.Observable.prototype = {
5690 * @cfg {Object} listeners list of events and functions to call for this object,
5694 'click' : function(e) {
5704 * Fires the specified event with the passed parameters (minus the event name).
5705 * @param {String} eventName
5706 * @param {Object...} args Variable number of parameters are passed to handlers
5707 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5709 fireEvent : function(){
5710 var ce = this.events[arguments[0].toLowerCase()];
5711 if(typeof ce == "object"){
5712 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5719 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5722 * Appends an event handler to this component
5723 * @param {String} eventName The type of event to listen for
5724 * @param {Function} handler The method the event invokes
5725 * @param {Object} scope (optional) The scope in which to execute the handler
5726 * function. The handler function's "this" context.
5727 * @param {Object} options (optional) An object containing handler configuration
5728 * properties. This may contain any of the following properties:<ul>
5729 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5730 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5731 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5732 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5733 * by the specified number of milliseconds. If the event fires again within that time, the original
5734 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5737 * <b>Combining Options</b><br>
5738 * Using the options argument, it is possible to combine different types of listeners:<br>
5740 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5742 el.on('click', this.onClick, this, {
5749 * <b>Attaching multiple handlers in 1 call</b><br>
5750 * The method also allows for a single argument to be passed which is a config object containing properties
5751 * which specify multiple handlers.
5760 fn: this.onMouseOver,
5764 fn: this.onMouseOut,
5770 * Or a shorthand syntax which passes the same scope object to all handlers:
5773 'click': this.onClick,
5774 'mouseover': this.onMouseOver,
5775 'mouseout': this.onMouseOut,
5780 addListener : function(eventName, fn, scope, o){
5781 if(typeof eventName == "object"){
5784 if(this.filterOptRe.test(e)){
5787 if(typeof o[e] == "function"){
5789 this.addListener(e, o[e], o.scope, o);
5791 // individual options
5792 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5797 o = (!o || typeof o == "boolean") ? {} : o;
5798 eventName = eventName.toLowerCase();
5799 var ce = this.events[eventName] || true;
5800 if(typeof ce == "boolean"){
5801 ce = new Roo.util.Event(this, eventName);
5802 this.events[eventName] = ce;
5804 ce.addListener(fn, scope, o);
5808 * Removes a listener
5809 * @param {String} eventName The type of event to listen for
5810 * @param {Function} handler The handler to remove
5811 * @param {Object} scope (optional) The scope (this object) for the handler
5813 removeListener : function(eventName, fn, scope){
5814 var ce = this.events[eventName.toLowerCase()];
5815 if(typeof ce == "object"){
5816 ce.removeListener(fn, scope);
5821 * Removes all listeners for this object
5823 purgeListeners : function(){
5824 for(var evt in this.events){
5825 if(typeof this.events[evt] == "object"){
5826 this.events[evt].clearListeners();
5831 relayEvents : function(o, events){
5832 var createHandler = function(ename){
5834 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5837 for(var i = 0, len = events.length; i < len; i++){
5838 var ename = events[i];
5839 if(!this.events[ename]){ this.events[ename] = true; };
5840 o.on(ename, createHandler(ename), this);
5845 * Used to define events on this Observable
5846 * @param {Object} object The object with the events defined
5848 addEvents : function(o){
5852 Roo.applyIf(this.events, o);
5856 * Checks to see if this object has any listeners for a specified event
5857 * @param {String} eventName The name of the event to check for
5858 * @return {Boolean} True if the event is being listened for, else false
5860 hasListener : function(eventName){
5861 var e = this.events[eventName];
5862 return typeof e == "object" && e.listeners.length > 0;
5866 * Appends an event handler to this element (shorthand for addListener)
5867 * @param {String} eventName The type of event to listen for
5868 * @param {Function} handler The method the event invokes
5869 * @param {Object} scope (optional) The scope in which to execute the handler
5870 * function. The handler function's "this" context.
5871 * @param {Object} options (optional)
5874 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5876 * Removes a listener (shorthand for removeListener)
5877 * @param {String} eventName The type of event to listen for
5878 * @param {Function} handler The handler to remove
5879 * @param {Object} scope (optional) The scope (this object) for the handler
5882 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5885 * Starts capture on the specified Observable. All events will be passed
5886 * to the supplied function with the event name + standard signature of the event
5887 * <b>before</b> the event is fired. If the supplied function returns false,
5888 * the event will not fire.
5889 * @param {Observable} o The Observable to capture
5890 * @param {Function} fn The function to call
5891 * @param {Object} scope (optional) The scope (this object) for the fn
5894 Roo.util.Observable.capture = function(o, fn, scope){
5895 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5899 * Removes <b>all</b> added captures from the Observable.
5900 * @param {Observable} o The Observable to release
5903 Roo.util.Observable.releaseCapture = function(o){
5904 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5909 var createBuffered = function(h, o, scope){
5910 var task = new Roo.util.DelayedTask();
5912 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5916 var createSingle = function(h, e, fn, scope){
5918 e.removeListener(fn, scope);
5919 return h.apply(scope, arguments);
5923 var createDelayed = function(h, o, scope){
5925 var args = Array.prototype.slice.call(arguments, 0);
5926 setTimeout(function(){
5927 h.apply(scope, args);
5932 Roo.util.Event = function(obj, name){
5935 this.listeners = [];
5938 Roo.util.Event.prototype = {
5939 addListener : function(fn, scope, options){
5940 var o = options || {};
5941 scope = scope || this.obj;
5942 if(!this.isListening(fn, scope)){
5943 var l = {fn: fn, scope: scope, options: o};
5946 h = createDelayed(h, o, scope);
5949 h = createSingle(h, this, fn, scope);
5952 h = createBuffered(h, o, scope);
5955 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5956 this.listeners.push(l);
5958 this.listeners = this.listeners.slice(0);
5959 this.listeners.push(l);
5964 findListener : function(fn, scope){
5965 scope = scope || this.obj;
5966 var ls = this.listeners;
5967 for(var i = 0, len = ls.length; i < len; i++){
5969 if(l.fn == fn && l.scope == scope){
5976 isListening : function(fn, scope){
5977 return this.findListener(fn, scope) != -1;
5980 removeListener : function(fn, scope){
5982 if((index = this.findListener(fn, scope)) != -1){
5984 this.listeners.splice(index, 1);
5986 this.listeners = this.listeners.slice(0);
5987 this.listeners.splice(index, 1);
5994 clearListeners : function(){
5995 this.listeners = [];
5999 var ls = this.listeners, scope, len = ls.length;
6002 var args = Array.prototype.slice.call(arguments, 0);
6003 for(var i = 0; i < len; i++){
6005 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6006 this.firing = false;
6010 this.firing = false;
6017 * Ext JS Library 1.1.1
6018 * Copyright(c) 2006-2007, Ext JS, LLC.
6020 * Originally Released Under LGPL - original licence link has changed is not relivant.
6023 * <script type="text/javascript">
6027 * @class Roo.EventManager
6028 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6029 * several useful events directly.
6030 * See {@link Roo.EventObject} for more details on normalized event objects.
6033 Roo.EventManager = function(){
6034 var docReadyEvent, docReadyProcId, docReadyState = false;
6035 var resizeEvent, resizeTask, textEvent, textSize;
6036 var E = Roo.lib.Event;
6037 var D = Roo.lib.Dom;
6040 var fireDocReady = function(){
6042 docReadyState = true;
6045 clearInterval(docReadyProcId);
6047 if(Roo.isGecko || Roo.isOpera) {
6048 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6051 var defer = document.getElementById("ie-deferred-loader");
6053 defer.onreadystatechange = null;
6054 defer.parentNode.removeChild(defer);
6058 docReadyEvent.fire();
6059 docReadyEvent.clearListeners();
6064 var initDocReady = function(){
6065 docReadyEvent = new Roo.util.Event();
6066 if(Roo.isGecko || Roo.isOpera) {
6067 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6069 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6070 var defer = document.getElementById("ie-deferred-loader");
6071 defer.onreadystatechange = function(){
6072 if(this.readyState == "complete"){
6076 }else if(Roo.isSafari){
6077 docReadyProcId = setInterval(function(){
6078 var rs = document.readyState;
6079 if(rs == "complete") {
6084 // no matter what, make sure it fires on load
6085 E.on(window, "load", fireDocReady);
6088 var createBuffered = function(h, o){
6089 var task = new Roo.util.DelayedTask(h);
6091 // create new event object impl so new events don't wipe out properties
6092 e = new Roo.EventObjectImpl(e);
6093 task.delay(o.buffer, h, null, [e]);
6097 var createSingle = function(h, el, ename, fn){
6099 Roo.EventManager.removeListener(el, ename, fn);
6104 var createDelayed = function(h, o){
6106 // create new event object impl so new events don't wipe out properties
6107 e = new Roo.EventObjectImpl(e);
6108 setTimeout(function(){
6114 var listen = function(element, ename, opt, fn, scope){
6115 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6116 fn = fn || o.fn; scope = scope || o.scope;
6117 var el = Roo.getDom(element);
6119 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6121 var h = function(e){
6122 e = Roo.EventObject.setEvent(e);
6125 t = e.getTarget(o.delegate, el);
6132 if(o.stopEvent === true){
6135 if(o.preventDefault === true){
6138 if(o.stopPropagation === true){
6139 e.stopPropagation();
6142 if(o.normalized === false){
6146 fn.call(scope || el, e, t, o);
6149 h = createDelayed(h, o);
6152 h = createSingle(h, el, ename, fn);
6155 h = createBuffered(h, o);
6157 fn._handlers = fn._handlers || [];
6158 fn._handlers.push([Roo.id(el), ename, h]);
6161 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6162 el.addEventListener("DOMMouseScroll", h, false);
6163 E.on(window, 'unload', function(){
6164 el.removeEventListener("DOMMouseScroll", h, false);
6167 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6168 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6173 var stopListening = function(el, ename, fn){
6174 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6176 for(var i = 0, len = hds.length; i < len; i++){
6178 if(h[0] == id && h[1] == ename){
6185 E.un(el, ename, hd);
6186 el = Roo.getDom(el);
6187 if(ename == "mousewheel" && el.addEventListener){
6188 el.removeEventListener("DOMMouseScroll", hd, false);
6190 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6191 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6195 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6202 * @scope Roo.EventManager
6207 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6208 * object with a Roo.EventObject
6209 * @param {Function} fn The method the event invokes
6210 * @param {Object} scope An object that becomes the scope of the handler
6211 * @param {boolean} override If true, the obj passed in becomes
6212 * the execution scope of the listener
6213 * @return {Function} The wrapped function
6216 wrap : function(fn, scope, override){
6218 Roo.EventObject.setEvent(e);
6219 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6224 * Appends an event handler to an element (shorthand for addListener)
6225 * @param {String/HTMLElement} element The html element or id to assign the
6226 * @param {String} eventName The type of event to listen for
6227 * @param {Function} handler The method the event invokes
6228 * @param {Object} scope (optional) The scope in which to execute the handler
6229 * function. The handler function's "this" context.
6230 * @param {Object} options (optional) An object containing handler configuration
6231 * properties. This may contain any of the following properties:<ul>
6232 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6233 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6234 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6235 * <li>preventDefault {Boolean} True to prevent the default action</li>
6236 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6237 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6238 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6239 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6240 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6241 * by the specified number of milliseconds. If the event fires again within that time, the original
6242 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6245 * <b>Combining Options</b><br>
6246 * Using the options argument, it is possible to combine different types of listeners:<br>
6248 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6250 el.on('click', this.onClick, this, {
6257 * <b>Attaching multiple handlers in 1 call</b><br>
6258 * The method also allows for a single argument to be passed which is a config object containing properties
6259 * which specify multiple handlers.
6269 fn: this.onMouseOver
6278 * Or a shorthand syntax:<br>
6281 'click' : this.onClick,
6282 'mouseover' : this.onMouseOver,
6283 'mouseout' : this.onMouseOut
6287 addListener : function(element, eventName, fn, scope, options){
6288 if(typeof eventName == "object"){
6294 if(typeof o[e] == "function"){
6296 listen(element, e, o, o[e], o.scope);
6298 // individual options
6299 listen(element, e, o[e]);
6304 return listen(element, eventName, options, fn, scope);
6308 * Removes an event handler
6310 * @param {String/HTMLElement} element The id or html element to remove the
6312 * @param {String} eventName The type of event
6313 * @param {Function} fn
6314 * @return {Boolean} True if a listener was actually removed
6316 removeListener : function(element, eventName, fn){
6317 return stopListening(element, eventName, fn);
6321 * Fires when the document is ready (before onload and before images are loaded). Can be
6322 * accessed shorthanded Roo.onReady().
6323 * @param {Function} fn The method the event invokes
6324 * @param {Object} scope An object that becomes the scope of the handler
6325 * @param {boolean} options
6327 onDocumentReady : function(fn, scope, options){
6328 if(docReadyState){ // if it already fired
6329 docReadyEvent.addListener(fn, scope, options);
6330 docReadyEvent.fire();
6331 docReadyEvent.clearListeners();
6337 docReadyEvent.addListener(fn, scope, options);
6341 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6342 * @param {Function} fn The method the event invokes
6343 * @param {Object} scope An object that becomes the scope of the handler
6344 * @param {boolean} options
6346 onWindowResize : function(fn, scope, options){
6348 resizeEvent = new Roo.util.Event();
6349 resizeTask = new Roo.util.DelayedTask(function(){
6350 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6352 E.on(window, "resize", function(){
6354 resizeTask.delay(50);
6356 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6360 resizeEvent.addListener(fn, scope, options);
6364 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6365 * @param {Function} fn The method the event invokes
6366 * @param {Object} scope An object that becomes the scope of the handler
6367 * @param {boolean} options
6369 onTextResize : function(fn, scope, options){
6371 textEvent = new Roo.util.Event();
6372 var textEl = new Roo.Element(document.createElement('div'));
6373 textEl.dom.className = 'x-text-resize';
6374 textEl.dom.innerHTML = 'X';
6375 textEl.appendTo(document.body);
6376 textSize = textEl.dom.offsetHeight;
6377 setInterval(function(){
6378 if(textEl.dom.offsetHeight != textSize){
6379 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6381 }, this.textResizeInterval);
6383 textEvent.addListener(fn, scope, options);
6387 * Removes the passed window resize listener.
6388 * @param {Function} fn The method the event invokes
6389 * @param {Object} scope The scope of handler
6391 removeResizeListener : function(fn, scope){
6393 resizeEvent.removeListener(fn, scope);
6398 fireResize : function(){
6400 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6404 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6408 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6410 textResizeInterval : 50
6415 * @scopeAlias pub=Roo.EventManager
6419 * Appends an event handler to an element (shorthand for addListener)
6420 * @param {String/HTMLElement} element The html element or id to assign the
6421 * @param {String} eventName The type of event to listen for
6422 * @param {Function} handler The method the event invokes
6423 * @param {Object} scope (optional) The scope in which to execute the handler
6424 * function. The handler function's "this" context.
6425 * @param {Object} options (optional) An object containing handler configuration
6426 * properties. This may contain any of the following properties:<ul>
6427 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6428 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6429 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6430 * <li>preventDefault {Boolean} True to prevent the default action</li>
6431 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6432 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6433 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6434 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6435 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6436 * by the specified number of milliseconds. If the event fires again within that time, the original
6437 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6440 * <b>Combining Options</b><br>
6441 * Using the options argument, it is possible to combine different types of listeners:<br>
6443 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6445 el.on('click', this.onClick, this, {
6452 * <b>Attaching multiple handlers in 1 call</b><br>
6453 * The method also allows for a single argument to be passed which is a config object containing properties
6454 * which specify multiple handlers.
6464 fn: this.onMouseOver
6473 * Or a shorthand syntax:<br>
6476 'click' : this.onClick,
6477 'mouseover' : this.onMouseOver,
6478 'mouseout' : this.onMouseOut
6482 pub.on = pub.addListener;
6483 pub.un = pub.removeListener;
6485 pub.stoppedMouseDownEvent = new Roo.util.Event();
6489 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6490 * @param {Function} fn The method the event invokes
6491 * @param {Object} scope An object that becomes the scope of the handler
6492 * @param {boolean} override If true, the obj passed in becomes
6493 * the execution scope of the listener
6497 Roo.onReady = Roo.EventManager.onDocumentReady;
6499 Roo.onReady(function(){
6500 var bd = Roo.get(document.body);
6505 : Roo.isGecko ? "roo-gecko"
6506 : Roo.isOpera ? "roo-opera"
6507 : Roo.isSafari ? "roo-safari" : ""];
6510 cls.push("roo-mac");
6513 cls.push("roo-linux");
6515 if(Roo.isBorderBox){
6516 cls.push('roo-border-box');
6518 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6519 var p = bd.dom.parentNode;
6521 p.className += ' roo-strict';
6524 bd.addClass(cls.join(' '));
6528 * @class Roo.EventObject
6529 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6530 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6533 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6535 var target = e.getTarget();
6538 var myDiv = Roo.get("myDiv");
6539 myDiv.on("click", handleClick);
6541 Roo.EventManager.on("myDiv", 'click', handleClick);
6542 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6546 Roo.EventObject = function(){
6548 var E = Roo.lib.Event;
6550 // safari keypress events for special keys return bad keycodes
6553 63235 : 39, // right
6556 63276 : 33, // page up
6557 63277 : 34, // page down
6558 63272 : 46, // delete
6563 // normalize button clicks
6564 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6565 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6567 Roo.EventObjectImpl = function(e){
6569 this.setEvent(e.browserEvent || e);
6572 Roo.EventObjectImpl.prototype = {
6574 * Used to fix doc tools.
6575 * @scope Roo.EventObject.prototype
6581 /** The normal browser event */
6582 browserEvent : null,
6583 /** The button pressed in a mouse event */
6585 /** True if the shift key was down during the event */
6587 /** True if the control key was down during the event */
6589 /** True if the alt key was down during the event */
6648 setEvent : function(e){
6649 if(e == this || (e && e.browserEvent)){ // already wrapped
6652 this.browserEvent = e;
6654 // normalize buttons
6655 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6656 if(e.type == 'click' && this.button == -1){
6660 this.shiftKey = e.shiftKey;
6661 // mac metaKey behaves like ctrlKey
6662 this.ctrlKey = e.ctrlKey || e.metaKey;
6663 this.altKey = e.altKey;
6664 // in getKey these will be normalized for the mac
6665 this.keyCode = e.keyCode;
6666 // keyup warnings on firefox.
6667 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6668 // cache the target for the delayed and or buffered events
6669 this.target = E.getTarget(e);
6671 this.xy = E.getXY(e);
6674 this.shiftKey = false;
6675 this.ctrlKey = false;
6676 this.altKey = false;
6686 * Stop the event (preventDefault and stopPropagation)
6688 stopEvent : function(){
6689 if(this.browserEvent){
6690 if(this.browserEvent.type == 'mousedown'){
6691 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6693 E.stopEvent(this.browserEvent);
6698 * Prevents the browsers default handling of the event.
6700 preventDefault : function(){
6701 if(this.browserEvent){
6702 E.preventDefault(this.browserEvent);
6707 isNavKeyPress : function(){
6708 var k = this.keyCode;
6709 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6710 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6713 isSpecialKey : function(){
6714 var k = this.keyCode;
6715 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6716 (k == 16) || (k == 17) ||
6717 (k >= 18 && k <= 20) ||
6718 (k >= 33 && k <= 35) ||
6719 (k >= 36 && k <= 39) ||
6720 (k >= 44 && k <= 45);
6723 * Cancels bubbling of the event.
6725 stopPropagation : function(){
6726 if(this.browserEvent){
6727 if(this.type == 'mousedown'){
6728 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6730 E.stopPropagation(this.browserEvent);
6735 * Gets the key code for the event.
6738 getCharCode : function(){
6739 return this.charCode || this.keyCode;
6743 * Returns a normalized keyCode for the event.
6744 * @return {Number} The key code
6746 getKey : function(){
6747 var k = this.keyCode || this.charCode;
6748 return Roo.isSafari ? (safariKeys[k] || k) : k;
6752 * Gets the x coordinate of the event.
6755 getPageX : function(){
6760 * Gets the y coordinate of the event.
6763 getPageY : function(){
6768 * Gets the time of the event.
6771 getTime : function(){
6772 if(this.browserEvent){
6773 return E.getTime(this.browserEvent);
6779 * Gets the page coordinates of the event.
6780 * @return {Array} The xy values like [x, y]
6787 * Gets the target for the event.
6788 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6789 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6790 search as a number or element (defaults to 10 || document.body)
6791 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6792 * @return {HTMLelement}
6794 getTarget : function(selector, maxDepth, returnEl){
6795 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6798 * Gets the related target.
6799 * @return {HTMLElement}
6801 getRelatedTarget : function(){
6802 if(this.browserEvent){
6803 return E.getRelatedTarget(this.browserEvent);
6809 * Normalizes mouse wheel delta across browsers
6810 * @return {Number} The delta
6812 getWheelDelta : function(){
6813 var e = this.browserEvent;
6815 if(e.wheelDelta){ /* IE/Opera. */
6816 delta = e.wheelDelta/120;
6817 }else if(e.detail){ /* Mozilla case. */
6818 delta = -e.detail/3;
6824 * Returns true if the control, meta, shift or alt key was pressed during this event.
6827 hasModifier : function(){
6828 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6832 * Returns true if the target of this event equals el or is a child of el
6833 * @param {String/HTMLElement/Element} el
6834 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6837 within : function(el, related){
6838 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6839 return t && Roo.fly(el).contains(t);
6842 getPoint : function(){
6843 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6847 return new Roo.EventObjectImpl();
6852 * Ext JS Library 1.1.1
6853 * Copyright(c) 2006-2007, Ext JS, LLC.
6855 * Originally Released Under LGPL - original licence link has changed is not relivant.
6858 * <script type="text/javascript">
6862 // was in Composite Element!??!?!
6865 var D = Roo.lib.Dom;
6866 var E = Roo.lib.Event;
6867 var A = Roo.lib.Anim;
6869 // local style camelizing for speed
6871 var camelRe = /(-[a-z])/gi;
6872 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6873 var view = document.defaultView;
6876 * @class Roo.Element
6877 * Represents an Element in the DOM.<br><br>
6880 var el = Roo.get("my-div");
6883 var el = getEl("my-div");
6885 // or with a DOM element
6886 var el = Roo.get(myDivElement);
6888 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6889 * each call instead of constructing a new one.<br><br>
6890 * <b>Animations</b><br />
6891 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6892 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6894 Option Default Description
6895 --------- -------- ---------------------------------------------
6896 duration .35 The duration of the animation in seconds
6897 easing easeOut The YUI easing method
6898 callback none A function to execute when the anim completes
6899 scope this The scope (this) of the callback function
6901 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6902 * manipulate the animation. Here's an example:
6904 var el = Roo.get("my-div");
6909 // default animation
6910 el.setWidth(100, true);
6912 // animation with some options set
6919 // using the "anim" property to get the Anim object
6925 el.setWidth(100, opt);
6927 if(opt.anim.isAnimated()){
6931 * <b> Composite (Collections of) Elements</b><br />
6932 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6933 * @constructor Create a new Element directly.
6934 * @param {String/HTMLElement} element
6935 * @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).
6937 Roo.Element = function(element, forceNew){
6938 var dom = typeof element == "string" ?
6939 document.getElementById(element) : element;
6940 if(!dom){ // invalid id/element
6944 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6945 return Roo.Element.cache[id];
6955 * The DOM element ID
6958 this.id = id || Roo.id(dom);
6961 var El = Roo.Element;
6965 * The element's default display mode (defaults to "")
6968 originalDisplay : "",
6972 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6977 * Sets the element's visibility mode. When setVisible() is called it
6978 * will use this to determine whether to set the visibility or the display property.
6979 * @param visMode Element.VISIBILITY or Element.DISPLAY
6980 * @return {Roo.Element} this
6982 setVisibilityMode : function(visMode){
6983 this.visibilityMode = visMode;
6987 * Convenience method for setVisibilityMode(Element.DISPLAY)
6988 * @param {String} display (optional) What to set display to when visible
6989 * @return {Roo.Element} this
6991 enableDisplayMode : function(display){
6992 this.setVisibilityMode(El.DISPLAY);
6993 if(typeof display != "undefined") this.originalDisplay = display;
6998 * 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)
6999 * @param {String} selector The simple selector to test
7000 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7001 search as a number or element (defaults to 10 || document.body)
7002 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7003 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7005 findParent : function(simpleSelector, maxDepth, returnEl){
7006 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7007 maxDepth = maxDepth || 50;
7008 if(typeof maxDepth != "number"){
7009 stopEl = Roo.getDom(maxDepth);
7012 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7013 if(dq.is(p, simpleSelector)){
7014 return returnEl ? Roo.get(p) : p;
7024 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7025 * @param {String} selector The simple selector to test
7026 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7027 search as a number or element (defaults to 10 || document.body)
7028 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7029 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7031 findParentNode : function(simpleSelector, maxDepth, returnEl){
7032 var p = Roo.fly(this.dom.parentNode, '_internal');
7033 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7037 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7038 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7039 * @param {String} selector The simple selector to test
7040 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7041 search as a number or element (defaults to 10 || document.body)
7042 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7044 up : function(simpleSelector, maxDepth){
7045 return this.findParentNode(simpleSelector, maxDepth, true);
7051 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7052 * @param {String} selector The simple selector to test
7053 * @return {Boolean} True if this element matches the selector, else false
7055 is : function(simpleSelector){
7056 return Roo.DomQuery.is(this.dom, simpleSelector);
7060 * Perform animation on this element.
7061 * @param {Object} args The YUI animation control args
7062 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7063 * @param {Function} onComplete (optional) Function to call when animation completes
7064 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7065 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7066 * @return {Roo.Element} this
7068 animate : function(args, duration, onComplete, easing, animType){
7069 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7074 * @private Internal animation call
7076 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7077 animType = animType || 'run';
7079 var anim = Roo.lib.Anim[animType](
7081 (opt.duration || defaultDur) || .35,
7082 (opt.easing || defaultEase) || 'easeOut',
7084 Roo.callback(cb, this);
7085 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7093 // private legacy anim prep
7094 preanim : function(a, i){
7095 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7099 * Removes worthless text nodes
7100 * @param {Boolean} forceReclean (optional) By default the element
7101 * keeps track if it has been cleaned already so
7102 * you can call this over and over. However, if you update the element and
7103 * need to force a reclean, you can pass true.
7105 clean : function(forceReclean){
7106 if(this.isCleaned && forceReclean !== true){
7110 var d = this.dom, n = d.firstChild, ni = -1;
7112 var nx = n.nextSibling;
7113 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7120 this.isCleaned = true;
7125 calcOffsetsTo : function(el){
7128 var restorePos = false;
7129 if(el.getStyle('position') == 'static'){
7130 el.position('relative');
7135 while(op && op != d && op.tagName != 'HTML'){
7138 op = op.offsetParent;
7141 el.position('static');
7147 * Scrolls this element into view within the passed container.
7148 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7149 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7150 * @return {Roo.Element} this
7152 scrollIntoView : function(container, hscroll){
7153 var c = Roo.getDom(container) || document.body;
7156 var o = this.calcOffsetsTo(c),
7159 b = t+el.offsetHeight,
7160 r = l+el.offsetWidth;
7162 var ch = c.clientHeight;
7163 var ct = parseInt(c.scrollTop, 10);
7164 var cl = parseInt(c.scrollLeft, 10);
7166 var cr = cl + c.clientWidth;
7174 if(hscroll !== false){
7178 c.scrollLeft = r-c.clientWidth;
7185 scrollChildIntoView : function(child, hscroll){
7186 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7190 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7191 * the new height may not be available immediately.
7192 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7193 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7194 * @param {Function} onComplete (optional) Function to call when animation completes
7195 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7196 * @return {Roo.Element} this
7198 autoHeight : function(animate, duration, onComplete, easing){
7199 var oldHeight = this.getHeight();
7201 this.setHeight(1); // force clipping
7202 setTimeout(function(){
7203 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7205 this.setHeight(height);
7207 if(typeof onComplete == "function"){
7211 this.setHeight(oldHeight); // restore original height
7212 this.setHeight(height, animate, duration, function(){
7214 if(typeof onComplete == "function") onComplete();
7215 }.createDelegate(this), easing);
7217 }.createDelegate(this), 0);
7222 * Returns true if this element is an ancestor of the passed element
7223 * @param {HTMLElement/String} el The element to check
7224 * @return {Boolean} True if this element is an ancestor of el, else false
7226 contains : function(el){
7227 if(!el){return false;}
7228 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7232 * Checks whether the element is currently visible using both visibility and display properties.
7233 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7234 * @return {Boolean} True if the element is currently visible, else false
7236 isVisible : function(deep) {
7237 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7238 if(deep !== true || !vis){
7241 var p = this.dom.parentNode;
7242 while(p && p.tagName.toLowerCase() != "body"){
7243 if(!Roo.fly(p, '_isVisible').isVisible()){
7252 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7253 * @param {String} selector The CSS selector
7254 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7255 * @return {CompositeElement/CompositeElementLite} The composite element
7257 select : function(selector, unique){
7258 return El.select(selector, unique, this.dom);
7262 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7263 * @param {String} selector The CSS selector
7264 * @return {Array} An array of the matched nodes
7266 query : function(selector, unique){
7267 return Roo.DomQuery.select(selector, this.dom);
7271 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7272 * @param {String} selector The CSS selector
7273 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7274 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7276 child : function(selector, returnDom){
7277 var n = Roo.DomQuery.selectNode(selector, this.dom);
7278 return returnDom ? n : Roo.get(n);
7282 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7283 * @param {String} selector The CSS selector
7284 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7285 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7287 down : function(selector, returnDom){
7288 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7289 return returnDom ? n : Roo.get(n);
7293 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7294 * @param {String} group The group the DD object is member of
7295 * @param {Object} config The DD config object
7296 * @param {Object} overrides An object containing methods to override/implement on the DD object
7297 * @return {Roo.dd.DD} The DD object
7299 initDD : function(group, config, overrides){
7300 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7301 return Roo.apply(dd, overrides);
7305 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7306 * @param {String} group The group the DDProxy object is member of
7307 * @param {Object} config The DDProxy config object
7308 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7309 * @return {Roo.dd.DDProxy} The DDProxy object
7311 initDDProxy : function(group, config, overrides){
7312 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7313 return Roo.apply(dd, overrides);
7317 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7318 * @param {String} group The group the DDTarget object is member of
7319 * @param {Object} config The DDTarget config object
7320 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7321 * @return {Roo.dd.DDTarget} The DDTarget object
7323 initDDTarget : function(group, config, overrides){
7324 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7325 return Roo.apply(dd, overrides);
7329 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7330 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7331 * @param {Boolean} visible Whether the element is visible
7332 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7333 * @return {Roo.Element} this
7335 setVisible : function(visible, animate){
7337 if(this.visibilityMode == El.DISPLAY){
7338 this.setDisplayed(visible);
7341 this.dom.style.visibility = visible ? "visible" : "hidden";
7344 // closure for composites
7346 var visMode = this.visibilityMode;
7348 this.setOpacity(.01);
7349 this.setVisible(true);
7351 this.anim({opacity: { to: (visible?1:0) }},
7352 this.preanim(arguments, 1),
7353 null, .35, 'easeIn', function(){
7355 if(visMode == El.DISPLAY){
7356 dom.style.display = "none";
7358 dom.style.visibility = "hidden";
7360 Roo.get(dom).setOpacity(1);
7368 * Returns true if display is not "none"
7371 isDisplayed : function() {
7372 return this.getStyle("display") != "none";
7376 * Toggles the element's visibility or display, depending on visibility mode.
7377 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7378 * @return {Roo.Element} this
7380 toggle : function(animate){
7381 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7386 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7387 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7388 * @return {Roo.Element} this
7390 setDisplayed : function(value) {
7391 if(typeof value == "boolean"){
7392 value = value ? this.originalDisplay : "none";
7394 this.setStyle("display", value);
7399 * Tries to focus the element. Any exceptions are caught and ignored.
7400 * @return {Roo.Element} this
7402 focus : function() {
7410 * Tries to blur the element. Any exceptions are caught and ignored.
7411 * @return {Roo.Element} this
7421 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7422 * @param {String/Array} className The CSS class to add, or an array of classes
7423 * @return {Roo.Element} this
7425 addClass : function(className){
7426 if(className instanceof Array){
7427 for(var i = 0, len = className.length; i < len; i++) {
7428 this.addClass(className[i]);
7431 if(className && !this.hasClass(className)){
7432 this.dom.className = this.dom.className + " " + className;
7439 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7440 * @param {String/Array} className The CSS class to add, or an array of classes
7441 * @return {Roo.Element} this
7443 radioClass : function(className){
7444 var siblings = this.dom.parentNode.childNodes;
7445 for(var i = 0; i < siblings.length; i++) {
7446 var s = siblings[i];
7447 if(s.nodeType == 1){
7448 Roo.get(s).removeClass(className);
7451 this.addClass(className);
7456 * Removes one or more CSS classes from the element.
7457 * @param {String/Array} className The CSS class to remove, or an array of classes
7458 * @return {Roo.Element} this
7460 removeClass : function(className){
7461 if(!className || !this.dom.className){
7464 if(className instanceof Array){
7465 for(var i = 0, len = className.length; i < len; i++) {
7466 this.removeClass(className[i]);
7469 if(this.hasClass(className)){
7470 var re = this.classReCache[className];
7472 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7473 this.classReCache[className] = re;
7475 this.dom.className =
7476 this.dom.className.replace(re, " ");
7486 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7487 * @param {String} className The CSS class to toggle
7488 * @return {Roo.Element} this
7490 toggleClass : function(className){
7491 if(this.hasClass(className)){
7492 this.removeClass(className);
7494 this.addClass(className);
7500 * Checks if the specified CSS class exists on this element's DOM node.
7501 * @param {String} className The CSS class to check for
7502 * @return {Boolean} True if the class exists, else false
7504 hasClass : function(className){
7505 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7509 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7510 * @param {String} oldClassName The CSS class to replace
7511 * @param {String} newClassName The replacement CSS class
7512 * @return {Roo.Element} this
7514 replaceClass : function(oldClassName, newClassName){
7515 this.removeClass(oldClassName);
7516 this.addClass(newClassName);
7521 * Returns an object with properties matching the styles requested.
7522 * For example, el.getStyles('color', 'font-size', 'width') might return
7523 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7524 * @param {String} style1 A style name
7525 * @param {String} style2 A style name
7526 * @param {String} etc.
7527 * @return {Object} The style object
7529 getStyles : function(){
7530 var a = arguments, len = a.length, r = {};
7531 for(var i = 0; i < len; i++){
7532 r[a[i]] = this.getStyle(a[i]);
7538 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7539 * @param {String} property The style property whose value is returned.
7540 * @return {String} The current value of the style property for this element.
7542 getStyle : function(){
7543 return view && view.getComputedStyle ?
7545 var el = this.dom, v, cs, camel;
7546 if(prop == 'float'){
7549 if(el.style && (v = el.style[prop])){
7552 if(cs = view.getComputedStyle(el, "")){
7553 if(!(camel = propCache[prop])){
7554 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7561 var el = this.dom, v, cs, camel;
7562 if(prop == 'opacity'){
7563 if(typeof el.style.filter == 'string'){
7564 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7566 var fv = parseFloat(m[1]);
7568 return fv ? fv / 100 : 0;
7573 }else if(prop == 'float'){
7574 prop = "styleFloat";
7576 if(!(camel = propCache[prop])){
7577 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7579 if(v = el.style[camel]){
7582 if(cs = el.currentStyle){
7590 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7591 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7592 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7593 * @return {Roo.Element} this
7595 setStyle : function(prop, value){
7596 if(typeof prop == "string"){
7598 if (prop == 'float') {
7599 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7604 if(!(camel = propCache[prop])){
7605 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7608 if(camel == 'opacity') {
7609 this.setOpacity(value);
7611 this.dom.style[camel] = value;
7614 for(var style in prop){
7615 if(typeof prop[style] != "function"){
7616 this.setStyle(style, prop[style]);
7624 * More flexible version of {@link #setStyle} for setting style properties.
7625 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7626 * a function which returns such a specification.
7627 * @return {Roo.Element} this
7629 applyStyles : function(style){
7630 Roo.DomHelper.applyStyles(this.dom, style);
7635 * 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).
7636 * @return {Number} The X position of the element
7639 return D.getX(this.dom);
7643 * 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).
7644 * @return {Number} The Y position of the element
7647 return D.getY(this.dom);
7651 * 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).
7652 * @return {Array} The XY position of the element
7655 return D.getXY(this.dom);
7659 * 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).
7660 * @param {Number} The X position of the element
7661 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7662 * @return {Roo.Element} this
7664 setX : function(x, animate){
7666 D.setX(this.dom, x);
7668 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7674 * 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).
7675 * @param {Number} The Y position of the element
7676 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7677 * @return {Roo.Element} this
7679 setY : function(y, animate){
7681 D.setY(this.dom, y);
7683 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7689 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7690 * @param {String} left The left CSS property value
7691 * @return {Roo.Element} this
7693 setLeft : function(left){
7694 this.setStyle("left", this.addUnits(left));
7699 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7700 * @param {String} top The top CSS property value
7701 * @return {Roo.Element} this
7703 setTop : function(top){
7704 this.setStyle("top", this.addUnits(top));
7709 * Sets the element's CSS right style.
7710 * @param {String} right The right CSS property value
7711 * @return {Roo.Element} this
7713 setRight : function(right){
7714 this.setStyle("right", this.addUnits(right));
7719 * Sets the element's CSS bottom style.
7720 * @param {String} bottom The bottom CSS property value
7721 * @return {Roo.Element} this
7723 setBottom : function(bottom){
7724 this.setStyle("bottom", this.addUnits(bottom));
7729 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7730 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7731 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7732 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7733 * @return {Roo.Element} this
7735 setXY : function(pos, animate){
7737 D.setXY(this.dom, pos);
7739 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7745 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7746 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7747 * @param {Number} x X value for new position (coordinates are page-based)
7748 * @param {Number} y Y value for new position (coordinates are page-based)
7749 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7750 * @return {Roo.Element} this
7752 setLocation : function(x, y, animate){
7753 this.setXY([x, y], this.preanim(arguments, 2));
7758 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7759 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7760 * @param {Number} x X value for new position (coordinates are page-based)
7761 * @param {Number} y Y value for new position (coordinates are page-based)
7762 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7763 * @return {Roo.Element} this
7765 moveTo : function(x, y, animate){
7766 this.setXY([x, y], this.preanim(arguments, 2));
7771 * Returns the region of the given element.
7772 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7773 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7775 getRegion : function(){
7776 return D.getRegion(this.dom);
7780 * Returns the offset height of the element
7781 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7782 * @return {Number} The element's height
7784 getHeight : function(contentHeight){
7785 var h = this.dom.offsetHeight || 0;
7786 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7790 * Returns the offset width of the element
7791 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7792 * @return {Number} The element's width
7794 getWidth : function(contentWidth){
7795 var w = this.dom.offsetWidth || 0;
7796 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7800 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7801 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7802 * if a height has not been set using CSS.
7805 getComputedHeight : function(){
7806 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7808 h = parseInt(this.getStyle('height'), 10) || 0;
7809 if(!this.isBorderBox()){
7810 h += this.getFrameWidth('tb');
7817 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7818 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7819 * if a width has not been set using CSS.
7822 getComputedWidth : function(){
7823 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7825 w = parseInt(this.getStyle('width'), 10) || 0;
7826 if(!this.isBorderBox()){
7827 w += this.getFrameWidth('lr');
7834 * Returns the size of the element.
7835 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7836 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7838 getSize : function(contentSize){
7839 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7843 * Returns the width and height of the viewport.
7844 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7846 getViewSize : function(){
7847 var d = this.dom, doc = document, aw = 0, ah = 0;
7848 if(d == doc || d == doc.body){
7849 return {width : D.getViewWidth(), height: D.getViewHeight()};
7852 width : d.clientWidth,
7853 height: d.clientHeight
7859 * Returns the value of the "value" attribute
7860 * @param {Boolean} asNumber true to parse the value as a number
7861 * @return {String/Number}
7863 getValue : function(asNumber){
7864 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7868 adjustWidth : function(width){
7869 if(typeof width == "number"){
7870 if(this.autoBoxAdjust && !this.isBorderBox()){
7871 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7881 adjustHeight : function(height){
7882 if(typeof height == "number"){
7883 if(this.autoBoxAdjust && !this.isBorderBox()){
7884 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7894 * Set the width of the element
7895 * @param {Number} width The new width
7896 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7897 * @return {Roo.Element} this
7899 setWidth : function(width, animate){
7900 width = this.adjustWidth(width);
7902 this.dom.style.width = this.addUnits(width);
7904 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7910 * Set the height of the element
7911 * @param {Number} height The new height
7912 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7913 * @return {Roo.Element} this
7915 setHeight : function(height, animate){
7916 height = this.adjustHeight(height);
7918 this.dom.style.height = this.addUnits(height);
7920 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7926 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7927 * @param {Number} width The new width
7928 * @param {Number} height The new height
7929 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7930 * @return {Roo.Element} this
7932 setSize : function(width, height, animate){
7933 if(typeof width == "object"){ // in case of object from getSize()
7934 height = width.height; width = width.width;
7936 width = this.adjustWidth(width); height = this.adjustHeight(height);
7938 this.dom.style.width = this.addUnits(width);
7939 this.dom.style.height = this.addUnits(height);
7941 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7947 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7948 * @param {Number} x X value for new position (coordinates are page-based)
7949 * @param {Number} y Y value for new position (coordinates are page-based)
7950 * @param {Number} width The new width
7951 * @param {Number} height The new height
7952 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7953 * @return {Roo.Element} this
7955 setBounds : function(x, y, width, height, animate){
7957 this.setSize(width, height);
7958 this.setLocation(x, y);
7960 width = this.adjustWidth(width); height = this.adjustHeight(height);
7961 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7962 this.preanim(arguments, 4), 'motion');
7968 * 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.
7969 * @param {Roo.lib.Region} region The region to fill
7970 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7971 * @return {Roo.Element} this
7973 setRegion : function(region, animate){
7974 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7979 * Appends an event handler
7981 * @param {String} eventName The type of event to append
7982 * @param {Function} fn The method the event invokes
7983 * @param {Object} scope (optional) The scope (this object) of the fn
7984 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7986 addListener : function(eventName, fn, scope, options){
7988 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7993 * Removes an event handler from this element
7994 * @param {String} eventName the type of event to remove
7995 * @param {Function} fn the method the event invokes
7996 * @return {Roo.Element} this
7998 removeListener : function(eventName, fn){
7999 Roo.EventManager.removeListener(this.dom, eventName, fn);
8004 * Removes all previous added listeners from this element
8005 * @return {Roo.Element} this
8007 removeAllListeners : function(){
8008 E.purgeElement(this.dom);
8012 relayEvent : function(eventName, observable){
8013 this.on(eventName, function(e){
8014 observable.fireEvent(eventName, e);
8019 * Set the opacity of the element
8020 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8021 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8022 * @return {Roo.Element} this
8024 setOpacity : function(opacity, animate){
8026 var s = this.dom.style;
8029 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8030 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8032 s.opacity = opacity;
8035 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8041 * Gets the left X coordinate
8042 * @param {Boolean} local True to get the local css position instead of page coordinate
8045 getLeft : function(local){
8049 return parseInt(this.getStyle("left"), 10) || 0;
8054 * Gets the right X coordinate of the element (element X position + element width)
8055 * @param {Boolean} local True to get the local css position instead of page coordinate
8058 getRight : function(local){
8060 return this.getX() + this.getWidth();
8062 return (this.getLeft(true) + this.getWidth()) || 0;
8067 * Gets the top Y coordinate
8068 * @param {Boolean} local True to get the local css position instead of page coordinate
8071 getTop : function(local) {
8075 return parseInt(this.getStyle("top"), 10) || 0;
8080 * Gets the bottom Y coordinate of the element (element Y position + element height)
8081 * @param {Boolean} local True to get the local css position instead of page coordinate
8084 getBottom : function(local){
8086 return this.getY() + this.getHeight();
8088 return (this.getTop(true) + this.getHeight()) || 0;
8093 * Initializes positioning on this element. If a desired position is not passed, it will make the
8094 * the element positioned relative IF it is not already positioned.
8095 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8096 * @param {Number} zIndex (optional) The zIndex to apply
8097 * @param {Number} x (optional) Set the page X position
8098 * @param {Number} y (optional) Set the page Y position
8100 position : function(pos, zIndex, x, y){
8102 if(this.getStyle('position') == 'static'){
8103 this.setStyle('position', 'relative');
8106 this.setStyle("position", pos);
8109 this.setStyle("z-index", zIndex);
8111 if(x !== undefined && y !== undefined){
8113 }else if(x !== undefined){
8115 }else if(y !== undefined){
8121 * Clear positioning back to the default when the document was loaded
8122 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8123 * @return {Roo.Element} this
8125 clearPositioning : function(value){
8133 "position" : "static"
8139 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8140 * snapshot before performing an update and then restoring the element.
8143 getPositioning : function(){
8144 var l = this.getStyle("left");
8145 var t = this.getStyle("top");
8147 "position" : this.getStyle("position"),
8149 "right" : l ? "" : this.getStyle("right"),
8151 "bottom" : t ? "" : this.getStyle("bottom"),
8152 "z-index" : this.getStyle("z-index")
8157 * Gets the width of the border(s) for the specified side(s)
8158 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8159 * passing lr would get the border (l)eft width + the border (r)ight width.
8160 * @return {Number} The width of the sides passed added together
8162 getBorderWidth : function(side){
8163 return this.addStyles(side, El.borders);
8167 * Gets the width of the padding(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 padding (l)eft + the padding (r)ight.
8170 * @return {Number} The padding of the sides passed added together
8172 getPadding : function(side){
8173 return this.addStyles(side, El.paddings);
8177 * Set positioning with an object returned by getPositioning().
8178 * @param {Object} posCfg
8179 * @return {Roo.Element} this
8181 setPositioning : function(pc){
8182 this.applyStyles(pc);
8183 if(pc.right == "auto"){
8184 this.dom.style.right = "";
8186 if(pc.bottom == "auto"){
8187 this.dom.style.bottom = "";
8193 fixDisplay : function(){
8194 if(this.getStyle("display") == "none"){
8195 this.setStyle("visibility", "hidden");
8196 this.setStyle("display", this.originalDisplay); // first try reverting to default
8197 if(this.getStyle("display") == "none"){ // if that fails, default to block
8198 this.setStyle("display", "block");
8204 * Quick set left and top adding default units
8205 * @param {String} left The left CSS property value
8206 * @param {String} top The top CSS property value
8207 * @return {Roo.Element} this
8209 setLeftTop : function(left, top){
8210 this.dom.style.left = this.addUnits(left);
8211 this.dom.style.top = this.addUnits(top);
8216 * Move this element relative to its current position.
8217 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8218 * @param {Number} distance How far to move the element in pixels
8219 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8220 * @return {Roo.Element} this
8222 move : function(direction, distance, animate){
8223 var xy = this.getXY();
8224 direction = direction.toLowerCase();
8228 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8232 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8237 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8242 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8249 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8250 * @return {Roo.Element} this
8253 if(!this.isClipped){
8254 this.isClipped = true;
8255 this.originalClip = {
8256 "o": this.getStyle("overflow"),
8257 "x": this.getStyle("overflow-x"),
8258 "y": this.getStyle("overflow-y")
8260 this.setStyle("overflow", "hidden");
8261 this.setStyle("overflow-x", "hidden");
8262 this.setStyle("overflow-y", "hidden");
8268 * Return clipping (overflow) to original clipping before clip() was called
8269 * @return {Roo.Element} this
8271 unclip : function(){
8273 this.isClipped = false;
8274 var o = this.originalClip;
8275 if(o.o){this.setStyle("overflow", o.o);}
8276 if(o.x){this.setStyle("overflow-x", o.x);}
8277 if(o.y){this.setStyle("overflow-y", o.y);}
8284 * Gets the x,y coordinates specified by the anchor position on the element.
8285 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8286 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8287 * {width: (target width), height: (target height)} (defaults to the element's current size)
8288 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8289 * @return {Array} [x, y] An array containing the element's x and y coordinates
8291 getAnchorXY : function(anchor, local, s){
8292 //Passing a different size is useful for pre-calculating anchors,
8293 //especially for anchored animations that change the el size.
8295 var w, h, vp = false;
8298 if(d == document.body || d == document){
8300 w = D.getViewWidth(); h = D.getViewHeight();
8302 w = this.getWidth(); h = this.getHeight();
8305 w = s.width; h = s.height;
8307 var x = 0, y = 0, r = Math.round;
8308 switch((anchor || "tl").toLowerCase()){
8350 var sc = this.getScroll();
8351 return [x + sc.left, y + sc.top];
8353 //Add the element's offset xy
8354 var o = this.getXY();
8355 return [x+o[0], y+o[1]];
8359 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8360 * supported position values.
8361 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8362 * @param {String} position The position to align to.
8363 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8364 * @return {Array} [x, y]
8366 getAlignToXY : function(el, p, o){
8370 throw "Element.alignTo with an element that doesn't exist";
8372 var c = false; //constrain to viewport
8373 var p1 = "", p2 = "";
8380 }else if(p.indexOf("-") == -1){
8383 p = p.toLowerCase();
8384 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8386 throw "Element.alignTo with an invalid alignment " + p;
8388 p1 = m[1]; p2 = m[2]; c = !!m[3];
8390 //Subtract the aligned el's internal xy from the target's offset xy
8391 //plus custom offset to get the aligned el's new offset xy
8392 var a1 = this.getAnchorXY(p1, true);
8393 var a2 = el.getAnchorXY(p2, false);
8394 var x = a2[0] - a1[0] + o[0];
8395 var y = a2[1] - a1[1] + o[1];
8397 //constrain the aligned el to viewport if necessary
8398 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8399 // 5px of margin for ie
8400 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8402 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8403 //perpendicular to the vp border, allow the aligned el to slide on that border,
8404 //otherwise swap the aligned el to the opposite border of the target.
8405 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8406 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8407 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8408 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8411 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8412 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8414 if((x+w) > dw + scrollX){
8415 x = swapX ? r.left-w : dw+scrollX-w;
8418 x = swapX ? r.right : scrollX;
8420 if((y+h) > dh + scrollY){
8421 y = swapY ? r.top-h : dh+scrollY-h;
8424 y = swapY ? r.bottom : scrollY;
8431 getConstrainToXY : function(){
8432 var os = {top:0, left:0, bottom:0, right: 0};
8434 return function(el, local, offsets, proposedXY){
8436 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8438 var vw, vh, vx = 0, vy = 0;
8439 if(el.dom == document.body || el.dom == document){
8440 vw = Roo.lib.Dom.getViewWidth();
8441 vh = Roo.lib.Dom.getViewHeight();
8443 vw = el.dom.clientWidth;
8444 vh = el.dom.clientHeight;
8446 var vxy = el.getXY();
8452 var s = el.getScroll();
8454 vx += offsets.left + s.left;
8455 vy += offsets.top + s.top;
8457 vw -= offsets.right;
8458 vh -= offsets.bottom;
8463 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8464 var x = xy[0], y = xy[1];
8465 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8467 // only move it if it needs it
8470 // first validate right/bottom
8479 // then make sure top/left isn't negative
8488 return moved ? [x, y] : false;
8493 adjustForConstraints : function(xy, parent, offsets){
8494 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8498 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8499 * document it aligns it to the viewport.
8500 * The position parameter is optional, and can be specified in any one of the following formats:
8502 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8503 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8504 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8505 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8506 * <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
8507 * element's anchor point, and the second value is used as the target's anchor point.</li>
8509 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8510 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8511 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8512 * that specified in order to enforce the viewport constraints.
8513 * Following are all of the supported anchor positions:
8516 ----- -----------------------------
8517 tl The top left corner (default)
8518 t The center of the top edge
8519 tr The top right corner
8520 l The center of the left edge
8521 c In the center of the element
8522 r The center of the right edge
8523 bl The bottom left corner
8524 b The center of the bottom edge
8525 br The bottom right corner
8529 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8530 el.alignTo("other-el");
8532 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8533 el.alignTo("other-el", "tr?");
8535 // align the bottom right corner of el with the center left edge of other-el
8536 el.alignTo("other-el", "br-l?");
8538 // align the center of el with the bottom left corner of other-el and
8539 // adjust the x position by -6 pixels (and the y position by 0)
8540 el.alignTo("other-el", "c-bl", [-6, 0]);
8542 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8543 * @param {String} position The position to align to.
8544 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8545 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8546 * @return {Roo.Element} this
8548 alignTo : function(element, position, offsets, animate){
8549 var xy = this.getAlignToXY(element, position, offsets);
8550 this.setXY(xy, this.preanim(arguments, 3));
8555 * Anchors an element to another element and realigns it when the window is resized.
8556 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8557 * @param {String} position The position to align to.
8558 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8559 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8560 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8561 * is a number, it is used as the buffer delay (defaults to 50ms).
8562 * @param {Function} callback The function to call after the animation finishes
8563 * @return {Roo.Element} this
8565 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8566 var action = function(){
8567 this.alignTo(el, alignment, offsets, animate);
8568 Roo.callback(callback, this);
8570 Roo.EventManager.onWindowResize(action, this);
8571 var tm = typeof monitorScroll;
8572 if(tm != 'undefined'){
8573 Roo.EventManager.on(window, 'scroll', action, this,
8574 {buffer: tm == 'number' ? monitorScroll : 50});
8576 action.call(this); // align immediately
8580 * Clears any opacity settings from this element. Required in some cases for IE.
8581 * @return {Roo.Element} this
8583 clearOpacity : function(){
8584 if (window.ActiveXObject) {
8585 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8586 this.dom.style.filter = "";
8589 this.dom.style.opacity = "";
8590 this.dom.style["-moz-opacity"] = "";
8591 this.dom.style["-khtml-opacity"] = "";
8597 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8598 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8599 * @return {Roo.Element} this
8601 hide : function(animate){
8602 this.setVisible(false, this.preanim(arguments, 0));
8607 * Show 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 show : function(animate){
8612 this.setVisible(true, this.preanim(arguments, 0));
8617 * @private Test if size has a unit, otherwise appends the default
8619 addUnits : function(size){
8620 return Roo.Element.addUnits(size, this.defaultUnit);
8624 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8625 * @return {Roo.Element} this
8627 beginMeasure : function(){
8629 if(el.offsetWidth || el.offsetHeight){
8630 return this; // offsets work already
8633 var p = this.dom, b = document.body; // start with this element
8634 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8635 var pe = Roo.get(p);
8636 if(pe.getStyle('display') == 'none'){
8637 changed.push({el: p, visibility: pe.getStyle("visibility")});
8638 p.style.visibility = "hidden";
8639 p.style.display = "block";
8643 this._measureChanged = changed;
8649 * Restores displays to before beginMeasure was called
8650 * @return {Roo.Element} this
8652 endMeasure : function(){
8653 var changed = this._measureChanged;
8655 for(var i = 0, len = changed.length; i < len; i++) {
8657 r.el.style.visibility = r.visibility;
8658 r.el.style.display = "none";
8660 this._measureChanged = null;
8666 * Update the innerHTML of this element, optionally searching for and processing scripts
8667 * @param {String} html The new HTML
8668 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8669 * @param {Function} callback For async script loading you can be noticed when the update completes
8670 * @return {Roo.Element} this
8672 update : function(html, loadScripts, callback){
8673 if(typeof html == "undefined"){
8676 if(loadScripts !== true){
8677 this.dom.innerHTML = html;
8678 if(typeof callback == "function"){
8686 html += '<span id="' + id + '"></span>';
8688 E.onAvailable(id, function(){
8689 var hd = document.getElementsByTagName("head")[0];
8690 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8691 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8692 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8695 while(match = re.exec(html)){
8696 var attrs = match[1];
8697 var srcMatch = attrs ? attrs.match(srcRe) : false;
8698 if(srcMatch && srcMatch[2]){
8699 var s = document.createElement("script");
8700 s.src = srcMatch[2];
8701 var typeMatch = attrs.match(typeRe);
8702 if(typeMatch && typeMatch[2]){
8703 s.type = typeMatch[2];
8706 }else if(match[2] && match[2].length > 0){
8707 if(window.execScript) {
8708 window.execScript(match[2]);
8716 window.eval(match[2]);
8720 var el = document.getElementById(id);
8721 if(el){el.parentNode.removeChild(el);}
8722 if(typeof callback == "function"){
8726 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8731 * Direct access to the UpdateManager update() method (takes the same parameters).
8732 * @param {String/Function} url The url for this request or a function to call to get the url
8733 * @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}
8734 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8735 * @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.
8736 * @return {Roo.Element} this
8739 var um = this.getUpdateManager();
8740 um.update.apply(um, arguments);
8745 * Gets this element's UpdateManager
8746 * @return {Roo.UpdateManager} The UpdateManager
8748 getUpdateManager : function(){
8749 if(!this.updateManager){
8750 this.updateManager = new Roo.UpdateManager(this);
8752 return this.updateManager;
8756 * Disables text selection for this element (normalized across browsers)
8757 * @return {Roo.Element} this
8759 unselectable : function(){
8760 this.dom.unselectable = "on";
8761 this.swallowEvent("selectstart", true);
8762 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8763 this.addClass("x-unselectable");
8768 * Calculates the x, y to center this element on the screen
8769 * @return {Array} The x, y values [x, y]
8771 getCenterXY : function(){
8772 return this.getAlignToXY(document, 'c-c');
8776 * Centers the Element in either the viewport, or another Element.
8777 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8779 center : function(centerIn){
8780 this.alignTo(centerIn || document, 'c-c');
8785 * Tests various css rules/browsers to determine if this element uses a border box
8788 isBorderBox : function(){
8789 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8793 * Return a box {x, y, width, height} that can be used to set another elements
8794 * size/location to match this element.
8795 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8796 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8797 * @return {Object} box An object in the format {x, y, width, height}
8799 getBox : function(contentBox, local){
8804 var left = parseInt(this.getStyle("left"), 10) || 0;
8805 var top = parseInt(this.getStyle("top"), 10) || 0;
8808 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8810 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8812 var l = this.getBorderWidth("l")+this.getPadding("l");
8813 var r = this.getBorderWidth("r")+this.getPadding("r");
8814 var t = this.getBorderWidth("t")+this.getPadding("t");
8815 var b = this.getBorderWidth("b")+this.getPadding("b");
8816 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)};
8818 bx.right = bx.x + bx.width;
8819 bx.bottom = bx.y + bx.height;
8824 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8825 for more information about the sides.
8826 * @param {String} sides
8829 getFrameWidth : function(sides, onlyContentBox){
8830 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8834 * 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.
8835 * @param {Object} box The box to fill {x, y, width, height}
8836 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8837 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8838 * @return {Roo.Element} this
8840 setBox : function(box, adjust, animate){
8841 var w = box.width, h = box.height;
8842 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8843 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8844 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8846 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8851 * Forces the browser to repaint this element
8852 * @return {Roo.Element} this
8854 repaint : function(){
8856 this.addClass("x-repaint");
8857 setTimeout(function(){
8858 Roo.get(dom).removeClass("x-repaint");
8864 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8865 * then it returns the calculated width of the sides (see getPadding)
8866 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8867 * @return {Object/Number}
8869 getMargins : function(side){
8872 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8873 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8874 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8875 right: parseInt(this.getStyle("margin-right"), 10) || 0
8878 return this.addStyles(side, El.margins);
8883 addStyles : function(sides, styles){
8885 for(var i = 0, len = sides.length; i < len; i++){
8886 v = this.getStyle(styles[sides.charAt(i)]);
8888 w = parseInt(v, 10);
8896 * Creates a proxy element of this element
8897 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8898 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8899 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8900 * @return {Roo.Element} The new proxy element
8902 createProxy : function(config, renderTo, matchBox){
8904 renderTo = Roo.getDom(renderTo);
8906 renderTo = document.body;
8908 config = typeof config == "object" ?
8909 config : {tag : "div", cls: config};
8910 var proxy = Roo.DomHelper.append(renderTo, config, true);
8912 proxy.setBox(this.getBox());
8918 * Puts a mask over this element to disable user interaction. Requires core.css.
8919 * This method can only be applied to elements which accept child nodes.
8920 * @param {String} msg (optional) A message to display in the mask
8921 * @param {String} msgCls (optional) A css class to apply to the msg element
8922 * @return {Element} The mask element
8924 mask : function(msg, msgCls)
8926 if(this.getStyle("position") == "static"){
8927 this.setStyle("position", "relative");
8930 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8932 this.addClass("x-masked");
8933 this._mask.setDisplayed(true);
8938 while (dom && dom.style) {
8939 if (!isNaN(parseInt(dom.style.zIndex))) {
8940 z = Math.max(z, parseInt(dom.style.zIndex));
8942 dom = dom.parentNode;
8944 // if we are masking the body - then it hides everything..
8945 if (this.dom == document.body) {
8947 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
8948 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
8951 if(typeof msg == 'string'){
8953 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8955 var mm = this._maskMsg;
8956 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8957 mm.dom.firstChild.innerHTML = msg;
8958 mm.setDisplayed(true);
8960 mm.setStyle('z-index', z + 102);
8962 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8963 this._mask.setHeight(this.getHeight());
8965 this._mask.setStyle('z-index', z + 100);
8971 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8972 * it is cached for reuse.
8974 unmask : function(removeEl){
8976 if(removeEl === true){
8977 this._mask.remove();
8980 this._maskMsg.remove();
8981 delete this._maskMsg;
8984 this._mask.setDisplayed(false);
8986 this._maskMsg.setDisplayed(false);
8990 this.removeClass("x-masked");
8994 * Returns true if this element is masked
8997 isMasked : function(){
8998 return this._mask && this._mask.isVisible();
9002 * Creates an iframe shim for this element to keep selects and other windowed objects from
9004 * @return {Roo.Element} The new shim element
9006 createShim : function(){
9007 var el = document.createElement('iframe');
9008 el.frameBorder = 'no';
9009 el.className = 'roo-shim';
9010 if(Roo.isIE && Roo.isSecure){
9011 el.src = Roo.SSL_SECURE_URL;
9013 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9014 shim.autoBoxAdjust = false;
9019 * Removes this element from the DOM and deletes it from the cache
9021 remove : function(){
9022 if(this.dom.parentNode){
9023 this.dom.parentNode.removeChild(this.dom);
9025 delete El.cache[this.dom.id];
9029 * Sets up event handlers to add and remove a css class when the mouse is over this element
9030 * @param {String} className
9031 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9032 * mouseout events for children elements
9033 * @return {Roo.Element} this
9035 addClassOnOver : function(className, preventFlicker){
9036 this.on("mouseover", function(){
9037 Roo.fly(this, '_internal').addClass(className);
9039 var removeFn = function(e){
9040 if(preventFlicker !== true || !e.within(this, true)){
9041 Roo.fly(this, '_internal').removeClass(className);
9044 this.on("mouseout", removeFn, this.dom);
9049 * Sets up event handlers to add and remove a css class when this element has the focus
9050 * @param {String} className
9051 * @return {Roo.Element} this
9053 addClassOnFocus : function(className){
9054 this.on("focus", function(){
9055 Roo.fly(this, '_internal').addClass(className);
9057 this.on("blur", function(){
9058 Roo.fly(this, '_internal').removeClass(className);
9063 * 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)
9064 * @param {String} className
9065 * @return {Roo.Element} this
9067 addClassOnClick : function(className){
9069 this.on("mousedown", function(){
9070 Roo.fly(dom, '_internal').addClass(className);
9071 var d = Roo.get(document);
9072 var fn = function(){
9073 Roo.fly(dom, '_internal').removeClass(className);
9074 d.removeListener("mouseup", fn);
9076 d.on("mouseup", fn);
9082 * Stops the specified event from bubbling and optionally prevents the default action
9083 * @param {String} eventName
9084 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9085 * @return {Roo.Element} this
9087 swallowEvent : function(eventName, preventDefault){
9088 var fn = function(e){
9089 e.stopPropagation();
9094 if(eventName instanceof Array){
9095 for(var i = 0, len = eventName.length; i < len; i++){
9096 this.on(eventName[i], fn);
9100 this.on(eventName, fn);
9107 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9110 * Sizes this element to its parent element's dimensions performing
9111 * neccessary box adjustments.
9112 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9113 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9114 * @return {Roo.Element} this
9116 fitToParent : function(monitorResize, targetParent) {
9117 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9118 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9119 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9122 var p = Roo.get(targetParent || this.dom.parentNode);
9123 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9124 if (monitorResize === true) {
9125 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9126 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9132 * Gets the next sibling, skipping text nodes
9133 * @return {HTMLElement} The next sibling or null
9135 getNextSibling : function(){
9136 var n = this.dom.nextSibling;
9137 while(n && n.nodeType != 1){
9144 * Gets the previous sibling, skipping text nodes
9145 * @return {HTMLElement} The previous sibling or null
9147 getPrevSibling : function(){
9148 var n = this.dom.previousSibling;
9149 while(n && n.nodeType != 1){
9150 n = n.previousSibling;
9157 * Appends the passed element(s) to this element
9158 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9159 * @return {Roo.Element} this
9161 appendChild: function(el){
9168 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9169 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9170 * automatically generated with the specified attributes.
9171 * @param {HTMLElement} insertBefore (optional) a child element of this element
9172 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9173 * @return {Roo.Element} The new child element
9175 createChild: function(config, insertBefore, returnDom){
9176 config = config || {tag:'div'};
9178 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9180 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9184 * Appends this element to the passed element
9185 * @param {String/HTMLElement/Element} el The new parent element
9186 * @return {Roo.Element} this
9188 appendTo: function(el){
9189 el = Roo.getDom(el);
9190 el.appendChild(this.dom);
9195 * Inserts this element before the passed element in the DOM
9196 * @param {String/HTMLElement/Element} el The element to insert before
9197 * @return {Roo.Element} this
9199 insertBefore: function(el){
9200 el = Roo.getDom(el);
9201 el.parentNode.insertBefore(this.dom, el);
9206 * Inserts this element after the passed element in the DOM
9207 * @param {String/HTMLElement/Element} el The element to insert after
9208 * @return {Roo.Element} this
9210 insertAfter: function(el){
9211 el = Roo.getDom(el);
9212 el.parentNode.insertBefore(this.dom, el.nextSibling);
9217 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9218 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9219 * @return {Roo.Element} The new child
9221 insertFirst: function(el, returnDom){
9223 if(typeof el == 'object' && !el.nodeType){ // dh config
9224 return this.createChild(el, this.dom.firstChild, returnDom);
9226 el = Roo.getDom(el);
9227 this.dom.insertBefore(el, this.dom.firstChild);
9228 return !returnDom ? Roo.get(el) : el;
9233 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9234 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9235 * @param {String} where (optional) 'before' or 'after' defaults to before
9236 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9237 * @return {Roo.Element} the inserted Element
9239 insertSibling: function(el, where, returnDom){
9240 where = where ? where.toLowerCase() : 'before';
9242 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9244 if(typeof el == 'object' && !el.nodeType){ // dh config
9245 if(where == 'after' && !this.dom.nextSibling){
9246 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9248 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9252 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9253 where == 'before' ? this.dom : this.dom.nextSibling);
9262 * Creates and wraps this element with another element
9263 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9264 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9265 * @return {HTMLElement/Element} The newly created wrapper element
9267 wrap: function(config, returnDom){
9269 config = {tag: "div"};
9271 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9272 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9277 * Replaces the passed element with this element
9278 * @param {String/HTMLElement/Element} el The element to replace
9279 * @return {Roo.Element} this
9281 replace: function(el){
9283 this.insertBefore(el);
9289 * Inserts an html fragment into this element
9290 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9291 * @param {String} html The HTML fragment
9292 * @param {Boolean} returnEl True to return an Roo.Element
9293 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9295 insertHtml : function(where, html, returnEl){
9296 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9297 return returnEl ? Roo.get(el) : el;
9301 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9302 * @param {Object} o The object with the attributes
9303 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9304 * @return {Roo.Element} this
9306 set : function(o, useSet){
9308 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9310 if(attr == "style" || typeof o[attr] == "function") continue;
9312 el.className = o["cls"];
9314 if(useSet) el.setAttribute(attr, o[attr]);
9315 else el[attr] = o[attr];
9319 Roo.DomHelper.applyStyles(el, o.style);
9325 * Convenience method for constructing a KeyMap
9326 * @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:
9327 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9328 * @param {Function} fn The function to call
9329 * @param {Object} scope (optional) The scope of the function
9330 * @return {Roo.KeyMap} The KeyMap created
9332 addKeyListener : function(key, fn, scope){
9334 if(typeof key != "object" || key instanceof Array){
9350 return new Roo.KeyMap(this, config);
9354 * Creates a KeyMap for this element
9355 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9356 * @return {Roo.KeyMap} The KeyMap created
9358 addKeyMap : function(config){
9359 return new Roo.KeyMap(this, config);
9363 * Returns true if this element is scrollable.
9366 isScrollable : function(){
9368 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9372 * 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().
9373 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9374 * @param {Number} value The new scroll value
9375 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9376 * @return {Element} this
9379 scrollTo : function(side, value, animate){
9380 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9382 this.dom[prop] = value;
9384 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9385 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9391 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9392 * within this element's scrollable range.
9393 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9394 * @param {Number} distance How far to scroll the element in pixels
9395 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9396 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9397 * was scrolled as far as it could go.
9399 scroll : function(direction, distance, animate){
9400 if(!this.isScrollable()){
9404 var l = el.scrollLeft, t = el.scrollTop;
9405 var w = el.scrollWidth, h = el.scrollHeight;
9406 var cw = el.clientWidth, ch = el.clientHeight;
9407 direction = direction.toLowerCase();
9408 var scrolled = false;
9409 var a = this.preanim(arguments, 2);
9414 var v = Math.min(l + distance, w-cw);
9415 this.scrollTo("left", v, a);
9422 var v = Math.max(l - distance, 0);
9423 this.scrollTo("left", v, a);
9431 var v = Math.max(t - distance, 0);
9432 this.scrollTo("top", v, a);
9440 var v = Math.min(t + distance, h-ch);
9441 this.scrollTo("top", v, a);
9450 * Translates the passed page coordinates into left/top css values for this element
9451 * @param {Number/Array} x The page x or an array containing [x, y]
9452 * @param {Number} y The page y
9453 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9455 translatePoints : function(x, y){
9456 if(typeof x == 'object' || x instanceof Array){
9459 var p = this.getStyle('position');
9460 var o = this.getXY();
9462 var l = parseInt(this.getStyle('left'), 10);
9463 var t = parseInt(this.getStyle('top'), 10);
9466 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9469 t = (p == "relative") ? 0 : this.dom.offsetTop;
9472 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9476 * Returns the current scroll position of the element.
9477 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9479 getScroll : function(){
9480 var d = this.dom, doc = document;
9481 if(d == doc || d == doc.body){
9482 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9483 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9484 return {left: l, top: t};
9486 return {left: d.scrollLeft, top: d.scrollTop};
9491 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9492 * are convert to standard 6 digit hex color.
9493 * @param {String} attr The css attribute
9494 * @param {String} defaultValue The default value to use when a valid color isn't found
9495 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9498 getColor : function(attr, defaultValue, prefix){
9499 var v = this.getStyle(attr);
9500 if(!v || v == "transparent" || v == "inherit") {
9501 return defaultValue;
9503 var color = typeof prefix == "undefined" ? "#" : prefix;
9504 if(v.substr(0, 4) == "rgb("){
9505 var rvs = v.slice(4, v.length -1).split(",");
9506 for(var i = 0; i < 3; i++){
9507 var h = parseInt(rvs[i]).toString(16);
9514 if(v.substr(0, 1) == "#"){
9516 for(var i = 1; i < 4; i++){
9517 var c = v.charAt(i);
9520 }else if(v.length == 7){
9521 color += v.substr(1);
9525 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9529 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9530 * gradient background, rounded corners and a 4-way shadow.
9531 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9532 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9533 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9534 * @return {Roo.Element} this
9536 boxWrap : function(cls){
9537 cls = cls || 'x-box';
9538 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9539 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9544 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9545 * @param {String} namespace The namespace in which to look for the attribute
9546 * @param {String} name The attribute name
9547 * @return {String} The attribute value
9549 getAttributeNS : Roo.isIE ? function(ns, name){
9551 var type = typeof d[ns+":"+name];
9552 if(type != 'undefined' && type != 'unknown'){
9553 return d[ns+":"+name];
9556 } : function(ns, name){
9558 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9563 * Sets or Returns the value the dom attribute value
9564 * @param {String} name The attribute name
9565 * @param {String} value (optional) The value to set the attribute to
9566 * @return {String} The attribute value
9568 attr : function(name){
9569 if (arguments.length > 1) {
9570 this.dom.setAttribute(name, arguments[1]);
9571 return arguments[1];
9573 if (!this.dom.hasAttribute(name)) {
9576 return this.dom.getAttribute(name);
9583 var ep = El.prototype;
9586 * Appends an event handler (Shorthand for addListener)
9587 * @param {String} eventName The type of event to append
9588 * @param {Function} fn The method the event invokes
9589 * @param {Object} scope (optional) The scope (this object) of the fn
9590 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9593 ep.on = ep.addListener;
9595 ep.mon = ep.addListener;
9598 * Removes an event handler from this element (shorthand for removeListener)
9599 * @param {String} eventName the type of event to remove
9600 * @param {Function} fn the method the event invokes
9601 * @return {Roo.Element} this
9604 ep.un = ep.removeListener;
9607 * true to automatically adjust width and height settings for box-model issues (default to true)
9609 ep.autoBoxAdjust = true;
9612 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9615 El.addUnits = function(v, defaultUnit){
9616 if(v === "" || v == "auto"){
9619 if(v === undefined){
9622 if(typeof v == "number" || !El.unitPattern.test(v)){
9623 return v + (defaultUnit || 'px');
9628 // special markup used throughout Roo when box wrapping elements
9629 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>';
9631 * Visibility mode constant - Use visibility to hide element
9637 * Visibility mode constant - Use display to hide element
9643 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9644 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9645 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9657 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9658 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9659 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9660 * @return {Element} The Element object
9663 El.get = function(el){
9665 if(!el){ return null; }
9666 if(typeof el == "string"){ // element id
9667 if(!(elm = document.getElementById(el))){
9670 if(ex = El.cache[el]){
9673 ex = El.cache[el] = new El(elm);
9676 }else if(el.tagName){ // dom element
9680 if(ex = El.cache[id]){
9683 ex = El.cache[id] = new El(el);
9686 }else if(el instanceof El){
9688 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9689 // catch case where it hasn't been appended
9690 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9693 }else if(el.isComposite){
9695 }else if(el instanceof Array){
9696 return El.select(el);
9697 }else if(el == document){
9698 // create a bogus element object representing the document object
9700 var f = function(){};
9701 f.prototype = El.prototype;
9703 docEl.dom = document;
9711 El.uncache = function(el){
9712 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9714 delete El.cache[a[i].id || a[i]];
9720 // Garbage collection - uncache elements/purge listeners on orphaned elements
9721 // so we don't hold a reference and cause the browser to retain them
9722 El.garbageCollect = function(){
9723 if(!Roo.enableGarbageCollector){
9724 clearInterval(El.collectorThread);
9727 for(var eid in El.cache){
9728 var el = El.cache[eid], d = el.dom;
9729 // -------------------------------------------------------
9730 // Determining what is garbage:
9731 // -------------------------------------------------------
9733 // dom node is null, definitely garbage
9734 // -------------------------------------------------------
9736 // no parentNode == direct orphan, definitely garbage
9737 // -------------------------------------------------------
9738 // !d.offsetParent && !document.getElementById(eid)
9739 // display none elements have no offsetParent so we will
9740 // also try to look it up by it's id. However, check
9741 // offsetParent first so we don't do unneeded lookups.
9742 // This enables collection of elements that are not orphans
9743 // directly, but somewhere up the line they have an orphan
9745 // -------------------------------------------------------
9746 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9747 delete El.cache[eid];
9748 if(d && Roo.enableListenerCollection){
9754 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9758 El.Flyweight = function(dom){
9761 El.Flyweight.prototype = El.prototype;
9763 El._flyweights = {};
9765 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9766 * the dom node can be overwritten by other code.
9767 * @param {String/HTMLElement} el The dom node or id
9768 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9769 * prevent conflicts (e.g. internally Roo uses "_internal")
9771 * @return {Element} The shared Element object
9773 El.fly = function(el, named){
9774 named = named || '_global';
9775 el = Roo.getDom(el);
9779 if(!El._flyweights[named]){
9780 El._flyweights[named] = new El.Flyweight();
9782 El._flyweights[named].dom = el;
9783 return El._flyweights[named];
9787 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9788 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9789 * Shorthand of {@link Roo.Element#get}
9790 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9791 * @return {Element} The Element object
9797 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9798 * the dom node can be overwritten by other code.
9799 * Shorthand of {@link Roo.Element#fly}
9800 * @param {String/HTMLElement} el The dom node or id
9801 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9802 * prevent conflicts (e.g. internally Roo uses "_internal")
9804 * @return {Element} The shared Element object
9810 // speedy lookup for elements never to box adjust
9811 var noBoxAdjust = Roo.isStrict ? {
9814 input:1, select:1, textarea:1
9816 if(Roo.isIE || Roo.isGecko){
9817 noBoxAdjust['button'] = 1;
9821 Roo.EventManager.on(window, 'unload', function(){
9823 delete El._flyweights;
9831 Roo.Element.selectorFunction = Roo.DomQuery.select;
9834 Roo.Element.select = function(selector, unique, root){
9836 if(typeof selector == "string"){
9837 els = Roo.Element.selectorFunction(selector, root);
9838 }else if(selector.length !== undefined){
9841 throw "Invalid selector";
9843 if(unique === true){
9844 return new Roo.CompositeElement(els);
9846 return new Roo.CompositeElementLite(els);
9850 * Selects elements based on the passed CSS selector to enable working on them as 1.
9851 * @param {String/Array} selector The CSS selector or an array of elements
9852 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9853 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9854 * @return {CompositeElementLite/CompositeElement}
9858 Roo.select = Roo.Element.select;
9875 * Ext JS Library 1.1.1
9876 * Copyright(c) 2006-2007, Ext JS, LLC.
9878 * Originally Released Under LGPL - original licence link has changed is not relivant.
9881 * <script type="text/javascript">
9886 //Notifies Element that fx methods are available
9887 Roo.enableFx = true;
9891 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9892 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9893 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9894 * Element effects to work.</p><br/>
9896 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9897 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9898 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9899 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9900 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9901 * expected results and should be done with care.</p><br/>
9903 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9904 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9907 ----- -----------------------------
9908 tl The top left corner
9909 t The center of the top edge
9910 tr The top right corner
9911 l The center of the left edge
9912 r The center of the right edge
9913 bl The bottom left corner
9914 b The center of the bottom edge
9915 br The bottom right corner
9917 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9918 * below are common options that can be passed to any Fx method.</b>
9919 * @cfg {Function} callback A function called when the effect is finished
9920 * @cfg {Object} scope The scope of the effect function
9921 * @cfg {String} easing A valid Easing value for the effect
9922 * @cfg {String} afterCls A css class to apply after the effect
9923 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9924 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9925 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9926 * effects that end with the element being visually hidden, ignored otherwise)
9927 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9928 * a function which returns such a specification that will be applied to the Element after the effect finishes
9929 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9930 * @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
9931 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9935 * Slides the element into view. An anchor point can be optionally passed to set the point of
9936 * origin for the slide effect. This function automatically handles wrapping the element with
9937 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9940 // default: slide the element in from the top
9943 // custom: slide the element in from the right with a 2-second duration
9944 el.slideIn('r', { duration: 2 });
9946 // common config options shown with default values
9952 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9953 * @param {Object} options (optional) Object literal with any of the Fx config options
9954 * @return {Roo.Element} The Element
9956 slideIn : function(anchor, o){
9957 var el = this.getFxEl();
9960 el.queueFx(o, function(){
9962 anchor = anchor || "t";
9964 // fix display to visibility
9967 // restore values after effect
9968 var r = this.getFxRestore();
9969 var b = this.getBox();
9970 // fixed size for slide
9974 var wrap = this.fxWrap(r.pos, o, "hidden");
9976 var st = this.dom.style;
9977 st.visibility = "visible";
9978 st.position = "absolute";
9980 // clear out temp styles after slide and unwrap
9981 var after = function(){
9982 el.fxUnwrap(wrap, r.pos, o);
9984 st.height = r.height;
9987 // time to calc the positions
9988 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9990 switch(anchor.toLowerCase()){
9992 wrap.setSize(b.width, 0);
9993 st.left = st.bottom = "0";
9997 wrap.setSize(0, b.height);
9998 st.right = st.top = "0";
10002 wrap.setSize(0, b.height);
10003 wrap.setX(b.right);
10004 st.left = st.top = "0";
10005 a = {width: bw, points: pt};
10008 wrap.setSize(b.width, 0);
10009 wrap.setY(b.bottom);
10010 st.left = st.top = "0";
10011 a = {height: bh, points: pt};
10014 wrap.setSize(0, 0);
10015 st.right = st.bottom = "0";
10016 a = {width: bw, height: bh};
10019 wrap.setSize(0, 0);
10020 wrap.setY(b.y+b.height);
10021 st.right = st.top = "0";
10022 a = {width: bw, height: bh, points: pt};
10025 wrap.setSize(0, 0);
10026 wrap.setXY([b.right, b.bottom]);
10027 st.left = st.top = "0";
10028 a = {width: bw, height: bh, points: pt};
10031 wrap.setSize(0, 0);
10032 wrap.setX(b.x+b.width);
10033 st.left = st.bottom = "0";
10034 a = {width: bw, height: bh, points: pt};
10037 this.dom.style.visibility = "visible";
10040 arguments.callee.anim = wrap.fxanim(a,
10050 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10051 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10052 * 'hidden') but block elements will still take up space in the document. The element must be removed
10053 * from the DOM using the 'remove' config option if desired. This function automatically handles
10054 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10057 // default: slide the element out to the top
10060 // custom: slide the element out to the right with a 2-second duration
10061 el.slideOut('r', { duration: 2 });
10063 // common config options shown with default values
10071 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10072 * @param {Object} options (optional) Object literal with any of the Fx config options
10073 * @return {Roo.Element} The Element
10075 slideOut : function(anchor, o){
10076 var el = this.getFxEl();
10079 el.queueFx(o, function(){
10081 anchor = anchor || "t";
10083 // restore values after effect
10084 var r = this.getFxRestore();
10086 var b = this.getBox();
10087 // fixed size for slide
10091 var wrap = this.fxWrap(r.pos, o, "visible");
10093 var st = this.dom.style;
10094 st.visibility = "visible";
10095 st.position = "absolute";
10099 var after = function(){
10101 el.setDisplayed(false);
10106 el.fxUnwrap(wrap, r.pos, o);
10108 st.width = r.width;
10109 st.height = r.height;
10114 var a, zero = {to: 0};
10115 switch(anchor.toLowerCase()){
10117 st.left = st.bottom = "0";
10118 a = {height: zero};
10121 st.right = st.top = "0";
10125 st.left = st.top = "0";
10126 a = {width: zero, points: {to:[b.right, b.y]}};
10129 st.left = st.top = "0";
10130 a = {height: zero, points: {to:[b.x, b.bottom]}};
10133 st.right = st.bottom = "0";
10134 a = {width: zero, height: zero};
10137 st.right = st.top = "0";
10138 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10141 st.left = st.top = "0";
10142 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10145 st.left = st.bottom = "0";
10146 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10150 arguments.callee.anim = wrap.fxanim(a,
10160 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10161 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10162 * The element must be removed from the DOM using the 'remove' config option if desired.
10168 // common config options shown with default values
10176 * @param {Object} options (optional) Object literal with any of the Fx config options
10177 * @return {Roo.Element} The Element
10179 puff : function(o){
10180 var el = this.getFxEl();
10183 el.queueFx(o, function(){
10184 this.clearOpacity();
10187 // restore values after effect
10188 var r = this.getFxRestore();
10189 var st = this.dom.style;
10191 var after = function(){
10193 el.setDisplayed(false);
10200 el.setPositioning(r.pos);
10201 st.width = r.width;
10202 st.height = r.height;
10207 var width = this.getWidth();
10208 var height = this.getHeight();
10210 arguments.callee.anim = this.fxanim({
10211 width : {to: this.adjustWidth(width * 2)},
10212 height : {to: this.adjustHeight(height * 2)},
10213 points : {by: [-(width * .5), -(height * .5)]},
10215 fontSize: {to:200, unit: "%"}
10226 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10227 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10228 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10234 // all config options shown with default values
10242 * @param {Object} options (optional) Object literal with any of the Fx config options
10243 * @return {Roo.Element} The Element
10245 switchOff : function(o){
10246 var el = this.getFxEl();
10249 el.queueFx(o, function(){
10250 this.clearOpacity();
10253 // restore values after effect
10254 var r = this.getFxRestore();
10255 var st = this.dom.style;
10257 var after = function(){
10259 el.setDisplayed(false);
10265 el.setPositioning(r.pos);
10266 st.width = r.width;
10267 st.height = r.height;
10272 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10273 this.clearOpacity();
10277 points:{by:[0, this.getHeight() * .5]}
10278 }, o, 'motion', 0.3, 'easeIn', after);
10279 }).defer(100, this);
10286 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10287 * changed using the "attr" config option) and then fading back to the original color. If no original
10288 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10291 // default: highlight background to yellow
10294 // custom: highlight foreground text to blue for 2 seconds
10295 el.highlight("0000ff", { attr: 'color', duration: 2 });
10297 // common config options shown with default values
10298 el.highlight("ffff9c", {
10299 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10300 endColor: (current color) or "ffffff",
10305 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10306 * @param {Object} options (optional) Object literal with any of the Fx config options
10307 * @return {Roo.Element} The Element
10309 highlight : function(color, o){
10310 var el = this.getFxEl();
10313 el.queueFx(o, function(){
10314 color = color || "ffff9c";
10315 attr = o.attr || "backgroundColor";
10317 this.clearOpacity();
10320 var origColor = this.getColor(attr);
10321 var restoreColor = this.dom.style[attr];
10322 endColor = (o.endColor || origColor) || "ffffff";
10324 var after = function(){
10325 el.dom.style[attr] = restoreColor;
10330 a[attr] = {from: color, to: endColor};
10331 arguments.callee.anim = this.fxanim(a,
10341 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10344 // default: a single light blue ripple
10347 // custom: 3 red ripples lasting 3 seconds total
10348 el.frame("ff0000", 3, { duration: 3 });
10350 // common config options shown with default values
10351 el.frame("C3DAF9", 1, {
10352 duration: 1 //duration of entire animation (not each individual ripple)
10353 // Note: Easing is not configurable and will be ignored if included
10356 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10357 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10358 * @param {Object} options (optional) Object literal with any of the Fx config options
10359 * @return {Roo.Element} The Element
10361 frame : function(color, count, o){
10362 var el = this.getFxEl();
10365 el.queueFx(o, function(){
10366 color = color || "#C3DAF9";
10367 if(color.length == 6){
10368 color = "#" + color;
10370 count = count || 1;
10371 duration = o.duration || 1;
10374 var b = this.getBox();
10375 var animFn = function(){
10376 var proxy = this.createProxy({
10379 visbility:"hidden",
10380 position:"absolute",
10381 "z-index":"35000", // yee haw
10382 border:"0px solid " + color
10385 var scale = Roo.isBorderBox ? 2 : 1;
10387 top:{from:b.y, to:b.y - 20},
10388 left:{from:b.x, to:b.x - 20},
10389 borderWidth:{from:0, to:10},
10390 opacity:{from:1, to:0},
10391 height:{from:b.height, to:(b.height + (20*scale))},
10392 width:{from:b.width, to:(b.width + (20*scale))}
10393 }, duration, function(){
10397 animFn.defer((duration/2)*1000, this);
10408 * Creates a pause before any subsequent queued effects begin. If there are
10409 * no effects queued after the pause it will have no effect.
10414 * @param {Number} seconds The length of time to pause (in seconds)
10415 * @return {Roo.Element} The Element
10417 pause : function(seconds){
10418 var el = this.getFxEl();
10421 el.queueFx(o, function(){
10422 setTimeout(function(){
10424 }, seconds * 1000);
10430 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10431 * using the "endOpacity" config option.
10434 // default: fade in from opacity 0 to 100%
10437 // custom: fade in from opacity 0 to 75% over 2 seconds
10438 el.fadeIn({ endOpacity: .75, duration: 2});
10440 // common config options shown with default values
10442 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10447 * @param {Object} options (optional) Object literal with any of the Fx config options
10448 * @return {Roo.Element} The Element
10450 fadeIn : function(o){
10451 var el = this.getFxEl();
10453 el.queueFx(o, function(){
10454 this.setOpacity(0);
10456 this.dom.style.visibility = 'visible';
10457 var to = o.endOpacity || 1;
10458 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10459 o, null, .5, "easeOut", function(){
10461 this.clearOpacity();
10470 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10471 * using the "endOpacity" config option.
10474 // default: fade out from the element's current opacity to 0
10477 // custom: fade out from the element's current opacity to 25% over 2 seconds
10478 el.fadeOut({ endOpacity: .25, duration: 2});
10480 // common config options shown with default values
10482 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10489 * @param {Object} options (optional) Object literal with any of the Fx config options
10490 * @return {Roo.Element} The Element
10492 fadeOut : function(o){
10493 var el = this.getFxEl();
10495 el.queueFx(o, function(){
10496 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10497 o, null, .5, "easeOut", function(){
10498 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10499 this.dom.style.display = "none";
10501 this.dom.style.visibility = "hidden";
10503 this.clearOpacity();
10511 * Animates the transition of an element's dimensions from a starting height/width
10512 * to an ending height/width.
10515 // change height and width to 100x100 pixels
10516 el.scale(100, 100);
10518 // common config options shown with default values. The height and width will default to
10519 // the element's existing values if passed as null.
10522 [element's height], {
10527 * @param {Number} width The new width (pass undefined to keep the original width)
10528 * @param {Number} height The new height (pass undefined to keep the original height)
10529 * @param {Object} options (optional) Object literal with any of the Fx config options
10530 * @return {Roo.Element} The Element
10532 scale : function(w, h, o){
10533 this.shift(Roo.apply({}, o, {
10541 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10542 * Any of these properties not specified in the config object will not be changed. This effect
10543 * requires that at least one new dimension, position or opacity setting must be passed in on
10544 * the config object in order for the function to have any effect.
10547 // slide the element horizontally to x position 200 while changing the height and opacity
10548 el.shift({ x: 200, height: 50, opacity: .8 });
10550 // common config options shown with default values.
10552 width: [element's width],
10553 height: [element's height],
10554 x: [element's x position],
10555 y: [element's y position],
10556 opacity: [element's opacity],
10561 * @param {Object} options Object literal with any of the Fx config options
10562 * @return {Roo.Element} The Element
10564 shift : function(o){
10565 var el = this.getFxEl();
10567 el.queueFx(o, function(){
10568 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10569 if(w !== undefined){
10570 a.width = {to: this.adjustWidth(w)};
10572 if(h !== undefined){
10573 a.height = {to: this.adjustHeight(h)};
10575 if(x !== undefined || y !== undefined){
10577 x !== undefined ? x : this.getX(),
10578 y !== undefined ? y : this.getY()
10581 if(op !== undefined){
10582 a.opacity = {to: op};
10584 if(o.xy !== undefined){
10585 a.points = {to: o.xy};
10587 arguments.callee.anim = this.fxanim(a,
10588 o, 'motion', .35, "easeOut", function(){
10596 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10597 * ending point of the effect.
10600 // default: slide the element downward while fading out
10603 // custom: slide the element out to the right with a 2-second duration
10604 el.ghost('r', { duration: 2 });
10606 // common config options shown with default values
10614 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10615 * @param {Object} options (optional) Object literal with any of the Fx config options
10616 * @return {Roo.Element} The Element
10618 ghost : function(anchor, o){
10619 var el = this.getFxEl();
10622 el.queueFx(o, function(){
10623 anchor = anchor || "b";
10625 // restore values after effect
10626 var r = this.getFxRestore();
10627 var w = this.getWidth(),
10628 h = this.getHeight();
10630 var st = this.dom.style;
10632 var after = function(){
10634 el.setDisplayed(false);
10640 el.setPositioning(r.pos);
10641 st.width = r.width;
10642 st.height = r.height;
10647 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10648 switch(anchor.toLowerCase()){
10675 arguments.callee.anim = this.fxanim(a,
10685 * Ensures that all effects queued after syncFx is called on the element are
10686 * run concurrently. This is the opposite of {@link #sequenceFx}.
10687 * @return {Roo.Element} The Element
10689 syncFx : function(){
10690 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10699 * Ensures that all effects queued after sequenceFx is called on the element are
10700 * run in sequence. This is the opposite of {@link #syncFx}.
10701 * @return {Roo.Element} The Element
10703 sequenceFx : function(){
10704 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10706 concurrent : false,
10713 nextFx : function(){
10714 var ef = this.fxQueue[0];
10721 * Returns true if the element has any effects actively running or queued, else returns false.
10722 * @return {Boolean} True if element has active effects, else false
10724 hasActiveFx : function(){
10725 return this.fxQueue && this.fxQueue[0];
10729 * Stops any running effects and clears the element's internal effects queue if it contains
10730 * any additional effects that haven't started yet.
10731 * @return {Roo.Element} The Element
10733 stopFx : function(){
10734 if(this.hasActiveFx()){
10735 var cur = this.fxQueue[0];
10736 if(cur && cur.anim && cur.anim.isAnimated()){
10737 this.fxQueue = [cur]; // clear out others
10738 cur.anim.stop(true);
10745 beforeFx : function(o){
10746 if(this.hasActiveFx() && !o.concurrent){
10757 * Returns true if the element is currently blocking so that no other effect can be queued
10758 * until this effect is finished, else returns false if blocking is not set. This is commonly
10759 * used to ensure that an effect initiated by a user action runs to completion prior to the
10760 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10761 * @return {Boolean} True if blocking, else false
10763 hasFxBlock : function(){
10764 var q = this.fxQueue;
10765 return q && q[0] && q[0].block;
10769 queueFx : function(o, fn){
10773 if(!this.hasFxBlock()){
10774 Roo.applyIf(o, this.fxDefaults);
10776 var run = this.beforeFx(o);
10777 fn.block = o.block;
10778 this.fxQueue.push(fn);
10790 fxWrap : function(pos, o, vis){
10792 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10795 wrapXY = this.getXY();
10797 var div = document.createElement("div");
10798 div.style.visibility = vis;
10799 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10800 wrap.setPositioning(pos);
10801 if(wrap.getStyle("position") == "static"){
10802 wrap.position("relative");
10804 this.clearPositioning('auto');
10806 wrap.dom.appendChild(this.dom);
10808 wrap.setXY(wrapXY);
10815 fxUnwrap : function(wrap, pos, o){
10816 this.clearPositioning();
10817 this.setPositioning(pos);
10819 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10825 getFxRestore : function(){
10826 var st = this.dom.style;
10827 return {pos: this.getPositioning(), width: st.width, height : st.height};
10831 afterFx : function(o){
10833 this.applyStyles(o.afterStyle);
10836 this.addClass(o.afterCls);
10838 if(o.remove === true){
10841 Roo.callback(o.callback, o.scope, [this]);
10843 this.fxQueue.shift();
10849 getFxEl : function(){ // support for composite element fx
10850 return Roo.get(this.dom);
10854 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10855 animType = animType || 'run';
10857 var anim = Roo.lib.Anim[animType](
10859 (opt.duration || defaultDur) || .35,
10860 (opt.easing || defaultEase) || 'easeOut',
10862 Roo.callback(cb, this);
10871 // backwords compat
10872 Roo.Fx.resize = Roo.Fx.scale;
10874 //When included, Roo.Fx is automatically applied to Element so that all basic
10875 //effects are available directly via the Element API
10876 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10878 * Ext JS Library 1.1.1
10879 * Copyright(c) 2006-2007, Ext JS, LLC.
10881 * Originally Released Under LGPL - original licence link has changed is not relivant.
10884 * <script type="text/javascript">
10889 * @class Roo.CompositeElement
10890 * Standard composite class. Creates a Roo.Element for every element in the collection.
10892 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10893 * actions will be performed on all the elements in this collection.</b>
10895 * All methods return <i>this</i> and can be chained.
10897 var els = Roo.select("#some-el div.some-class", true);
10898 // or select directly from an existing element
10899 var el = Roo.get('some-el');
10900 el.select('div.some-class', true);
10902 els.setWidth(100); // all elements become 100 width
10903 els.hide(true); // all elements fade out and hide
10905 els.setWidth(100).hide(true);
10908 Roo.CompositeElement = function(els){
10909 this.elements = [];
10910 this.addElements(els);
10912 Roo.CompositeElement.prototype = {
10914 addElements : function(els){
10915 if(!els) return this;
10916 if(typeof els == "string"){
10917 els = Roo.Element.selectorFunction(els);
10919 var yels = this.elements;
10920 var index = yels.length-1;
10921 for(var i = 0, len = els.length; i < len; i++) {
10922 yels[++index] = Roo.get(els[i]);
10928 * Clears this composite and adds the elements returned by the passed selector.
10929 * @param {String/Array} els A string CSS selector, an array of elements or an element
10930 * @return {CompositeElement} this
10932 fill : function(els){
10933 this.elements = [];
10939 * Filters this composite to only elements that match the passed selector.
10940 * @param {String} selector A string CSS selector
10941 * @return {CompositeElement} this
10943 filter : function(selector){
10945 this.each(function(el){
10946 if(el.is(selector)){
10947 els[els.length] = el.dom;
10954 invoke : function(fn, args){
10955 var els = this.elements;
10956 for(var i = 0, len = els.length; i < len; i++) {
10957 Roo.Element.prototype[fn].apply(els[i], args);
10962 * Adds elements to this composite.
10963 * @param {String/Array} els A string CSS selector, an array of elements or an element
10964 * @return {CompositeElement} this
10966 add : function(els){
10967 if(typeof els == "string"){
10968 this.addElements(Roo.Element.selectorFunction(els));
10969 }else if(els.length !== undefined){
10970 this.addElements(els);
10972 this.addElements([els]);
10977 * Calls the passed function passing (el, this, index) for each element in this composite.
10978 * @param {Function} fn The function to call
10979 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10980 * @return {CompositeElement} this
10982 each : function(fn, scope){
10983 var els = this.elements;
10984 for(var i = 0, len = els.length; i < len; i++){
10985 if(fn.call(scope || els[i], els[i], this, i) === false) {
10993 * Returns the Element object at the specified index
10994 * @param {Number} index
10995 * @return {Roo.Element}
10997 item : function(index){
10998 return this.elements[index] || null;
11002 * Returns the first Element
11003 * @return {Roo.Element}
11005 first : function(){
11006 return this.item(0);
11010 * Returns the last Element
11011 * @return {Roo.Element}
11014 return this.item(this.elements.length-1);
11018 * Returns the number of elements in this composite
11021 getCount : function(){
11022 return this.elements.length;
11026 * Returns true if this composite contains the passed element
11029 contains : function(el){
11030 return this.indexOf(el) !== -1;
11034 * Returns true if this composite contains the passed element
11037 indexOf : function(el){
11038 return this.elements.indexOf(Roo.get(el));
11043 * Removes the specified element(s).
11044 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11045 * or an array of any of those.
11046 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11047 * @return {CompositeElement} this
11049 removeElement : function(el, removeDom){
11050 if(el instanceof Array){
11051 for(var i = 0, len = el.length; i < len; i++){
11052 this.removeElement(el[i]);
11056 var index = typeof el == 'number' ? el : this.indexOf(el);
11059 var d = this.elements[index];
11063 d.parentNode.removeChild(d);
11066 this.elements.splice(index, 1);
11072 * Replaces the specified element with the passed element.
11073 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11075 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11076 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11077 * @return {CompositeElement} this
11079 replaceElement : function(el, replacement, domReplace){
11080 var index = typeof el == 'number' ? el : this.indexOf(el);
11083 this.elements[index].replaceWith(replacement);
11085 this.elements.splice(index, 1, Roo.get(replacement))
11092 * Removes all elements.
11094 clear : function(){
11095 this.elements = [];
11099 Roo.CompositeElement.createCall = function(proto, fnName){
11100 if(!proto[fnName]){
11101 proto[fnName] = function(){
11102 return this.invoke(fnName, arguments);
11106 for(var fnName in Roo.Element.prototype){
11107 if(typeof Roo.Element.prototype[fnName] == "function"){
11108 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11114 * Ext JS Library 1.1.1
11115 * Copyright(c) 2006-2007, Ext JS, LLC.
11117 * Originally Released Under LGPL - original licence link has changed is not relivant.
11120 * <script type="text/javascript">
11124 * @class Roo.CompositeElementLite
11125 * @extends Roo.CompositeElement
11126 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11128 var els = Roo.select("#some-el div.some-class");
11129 // or select directly from an existing element
11130 var el = Roo.get('some-el');
11131 el.select('div.some-class');
11133 els.setWidth(100); // all elements become 100 width
11134 els.hide(true); // all elements fade out and hide
11136 els.setWidth(100).hide(true);
11137 </code></pre><br><br>
11138 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11139 * actions will be performed on all the elements in this collection.</b>
11141 Roo.CompositeElementLite = function(els){
11142 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11143 this.el = new Roo.Element.Flyweight();
11145 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11146 addElements : function(els){
11148 if(els instanceof Array){
11149 this.elements = this.elements.concat(els);
11151 var yels = this.elements;
11152 var index = yels.length-1;
11153 for(var i = 0, len = els.length; i < len; i++) {
11154 yels[++index] = els[i];
11160 invoke : function(fn, args){
11161 var els = this.elements;
11163 for(var i = 0, len = els.length; i < len; i++) {
11165 Roo.Element.prototype[fn].apply(el, args);
11170 * Returns a flyweight Element of the dom element object at the specified index
11171 * @param {Number} index
11172 * @return {Roo.Element}
11174 item : function(index){
11175 if(!this.elements[index]){
11178 this.el.dom = this.elements[index];
11182 // fixes scope with flyweight
11183 addListener : function(eventName, handler, scope, opt){
11184 var els = this.elements;
11185 for(var i = 0, len = els.length; i < len; i++) {
11186 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11192 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11193 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11194 * a reference to the dom node, use el.dom.</b>
11195 * @param {Function} fn The function to call
11196 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11197 * @return {CompositeElement} this
11199 each : function(fn, scope){
11200 var els = this.elements;
11202 for(var i = 0, len = els.length; i < len; i++){
11204 if(fn.call(scope || el, el, this, i) === false){
11211 indexOf : function(el){
11212 return this.elements.indexOf(Roo.getDom(el));
11215 replaceElement : function(el, replacement, domReplace){
11216 var index = typeof el == 'number' ? el : this.indexOf(el);
11218 replacement = Roo.getDom(replacement);
11220 var d = this.elements[index];
11221 d.parentNode.insertBefore(replacement, d);
11222 d.parentNode.removeChild(d);
11224 this.elements.splice(index, 1, replacement);
11229 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11233 * Ext JS Library 1.1.1
11234 * Copyright(c) 2006-2007, Ext JS, LLC.
11236 * Originally Released Under LGPL - original licence link has changed is not relivant.
11239 * <script type="text/javascript">
11245 * @class Roo.data.Connection
11246 * @extends Roo.util.Observable
11247 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11248 * either to a configured URL, or to a URL specified at request time.<br><br>
11250 * Requests made by this class are asynchronous, and will return immediately. No data from
11251 * the server will be available to the statement immediately following the {@link #request} call.
11252 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11254 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11255 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11256 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11257 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11258 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11259 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11260 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11261 * standard DOM methods.
11263 * @param {Object} config a configuration object.
11265 Roo.data.Connection = function(config){
11266 Roo.apply(this, config);
11269 * @event beforerequest
11270 * Fires before a network request is made to retrieve a data object.
11271 * @param {Connection} conn This Connection object.
11272 * @param {Object} options The options config object passed to the {@link #request} method.
11274 "beforerequest" : true,
11276 * @event requestcomplete
11277 * Fires if the request was successfully completed.
11278 * @param {Connection} conn This Connection object.
11279 * @param {Object} response The XHR object containing the response data.
11280 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11281 * @param {Object} options The options config object passed to the {@link #request} method.
11283 "requestcomplete" : true,
11285 * @event requestexception
11286 * Fires if an error HTTP status was returned from the server.
11287 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
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 "requestexception" : true
11295 Roo.data.Connection.superclass.constructor.call(this);
11298 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11300 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11303 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11304 * extra parameters to each request made by this object. (defaults to undefined)
11307 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11308 * to each request made by this object. (defaults to undefined)
11311 * @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)
11314 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11318 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11324 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11327 disableCaching: true,
11330 * Sends an HTTP request to a remote server.
11331 * @param {Object} options An object which may contain the following properties:<ul>
11332 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11333 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11334 * request, a url encoded string or a function to call to get either.</li>
11335 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11336 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11337 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11338 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11339 * <li>options {Object} The parameter to the request call.</li>
11340 * <li>success {Boolean} True if the request succeeded.</li>
11341 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11343 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11344 * The callback is passed the following parameters:<ul>
11345 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11346 * <li>options {Object} The parameter to the request call.</li>
11348 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11349 * The callback is passed the following parameters:<ul>
11350 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11351 * <li>options {Object} The parameter to the request call.</li>
11353 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11354 * for the callback function. Defaults to the browser window.</li>
11355 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11356 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11357 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11358 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11359 * params for the post data. Any params will be appended to the URL.</li>
11360 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11362 * @return {Number} transactionId
11364 request : function(o){
11365 if(this.fireEvent("beforerequest", this, o) !== false){
11368 if(typeof p == "function"){
11369 p = p.call(o.scope||window, o);
11371 if(typeof p == "object"){
11372 p = Roo.urlEncode(o.params);
11374 if(this.extraParams){
11375 var extras = Roo.urlEncode(this.extraParams);
11376 p = p ? (p + '&' + extras) : extras;
11379 var url = o.url || this.url;
11380 if(typeof url == 'function'){
11381 url = url.call(o.scope||window, o);
11385 var form = Roo.getDom(o.form);
11386 url = url || form.action;
11388 var enctype = form.getAttribute("enctype");
11389 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11390 return this.doFormUpload(o, p, url);
11392 var f = Roo.lib.Ajax.serializeForm(form);
11393 p = p ? (p + '&' + f) : f;
11396 var hs = o.headers;
11397 if(this.defaultHeaders){
11398 hs = Roo.apply(hs || {}, this.defaultHeaders);
11405 success: this.handleResponse,
11406 failure: this.handleFailure,
11408 argument: {options: o},
11409 timeout : o.timeout || this.timeout
11412 var method = o.method||this.method||(p ? "POST" : "GET");
11414 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11415 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11418 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11422 }else if(this.autoAbort !== false){
11426 if((method == 'GET' && p) || o.xmlData){
11427 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11430 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11431 return this.transId;
11433 Roo.callback(o.callback, o.scope, [o, null, null]);
11439 * Determine whether this object has a request outstanding.
11440 * @param {Number} transactionId (Optional) defaults to the last transaction
11441 * @return {Boolean} True if there is an outstanding request.
11443 isLoading : function(transId){
11445 return Roo.lib.Ajax.isCallInProgress(transId);
11447 return this.transId ? true : false;
11452 * Aborts any outstanding request.
11453 * @param {Number} transactionId (Optional) defaults to the last transaction
11455 abort : function(transId){
11456 if(transId || this.isLoading()){
11457 Roo.lib.Ajax.abort(transId || this.transId);
11462 handleResponse : function(response){
11463 this.transId = false;
11464 var options = response.argument.options;
11465 response.argument = options ? options.argument : null;
11466 this.fireEvent("requestcomplete", this, response, options);
11467 Roo.callback(options.success, options.scope, [response, options]);
11468 Roo.callback(options.callback, options.scope, [options, true, response]);
11472 handleFailure : function(response, e){
11473 this.transId = false;
11474 var options = response.argument.options;
11475 response.argument = options ? options.argument : null;
11476 this.fireEvent("requestexception", this, response, options, e);
11477 Roo.callback(options.failure, options.scope, [response, options]);
11478 Roo.callback(options.callback, options.scope, [options, false, response]);
11482 doFormUpload : function(o, ps, url){
11484 var frame = document.createElement('iframe');
11487 frame.className = 'x-hidden';
11489 frame.src = Roo.SSL_SECURE_URL;
11491 document.body.appendChild(frame);
11494 document.frames[id].name = id;
11497 var form = Roo.getDom(o.form);
11499 form.method = 'POST';
11500 form.enctype = form.encoding = 'multipart/form-data';
11506 if(ps){ // add dynamic params
11508 ps = Roo.urlDecode(ps, false);
11510 if(ps.hasOwnProperty(k)){
11511 hd = document.createElement('input');
11512 hd.type = 'hidden';
11515 form.appendChild(hd);
11522 var r = { // bogus response object
11527 r.argument = o ? o.argument : null;
11532 doc = frame.contentWindow.document;
11534 doc = (frame.contentDocument || window.frames[id].document);
11536 if(doc && doc.body){
11537 r.responseText = doc.body.innerHTML;
11539 if(doc && doc.XMLDocument){
11540 r.responseXML = doc.XMLDocument;
11542 r.responseXML = doc;
11549 Roo.EventManager.removeListener(frame, 'load', cb, this);
11551 this.fireEvent("requestcomplete", this, r, o);
11552 Roo.callback(o.success, o.scope, [r, o]);
11553 Roo.callback(o.callback, o.scope, [o, true, r]);
11555 setTimeout(function(){document.body.removeChild(frame);}, 100);
11558 Roo.EventManager.on(frame, 'load', cb, this);
11561 if(hiddens){ // remove dynamic params
11562 for(var i = 0, len = hiddens.length; i < len; i++){
11563 form.removeChild(hiddens[i]);
11570 * Ext JS Library 1.1.1
11571 * Copyright(c) 2006-2007, Ext JS, LLC.
11573 * Originally Released Under LGPL - original licence link has changed is not relivant.
11576 * <script type="text/javascript">
11580 * Global Ajax request class.
11583 * @extends Roo.data.Connection
11586 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11587 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11588 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11589 * @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)
11590 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11591 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11592 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11594 Roo.Ajax = new Roo.data.Connection({
11603 * Serialize the passed form into a url encoded string
11605 * @param {String/HTMLElement} form
11608 serializeForm : function(form){
11609 return Roo.lib.Ajax.serializeForm(form);
11613 * Ext JS Library 1.1.1
11614 * Copyright(c) 2006-2007, Ext JS, LLC.
11616 * Originally Released Under LGPL - original licence link has changed is not relivant.
11619 * <script type="text/javascript">
11624 * @class Roo.UpdateManager
11625 * @extends Roo.util.Observable
11626 * Provides AJAX-style update for Element object.<br><br>
11629 * // Get it from a Roo.Element object
11630 * var el = Roo.get("foo");
11631 * var mgr = el.getUpdateManager();
11632 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11634 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11636 * // or directly (returns the same UpdateManager instance)
11637 * var mgr = new Roo.UpdateManager("myElementId");
11638 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11639 * mgr.on("update", myFcnNeedsToKnow);
11641 // short handed call directly from the element object
11642 Roo.get("foo").load({
11646 text: "Loading Foo..."
11650 * Create new UpdateManager directly.
11651 * @param {String/HTMLElement/Roo.Element} el The element to update
11652 * @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).
11654 Roo.UpdateManager = function(el, forceNew){
11656 if(!forceNew && el.updateManager){
11657 return el.updateManager;
11660 * The Element object
11661 * @type Roo.Element
11665 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11668 this.defaultUrl = null;
11672 * @event beforeupdate
11673 * Fired before an update is made, return false from your handler and the update is cancelled.
11674 * @param {Roo.Element} el
11675 * @param {String/Object/Function} url
11676 * @param {String/Object} params
11678 "beforeupdate": true,
11681 * Fired after successful update is made.
11682 * @param {Roo.Element} el
11683 * @param {Object} oResponseObject The response Object
11688 * Fired on update failure.
11689 * @param {Roo.Element} el
11690 * @param {Object} oResponseObject The response Object
11694 var d = Roo.UpdateManager.defaults;
11696 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11699 this.sslBlankUrl = d.sslBlankUrl;
11701 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11704 this.disableCaching = d.disableCaching;
11706 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11709 this.indicatorText = d.indicatorText;
11711 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11714 this.showLoadIndicator = d.showLoadIndicator;
11716 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11719 this.timeout = d.timeout;
11722 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11725 this.loadScripts = d.loadScripts;
11728 * Transaction object of current executing transaction
11730 this.transaction = null;
11735 this.autoRefreshProcId = null;
11737 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11740 this.refreshDelegate = this.refresh.createDelegate(this);
11742 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11745 this.updateDelegate = this.update.createDelegate(this);
11747 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11750 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11754 this.successDelegate = this.processSuccess.createDelegate(this);
11758 this.failureDelegate = this.processFailure.createDelegate(this);
11760 if(!this.renderer){
11762 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11764 this.renderer = new Roo.UpdateManager.BasicRenderer();
11767 Roo.UpdateManager.superclass.constructor.call(this);
11770 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11772 * Get the Element this UpdateManager is bound to
11773 * @return {Roo.Element} The element
11775 getEl : function(){
11779 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11780 * @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:
11783 url: "your-url.php",<br/>
11784 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11785 callback: yourFunction,<br/>
11786 scope: yourObject, //(optional scope) <br/>
11787 discardUrl: false, <br/>
11788 nocache: false,<br/>
11789 text: "Loading...",<br/>
11791 scripts: false<br/>
11794 * The only required property is url. The optional properties nocache, text and scripts
11795 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11796 * @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}
11797 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11798 * @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.
11800 update : function(url, params, callback, discardUrl){
11801 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11802 var method = this.method,
11804 if(typeof url == "object"){ // must be config object
11807 params = params || cfg.params;
11808 callback = callback || cfg.callback;
11809 discardUrl = discardUrl || cfg.discardUrl;
11810 if(callback && cfg.scope){
11811 callback = callback.createDelegate(cfg.scope);
11813 if(typeof cfg.method != "undefined"){method = cfg.method;};
11814 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11815 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11816 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11817 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11819 this.showLoading();
11821 this.defaultUrl = url;
11823 if(typeof url == "function"){
11824 url = url.call(this);
11827 method = method || (params ? "POST" : "GET");
11828 if(method == "GET"){
11829 url = this.prepareUrl(url);
11832 var o = Roo.apply(cfg ||{}, {
11835 success: this.successDelegate,
11836 failure: this.failureDelegate,
11837 callback: undefined,
11838 timeout: (this.timeout*1000),
11839 argument: {"url": url, "form": null, "callback": callback, "params": params}
11841 Roo.log("updated manager called with timeout of " + o.timeout);
11842 this.transaction = Roo.Ajax.request(o);
11847 * 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.
11848 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11849 * @param {String/HTMLElement} form The form Id or form element
11850 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11851 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11852 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11854 formUpdate : function(form, url, reset, callback){
11855 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11856 if(typeof url == "function"){
11857 url = url.call(this);
11859 form = Roo.getDom(form);
11860 this.transaction = Roo.Ajax.request({
11863 success: this.successDelegate,
11864 failure: this.failureDelegate,
11865 timeout: (this.timeout*1000),
11866 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11868 this.showLoading.defer(1, this);
11873 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11874 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11876 refresh : function(callback){
11877 if(this.defaultUrl == null){
11880 this.update(this.defaultUrl, null, callback, true);
11884 * Set this element to auto refresh.
11885 * @param {Number} interval How often to update (in seconds).
11886 * @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)
11887 * @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}
11888 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11889 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11891 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11893 this.update(url || this.defaultUrl, params, callback, true);
11895 if(this.autoRefreshProcId){
11896 clearInterval(this.autoRefreshProcId);
11898 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11902 * Stop auto refresh on this element.
11904 stopAutoRefresh : function(){
11905 if(this.autoRefreshProcId){
11906 clearInterval(this.autoRefreshProcId);
11907 delete this.autoRefreshProcId;
11911 isAutoRefreshing : function(){
11912 return this.autoRefreshProcId ? true : false;
11915 * Called to update the element to "Loading" state. Override to perform custom action.
11917 showLoading : function(){
11918 if(this.showLoadIndicator){
11919 this.el.update(this.indicatorText);
11924 * Adds unique parameter to query string if disableCaching = true
11927 prepareUrl : function(url){
11928 if(this.disableCaching){
11929 var append = "_dc=" + (new Date().getTime());
11930 if(url.indexOf("?") !== -1){
11931 url += "&" + append;
11933 url += "?" + append;
11942 processSuccess : function(response){
11943 this.transaction = null;
11944 if(response.argument.form && response.argument.reset){
11945 try{ // put in try/catch since some older FF releases had problems with this
11946 response.argument.form.reset();
11949 if(this.loadScripts){
11950 this.renderer.render(this.el, response, this,
11951 this.updateComplete.createDelegate(this, [response]));
11953 this.renderer.render(this.el, response, this);
11954 this.updateComplete(response);
11958 updateComplete : function(response){
11959 this.fireEvent("update", this.el, response);
11960 if(typeof response.argument.callback == "function"){
11961 response.argument.callback(this.el, true, response);
11968 processFailure : function(response){
11969 this.transaction = null;
11970 this.fireEvent("failure", this.el, response);
11971 if(typeof response.argument.callback == "function"){
11972 response.argument.callback(this.el, false, response);
11977 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11978 * @param {Object} renderer The object implementing the render() method
11980 setRenderer : function(renderer){
11981 this.renderer = renderer;
11984 getRenderer : function(){
11985 return this.renderer;
11989 * Set the defaultUrl used for updates
11990 * @param {String/Function} defaultUrl The url or a function to call to get the url
11992 setDefaultUrl : function(defaultUrl){
11993 this.defaultUrl = defaultUrl;
11997 * Aborts the executing transaction
11999 abort : function(){
12000 if(this.transaction){
12001 Roo.Ajax.abort(this.transaction);
12006 * Returns true if an update is in progress
12007 * @return {Boolean}
12009 isUpdating : function(){
12010 if(this.transaction){
12011 return Roo.Ajax.isLoading(this.transaction);
12018 * @class Roo.UpdateManager.defaults
12019 * @static (not really - but it helps the doc tool)
12020 * The defaults collection enables customizing the default properties of UpdateManager
12022 Roo.UpdateManager.defaults = {
12024 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12030 * True to process scripts by default (Defaults to false).
12033 loadScripts : false,
12036 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12039 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12041 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12044 disableCaching : false,
12046 * Whether to show indicatorText when loading (Defaults to true).
12049 showLoadIndicator : true,
12051 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12054 indicatorText : '<div class="loading-indicator">Loading...</div>'
12058 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12060 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12061 * @param {String/HTMLElement/Roo.Element} el The element to update
12062 * @param {String} url The url
12063 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12064 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12067 * @member Roo.UpdateManager
12069 Roo.UpdateManager.updateElement = function(el, url, params, options){
12070 var um = Roo.get(el, true).getUpdateManager();
12071 Roo.apply(um, options);
12072 um.update(url, params, options ? options.callback : null);
12074 // alias for backwards compat
12075 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12077 * @class Roo.UpdateManager.BasicRenderer
12078 * Default Content renderer. Updates the elements innerHTML with the responseText.
12080 Roo.UpdateManager.BasicRenderer = function(){};
12082 Roo.UpdateManager.BasicRenderer.prototype = {
12084 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12085 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12086 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12087 * @param {Roo.Element} el The element being rendered
12088 * @param {Object} response The YUI Connect response object
12089 * @param {UpdateManager} updateManager The calling update manager
12090 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12092 render : function(el, response, updateManager, callback){
12093 el.update(response.responseText, updateManager.loadScripts, callback);
12099 * (c)) Alan Knowles
12105 * @class Roo.DomTemplate
12106 * @extends Roo.Template
12107 * An effort at a dom based template engine..
12109 * Similar to XTemplate, except it uses dom parsing to create the template..
12111 * Supported features:
12116 {a_variable} - output encoded.
12117 {a_variable.format:("Y-m-d")} - call a method on the variable
12118 {a_variable:raw} - unencoded output
12119 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12120 {a_variable:this.method_on_template(...)} - call a method on the template object.
12125 <div roo-for="a_variable or condition.."></div>
12126 <div roo-if="a_variable or condition"></div>
12127 <div roo-exec="some javascript"></div>
12128 <div roo-name="named_template"></div>
12133 Roo.DomTemplate = function()
12135 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12142 Roo.extend(Roo.DomTemplate, Roo.Template, {
12144 * id counter for sub templates.
12148 * flag to indicate if dom parser is inside a pre,
12149 * it will strip whitespace if not.
12154 * The various sub templates
12162 * basic tag replacing syntax
12165 * // you can fake an object call by doing this
12169 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12170 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12172 iterChild : function (node, method) {
12174 var oldPre = this.inPre;
12175 if (node.tagName == 'PRE') {
12178 for( var i = 0; i < node.childNodes.length; i++) {
12179 method.call(this, node.childNodes[i]);
12181 this.inPre = oldPre;
12187 * compile the template
12189 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12192 compile: function()
12196 // covert the html into DOM...
12200 doc = document.implementation.createHTMLDocument("");
12201 doc.documentElement.innerHTML = this.html ;
12202 div = doc.documentElement;
12204 // old IE... - nasty -- it causes all sorts of issues.. with
12205 // images getting pulled from server..
12206 div = document.createElement('div');
12207 div.innerHTML = this.html;
12209 //doc.documentElement.innerHTML = htmlBody
12215 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12217 var tpls = this.tpls;
12219 // create a top level template from the snippet..
12221 //Roo.log(div.innerHTML);
12228 body : div.innerHTML,
12241 Roo.each(tpls, function(tp){
12242 this.compileTpl(tp);
12243 this.tpls[tp.id] = tp;
12246 this.master = tpls[0];
12252 compileNode : function(node, istop) {
12257 // skip anything not a tag..
12258 if (node.nodeType != 1) {
12259 if (node.nodeType == 3 && !this.inPre) {
12260 // reduce white space..
12261 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12284 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12285 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12286 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12287 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12293 // just itterate children..
12294 this.iterChild(node,this.compileNode);
12297 tpl.uid = this.id++;
12298 tpl.value = node.getAttribute('roo-' + tpl.attr);
12299 node.removeAttribute('roo-'+ tpl.attr);
12300 if (tpl.attr != 'name') {
12301 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12302 node.parentNode.replaceChild(placeholder, node);
12305 var placeholder = document.createElement('span');
12306 placeholder.className = 'roo-tpl-' + tpl.value;
12307 node.parentNode.replaceChild(placeholder, node);
12310 // parent now sees '{domtplXXXX}
12311 this.iterChild(node,this.compileNode);
12313 // we should now have node body...
12314 var div = document.createElement('div');
12315 div.appendChild(node);
12317 // this has the unfortunate side effect of converting tagged attributes
12318 // eg. href="{...}" into %7C...%7D
12319 // this has been fixed by searching for those combo's although it's a bit hacky..
12322 tpl.body = div.innerHTML;
12329 switch (tpl.value) {
12330 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12331 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12332 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12337 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12341 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12345 tpl.id = tpl.value; // replace non characters???
12351 this.tpls.push(tpl);
12361 * Compile a segment of the template into a 'sub-template'
12367 compileTpl : function(tpl)
12369 var fm = Roo.util.Format;
12370 var useF = this.disableFormats !== true;
12372 var sep = Roo.isGecko ? "+\n" : ",\n";
12374 var undef = function(str) {
12375 Roo.debug && Roo.log("Property not found :" + str);
12379 //Roo.log(tpl.body);
12383 var fn = function(m, lbrace, name, format, args)
12386 //Roo.log(arguments);
12387 args = args ? args.replace(/\\'/g,"'") : args;
12388 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12389 if (typeof(format) == 'undefined') {
12390 format = 'htmlEncode';
12392 if (format == 'raw' ) {
12396 if(name.substr(0, 6) == 'domtpl'){
12397 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12400 // build an array of options to determine if value is undefined..
12402 // basically get 'xxxx.yyyy' then do
12403 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12404 // (function () { Roo.log("Property not found"); return ''; })() :
12409 Roo.each(name.split('.'), function(st) {
12410 lookfor += (lookfor.length ? '.': '') + st;
12411 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12414 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12417 if(format && useF){
12419 args = args ? ',' + args : "";
12421 if(format.substr(0, 5) != "this."){
12422 format = "fm." + format + '(';
12424 format = 'this.call("'+ format.substr(5) + '", ';
12428 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12431 if (args && args.length) {
12432 // called with xxyx.yuu:(test,test)
12434 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12436 // raw.. - :raw modifier..
12437 return "'"+ sep + udef_st + name + ")"+sep+"'";
12441 // branched to use + in gecko and [].join() in others
12443 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12444 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12447 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12448 body.push(tpl.body.replace(/(\r\n|\n)/g,
12449 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12450 body.push("'].join('');};};");
12451 body = body.join('');
12454 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12456 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12463 * same as applyTemplate, except it's done to one of the subTemplates
12464 * when using named templates, you can do:
12466 * var str = pl.applySubTemplate('your-name', values);
12469 * @param {Number} id of the template
12470 * @param {Object} values to apply to template
12471 * @param {Object} parent (normaly the instance of this object)
12473 applySubTemplate : function(id, values, parent)
12477 var t = this.tpls[id];
12481 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12482 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12486 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12493 if(t.execCall && t.execCall.call(this, values, parent)){
12497 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12503 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12504 parent = t.target ? values : parent;
12505 if(t.forCall && vs instanceof Array){
12507 for(var i = 0, len = vs.length; i < len; i++){
12509 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12511 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12513 //Roo.log(t.compiled);
12517 return buf.join('');
12520 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12525 return t.compiled.call(this, vs, parent);
12527 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12529 //Roo.log(t.compiled);
12537 applyTemplate : function(values){
12538 return this.master.compiled.call(this, values, {});
12539 //var s = this.subs;
12542 apply : function(){
12543 return this.applyTemplate.apply(this, arguments);
12548 Roo.DomTemplate.from = function(el){
12549 el = Roo.getDom(el);
12550 return new Roo.Domtemplate(el.value || el.innerHTML);
12553 * Ext JS Library 1.1.1
12554 * Copyright(c) 2006-2007, Ext JS, LLC.
12556 * Originally Released Under LGPL - original licence link has changed is not relivant.
12559 * <script type="text/javascript">
12563 * @class Roo.util.DelayedTask
12564 * Provides a convenient method of performing setTimeout where a new
12565 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12566 * You can use this class to buffer
12567 * the keypress events for a certain number of milliseconds, and perform only if they stop
12568 * for that amount of time.
12569 * @constructor The parameters to this constructor serve as defaults and are not required.
12570 * @param {Function} fn (optional) The default function to timeout
12571 * @param {Object} scope (optional) The default scope of that timeout
12572 * @param {Array} args (optional) The default Array of arguments
12574 Roo.util.DelayedTask = function(fn, scope, args){
12575 var id = null, d, t;
12577 var call = function(){
12578 var now = new Date().getTime();
12582 fn.apply(scope, args || []);
12586 * Cancels any pending timeout and queues a new one
12587 * @param {Number} delay The milliseconds to delay
12588 * @param {Function} newFn (optional) Overrides function passed to constructor
12589 * @param {Object} newScope (optional) Overrides scope passed to constructor
12590 * @param {Array} newArgs (optional) Overrides args passed to constructor
12592 this.delay = function(delay, newFn, newScope, newArgs){
12593 if(id && delay != d){
12597 t = new Date().getTime();
12599 scope = newScope || scope;
12600 args = newArgs || args;
12602 id = setInterval(call, d);
12607 * Cancel the last queued timeout
12609 this.cancel = function(){
12617 * Ext JS Library 1.1.1
12618 * Copyright(c) 2006-2007, Ext JS, LLC.
12620 * Originally Released Under LGPL - original licence link has changed is not relivant.
12623 * <script type="text/javascript">
12627 Roo.util.TaskRunner = function(interval){
12628 interval = interval || 10;
12629 var tasks = [], removeQueue = [];
12631 var running = false;
12633 var stopThread = function(){
12639 var startThread = function(){
12642 id = setInterval(runTasks, interval);
12646 var removeTask = function(task){
12647 removeQueue.push(task);
12653 var runTasks = function(){
12654 if(removeQueue.length > 0){
12655 for(var i = 0, len = removeQueue.length; i < len; i++){
12656 tasks.remove(removeQueue[i]);
12659 if(tasks.length < 1){
12664 var now = new Date().getTime();
12665 for(var i = 0, len = tasks.length; i < len; ++i){
12667 var itime = now - t.taskRunTime;
12668 if(t.interval <= itime){
12669 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12670 t.taskRunTime = now;
12671 if(rt === false || t.taskRunCount === t.repeat){
12676 if(t.duration && t.duration <= (now - t.taskStartTime)){
12683 * Queues a new task.
12684 * @param {Object} task
12686 this.start = function(task){
12688 task.taskStartTime = new Date().getTime();
12689 task.taskRunTime = 0;
12690 task.taskRunCount = 0;
12695 this.stop = function(task){
12700 this.stopAll = function(){
12702 for(var i = 0, len = tasks.length; i < len; i++){
12703 if(tasks[i].onStop){
12712 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12714 * Ext JS Library 1.1.1
12715 * Copyright(c) 2006-2007, Ext JS, LLC.
12717 * Originally Released Under LGPL - original licence link has changed is not relivant.
12720 * <script type="text/javascript">
12725 * @class Roo.util.MixedCollection
12726 * @extends Roo.util.Observable
12727 * A Collection class that maintains both numeric indexes and keys and exposes events.
12729 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12730 * collection (defaults to false)
12731 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12732 * and return the key value for that item. This is used when available to look up the key on items that
12733 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12734 * equivalent to providing an implementation for the {@link #getKey} method.
12736 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12744 * Fires when the collection is cleared.
12749 * Fires when an item is added to the collection.
12750 * @param {Number} index The index at which the item was added.
12751 * @param {Object} o The item added.
12752 * @param {String} key The key associated with the added item.
12757 * Fires when an item is replaced in the collection.
12758 * @param {String} key he key associated with the new added.
12759 * @param {Object} old The item being replaced.
12760 * @param {Object} new The new item.
12765 * Fires when an item is removed from the collection.
12766 * @param {Object} o The item being removed.
12767 * @param {String} key (optional) The key associated with the removed item.
12772 this.allowFunctions = allowFunctions === true;
12774 this.getKey = keyFn;
12776 Roo.util.MixedCollection.superclass.constructor.call(this);
12779 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12780 allowFunctions : false,
12783 * Adds an item to the collection.
12784 * @param {String} key The key to associate with the item
12785 * @param {Object} o The item to add.
12786 * @return {Object} The item added.
12788 add : function(key, o){
12789 if(arguments.length == 1){
12791 key = this.getKey(o);
12793 if(typeof key == "undefined" || key === null){
12795 this.items.push(o);
12796 this.keys.push(null);
12798 var old = this.map[key];
12800 return this.replace(key, o);
12803 this.items.push(o);
12805 this.keys.push(key);
12807 this.fireEvent("add", this.length-1, o, key);
12812 * MixedCollection has a generic way to fetch keys if you implement getKey.
12815 var mc = new Roo.util.MixedCollection();
12816 mc.add(someEl.dom.id, someEl);
12817 mc.add(otherEl.dom.id, otherEl);
12821 var mc = new Roo.util.MixedCollection();
12822 mc.getKey = function(el){
12828 // or via the constructor
12829 var mc = new Roo.util.MixedCollection(false, function(el){
12835 * @param o {Object} The item for which to find the key.
12836 * @return {Object} The key for the passed item.
12838 getKey : function(o){
12843 * Replaces an item in the collection.
12844 * @param {String} key The key associated with the item to replace, or the item to replace.
12845 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12846 * @return {Object} The new item.
12848 replace : function(key, o){
12849 if(arguments.length == 1){
12851 key = this.getKey(o);
12853 var old = this.item(key);
12854 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12855 return this.add(key, o);
12857 var index = this.indexOfKey(key);
12858 this.items[index] = o;
12860 this.fireEvent("replace", key, old, o);
12865 * Adds all elements of an Array or an Object to the collection.
12866 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12867 * an Array of values, each of which are added to the collection.
12869 addAll : function(objs){
12870 if(arguments.length > 1 || objs instanceof Array){
12871 var args = arguments.length > 1 ? arguments : objs;
12872 for(var i = 0, len = args.length; i < len; i++){
12876 for(var key in objs){
12877 if(this.allowFunctions || typeof objs[key] != "function"){
12878 this.add(key, objs[key]);
12885 * Executes the specified function once for every item in the collection, passing each
12886 * item as the first and only parameter. returning false from the function will stop the iteration.
12887 * @param {Function} fn The function to execute for each item.
12888 * @param {Object} scope (optional) The scope in which to execute the function.
12890 each : function(fn, scope){
12891 var items = [].concat(this.items); // each safe for removal
12892 for(var i = 0, len = items.length; i < len; i++){
12893 if(fn.call(scope || items[i], items[i], i, len) === false){
12900 * Executes the specified function once for every key in the collection, passing each
12901 * key, and its associated item as the first two parameters.
12902 * @param {Function} fn The function to execute for each item.
12903 * @param {Object} scope (optional) The scope in which to execute the function.
12905 eachKey : function(fn, scope){
12906 for(var i = 0, len = this.keys.length; i < len; i++){
12907 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12912 * Returns the first item in the collection which elicits a true return value from the
12913 * passed selection function.
12914 * @param {Function} fn The selection function to execute for each item.
12915 * @param {Object} scope (optional) The scope in which to execute the function.
12916 * @return {Object} The first item in the collection which returned true from the selection function.
12918 find : function(fn, scope){
12919 for(var i = 0, len = this.items.length; i < len; i++){
12920 if(fn.call(scope || window, this.items[i], this.keys[i])){
12921 return this.items[i];
12928 * Inserts an item at the specified index in the collection.
12929 * @param {Number} index The index to insert the item at.
12930 * @param {String} key The key to associate with the new item, or the item itself.
12931 * @param {Object} o (optional) If the second parameter was a key, the new item.
12932 * @return {Object} The item inserted.
12934 insert : function(index, key, o){
12935 if(arguments.length == 2){
12937 key = this.getKey(o);
12939 if(index >= this.length){
12940 return this.add(key, o);
12943 this.items.splice(index, 0, o);
12944 if(typeof key != "undefined" && key != null){
12947 this.keys.splice(index, 0, key);
12948 this.fireEvent("add", index, o, key);
12953 * Removed an item from the collection.
12954 * @param {Object} o The item to remove.
12955 * @return {Object} The item removed.
12957 remove : function(o){
12958 return this.removeAt(this.indexOf(o));
12962 * Remove an item from a specified index in the collection.
12963 * @param {Number} index The index within the collection of the item to remove.
12965 removeAt : function(index){
12966 if(index < this.length && index >= 0){
12968 var o = this.items[index];
12969 this.items.splice(index, 1);
12970 var key = this.keys[index];
12971 if(typeof key != "undefined"){
12972 delete this.map[key];
12974 this.keys.splice(index, 1);
12975 this.fireEvent("remove", o, key);
12980 * Removed an item associated with the passed key fom the collection.
12981 * @param {String} key The key of the item to remove.
12983 removeKey : function(key){
12984 return this.removeAt(this.indexOfKey(key));
12988 * Returns the number of items in the collection.
12989 * @return {Number} the number of items in the collection.
12991 getCount : function(){
12992 return this.length;
12996 * Returns index within the collection of the passed Object.
12997 * @param {Object} o The item to find the index of.
12998 * @return {Number} index of the item.
13000 indexOf : function(o){
13001 if(!this.items.indexOf){
13002 for(var i = 0, len = this.items.length; i < len; i++){
13003 if(this.items[i] == o) return i;
13007 return this.items.indexOf(o);
13012 * Returns index within the collection of the passed key.
13013 * @param {String} key The key to find the index of.
13014 * @return {Number} index of the key.
13016 indexOfKey : function(key){
13017 if(!this.keys.indexOf){
13018 for(var i = 0, len = this.keys.length; i < len; i++){
13019 if(this.keys[i] == key) return i;
13023 return this.keys.indexOf(key);
13028 * Returns the item associated with the passed key OR index. Key has priority over index.
13029 * @param {String/Number} key The key or index of the item.
13030 * @return {Object} The item associated with the passed key.
13032 item : function(key){
13033 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13034 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13038 * Returns the item at the specified index.
13039 * @param {Number} index The index of the item.
13042 itemAt : function(index){
13043 return this.items[index];
13047 * Returns the item associated with the passed key.
13048 * @param {String/Number} key The key of the item.
13049 * @return {Object} The item associated with the passed key.
13051 key : function(key){
13052 return this.map[key];
13056 * Returns true if the collection contains the passed Object as an item.
13057 * @param {Object} o The Object to look for in the collection.
13058 * @return {Boolean} True if the collection contains the Object as an item.
13060 contains : function(o){
13061 return this.indexOf(o) != -1;
13065 * Returns true if the collection contains the passed Object as a key.
13066 * @param {String} key The key to look for in the collection.
13067 * @return {Boolean} True if the collection contains the Object as a key.
13069 containsKey : function(key){
13070 return typeof this.map[key] != "undefined";
13074 * Removes all items from the collection.
13076 clear : function(){
13081 this.fireEvent("clear");
13085 * Returns the first item in the collection.
13086 * @return {Object} the first item in the collection..
13088 first : function(){
13089 return this.items[0];
13093 * Returns the last item in the collection.
13094 * @return {Object} the last item in the collection..
13097 return this.items[this.length-1];
13100 _sort : function(property, dir, fn){
13101 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13102 fn = fn || function(a, b){
13105 var c = [], k = this.keys, items = this.items;
13106 for(var i = 0, len = items.length; i < len; i++){
13107 c[c.length] = {key: k[i], value: items[i], index: i};
13109 c.sort(function(a, b){
13110 var v = fn(a[property], b[property]) * dsc;
13112 v = (a.index < b.index ? -1 : 1);
13116 for(var i = 0, len = c.length; i < len; i++){
13117 items[i] = c[i].value;
13120 this.fireEvent("sort", this);
13124 * Sorts this collection with the passed comparison function
13125 * @param {String} direction (optional) "ASC" or "DESC"
13126 * @param {Function} fn (optional) comparison function
13128 sort : function(dir, fn){
13129 this._sort("value", dir, fn);
13133 * Sorts this collection by keys
13134 * @param {String} direction (optional) "ASC" or "DESC"
13135 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13137 keySort : function(dir, fn){
13138 this._sort("key", dir, fn || function(a, b){
13139 return String(a).toUpperCase()-String(b).toUpperCase();
13144 * Returns a range of items in this collection
13145 * @param {Number} startIndex (optional) defaults to 0
13146 * @param {Number} endIndex (optional) default to the last item
13147 * @return {Array} An array of items
13149 getRange : function(start, end){
13150 var items = this.items;
13151 if(items.length < 1){
13154 start = start || 0;
13155 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13158 for(var i = start; i <= end; i++) {
13159 r[r.length] = items[i];
13162 for(var i = start; i >= end; i--) {
13163 r[r.length] = items[i];
13170 * Filter the <i>objects</i> in this collection by a specific property.
13171 * Returns a new collection that has been filtered.
13172 * @param {String} property A property on your objects
13173 * @param {String/RegExp} value Either string that the property values
13174 * should start with or a RegExp to test against the property
13175 * @return {MixedCollection} The new filtered collection
13177 filter : function(property, value){
13178 if(!value.exec){ // not a regex
13179 value = String(value);
13180 if(value.length == 0){
13181 return this.clone();
13183 value = new RegExp("^" + Roo.escapeRe(value), "i");
13185 return this.filterBy(function(o){
13186 return o && value.test(o[property]);
13191 * Filter by a function. * Returns a new collection that has been filtered.
13192 * The passed function will be called with each
13193 * object in the collection. If the function returns true, the value is included
13194 * otherwise it is filtered.
13195 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13196 * @param {Object} scope (optional) The scope of the function (defaults to this)
13197 * @return {MixedCollection} The new filtered collection
13199 filterBy : function(fn, scope){
13200 var r = new Roo.util.MixedCollection();
13201 r.getKey = this.getKey;
13202 var k = this.keys, it = this.items;
13203 for(var i = 0, len = it.length; i < len; i++){
13204 if(fn.call(scope||this, it[i], k[i])){
13205 r.add(k[i], it[i]);
13212 * Creates a duplicate of this collection
13213 * @return {MixedCollection}
13215 clone : function(){
13216 var r = new Roo.util.MixedCollection();
13217 var k = this.keys, it = this.items;
13218 for(var i = 0, len = it.length; i < len; i++){
13219 r.add(k[i], it[i]);
13221 r.getKey = this.getKey;
13226 * Returns the item associated with the passed key or index.
13228 * @param {String/Number} key The key or index of the item.
13229 * @return {Object} The item associated with the passed key.
13231 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13233 * Ext JS Library 1.1.1
13234 * Copyright(c) 2006-2007, Ext JS, LLC.
13236 * Originally Released Under LGPL - original licence link has changed is not relivant.
13239 * <script type="text/javascript">
13242 * @class Roo.util.JSON
13243 * Modified version of Douglas Crockford"s json.js that doesn"t
13244 * mess with the Object prototype
13245 * http://www.json.org/js.html
13248 Roo.util.JSON = new (function(){
13249 var useHasOwn = {}.hasOwnProperty ? true : false;
13251 // crashes Safari in some instances
13252 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13254 var pad = function(n) {
13255 return n < 10 ? "0" + n : n;
13268 var encodeString = function(s){
13269 if (/["\\\x00-\x1f]/.test(s)) {
13270 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13275 c = b.charCodeAt();
13277 Math.floor(c / 16).toString(16) +
13278 (c % 16).toString(16);
13281 return '"' + s + '"';
13284 var encodeArray = function(o){
13285 var a = ["["], b, i, l = o.length, v;
13286 for (i = 0; i < l; i += 1) {
13288 switch (typeof v) {
13297 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13305 var encodeDate = function(o){
13306 return '"' + o.getFullYear() + "-" +
13307 pad(o.getMonth() + 1) + "-" +
13308 pad(o.getDate()) + "T" +
13309 pad(o.getHours()) + ":" +
13310 pad(o.getMinutes()) + ":" +
13311 pad(o.getSeconds()) + '"';
13315 * Encodes an Object, Array or other value
13316 * @param {Mixed} o The variable to encode
13317 * @return {String} The JSON string
13319 this.encode = function(o)
13321 // should this be extended to fully wrap stringify..
13323 if(typeof o == "undefined" || o === null){
13325 }else if(o instanceof Array){
13326 return encodeArray(o);
13327 }else if(o instanceof Date){
13328 return encodeDate(o);
13329 }else if(typeof o == "string"){
13330 return encodeString(o);
13331 }else if(typeof o == "number"){
13332 return isFinite(o) ? String(o) : "null";
13333 }else if(typeof o == "boolean"){
13336 var a = ["{"], b, i, v;
13338 if(!useHasOwn || o.hasOwnProperty(i)) {
13340 switch (typeof v) {
13349 a.push(this.encode(i), ":",
13350 v === null ? "null" : this.encode(v));
13361 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13362 * @param {String} json The JSON string
13363 * @return {Object} The resulting object
13365 this.decode = function(json){
13367 return /** eval:var:json */ eval("(" + json + ')');
13371 * Shorthand for {@link Roo.util.JSON#encode}
13372 * @member Roo encode
13374 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13376 * Shorthand for {@link Roo.util.JSON#decode}
13377 * @member Roo decode
13379 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13382 * Ext JS Library 1.1.1
13383 * Copyright(c) 2006-2007, Ext JS, LLC.
13385 * Originally Released Under LGPL - original licence link has changed is not relivant.
13388 * <script type="text/javascript">
13392 * @class Roo.util.Format
13393 * Reusable data formatting functions
13396 Roo.util.Format = function(){
13397 var trimRe = /^\s+|\s+$/g;
13400 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13401 * @param {String} value The string to truncate
13402 * @param {Number} length The maximum length to allow before truncating
13403 * @return {String} The converted text
13405 ellipsis : function(value, len){
13406 if(value && value.length > len){
13407 return value.substr(0, len-3)+"...";
13413 * Checks a reference and converts it to empty string if it is undefined
13414 * @param {Mixed} value Reference to check
13415 * @return {Mixed} Empty string if converted, otherwise the original value
13417 undef : function(value){
13418 return typeof value != "undefined" ? value : "";
13422 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13423 * @param {String} value The string to encode
13424 * @return {String} The encoded text
13426 htmlEncode : function(value){
13427 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13431 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13432 * @param {String} value The string to decode
13433 * @return {String} The decoded text
13435 htmlDecode : function(value){
13436 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13440 * Trims any whitespace from either side of a string
13441 * @param {String} value The text to trim
13442 * @return {String} The trimmed text
13444 trim : function(value){
13445 return String(value).replace(trimRe, "");
13449 * Returns a substring from within an original string
13450 * @param {String} value The original text
13451 * @param {Number} start The start index of the substring
13452 * @param {Number} length The length of the substring
13453 * @return {String} The substring
13455 substr : function(value, start, length){
13456 return String(value).substr(start, length);
13460 * Converts a string to all lower case letters
13461 * @param {String} value The text to convert
13462 * @return {String} The converted text
13464 lowercase : function(value){
13465 return String(value).toLowerCase();
13469 * Converts a string to all upper case letters
13470 * @param {String} value The text to convert
13471 * @return {String} The converted text
13473 uppercase : function(value){
13474 return String(value).toUpperCase();
13478 * Converts the first character only of a string to upper case
13479 * @param {String} value The text to convert
13480 * @return {String} The converted text
13482 capitalize : function(value){
13483 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13487 call : function(value, fn){
13488 if(arguments.length > 2){
13489 var args = Array.prototype.slice.call(arguments, 2);
13490 args.unshift(value);
13492 return /** eval:var:value */ eval(fn).apply(window, args);
13494 /** eval:var:value */
13495 return /** eval:var:value */ eval(fn).call(window, value);
13501 * safer version of Math.toFixed..??/
13502 * @param {Number/String} value The numeric value to format
13503 * @param {Number/String} value Decimal places
13504 * @return {String} The formatted currency string
13506 toFixed : function(v, n)
13508 // why not use to fixed - precision is buggered???
13510 return Math.round(v-0);
13512 var fact = Math.pow(10,n+1);
13513 v = (Math.round((v-0)*fact))/fact;
13514 var z = (''+fact).substring(2);
13515 if (v == Math.floor(v)) {
13516 return Math.floor(v) + '.' + z;
13519 // now just padd decimals..
13520 var ps = String(v).split('.');
13521 var fd = (ps[1] + z);
13522 var r = fd.substring(0,n);
13523 var rm = fd.substring(n);
13525 return ps[0] + '.' + r;
13527 r*=1; // turn it into a number;
13529 if (String(r).length != n) {
13532 r = String(r).substring(1); // chop the end off.
13535 return ps[0] + '.' + r;
13540 * Format a number as US currency
13541 * @param {Number/String} value The numeric value to format
13542 * @return {String} The formatted currency string
13544 usMoney : function(v){
13545 return '$' + Roo.util.Format.number(v);
13550 * eventually this should probably emulate php's number_format
13551 * @param {Number/String} value The numeric value to format
13552 * @param {Number} decimals number of decimal places
13553 * @return {String} The formatted currency string
13555 number : function(v,decimals)
13557 // multiply and round.
13558 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13559 var mul = Math.pow(10, decimals);
13560 var zero = String(mul).substring(1);
13561 v = (Math.round((v-0)*mul))/mul;
13563 // if it's '0' number.. then
13565 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13567 var ps = v.split('.');
13571 var r = /(\d+)(\d{3})/;
13573 while (r.test(whole)) {
13574 whole = whole.replace(r, '$1' + ',' + '$2');
13580 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13581 // does not have decimals
13582 (decimals ? ('.' + zero) : '');
13585 return whole + sub ;
13589 * Parse a value into a formatted date using the specified format pattern.
13590 * @param {Mixed} value The value to format
13591 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13592 * @return {String} The formatted date string
13594 date : function(v, format){
13598 if(!(v instanceof Date)){
13599 v = new Date(Date.parse(v));
13601 return v.dateFormat(format || "m/d/Y");
13605 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13606 * @param {String} format Any valid date format string
13607 * @return {Function} The date formatting function
13609 dateRenderer : function(format){
13610 return function(v){
13611 return Roo.util.Format.date(v, format);
13616 stripTagsRE : /<\/?[^>]+>/gi,
13619 * Strips all HTML tags
13620 * @param {Mixed} value The text from which to strip tags
13621 * @return {String} The stripped text
13623 stripTags : function(v){
13624 return !v ? v : String(v).replace(this.stripTagsRE, "");
13629 * Ext JS Library 1.1.1
13630 * Copyright(c) 2006-2007, Ext JS, LLC.
13632 * Originally Released Under LGPL - original licence link has changed is not relivant.
13635 * <script type="text/javascript">
13642 * @class Roo.MasterTemplate
13643 * @extends Roo.Template
13644 * Provides a template that can have child templates. The syntax is:
13646 var t = new Roo.MasterTemplate(
13647 '<select name="{name}">',
13648 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13651 t.add('options', {value: 'foo', text: 'bar'});
13652 // or you can add multiple child elements in one shot
13653 t.addAll('options', [
13654 {value: 'foo', text: 'bar'},
13655 {value: 'foo2', text: 'bar2'},
13656 {value: 'foo3', text: 'bar3'}
13658 // then append, applying the master template values
13659 t.append('my-form', {name: 'my-select'});
13661 * A name attribute for the child template is not required if you have only one child
13662 * template or you want to refer to them by index.
13664 Roo.MasterTemplate = function(){
13665 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13666 this.originalHtml = this.html;
13668 var m, re = this.subTemplateRe;
13671 while(m = re.exec(this.html)){
13672 var name = m[1], content = m[2];
13677 tpl : new Roo.Template(content)
13680 st[name] = st[subIndex];
13682 st[subIndex].tpl.compile();
13683 st[subIndex].tpl.call = this.call.createDelegate(this);
13686 this.subCount = subIndex;
13689 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13691 * The regular expression used to match sub templates
13695 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13698 * Applies the passed values to a child template.
13699 * @param {String/Number} name (optional) The name or index of the child template
13700 * @param {Array/Object} values The values to be applied to the template
13701 * @return {MasterTemplate} this
13703 add : function(name, values){
13704 if(arguments.length == 1){
13705 values = arguments[0];
13708 var s = this.subs[name];
13709 s.buffer[s.buffer.length] = s.tpl.apply(values);
13714 * Applies all the passed values to a child template.
13715 * @param {String/Number} name (optional) The name or index of the child template
13716 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13717 * @param {Boolean} reset (optional) True to reset the template first
13718 * @return {MasterTemplate} this
13720 fill : function(name, values, reset){
13722 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13730 for(var i = 0, len = values.length; i < len; i++){
13731 this.add(name, values[i]);
13737 * Resets the template for reuse
13738 * @return {MasterTemplate} this
13740 reset : function(){
13742 for(var i = 0; i < this.subCount; i++){
13748 applyTemplate : function(values){
13750 var replaceIndex = -1;
13751 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13752 return s[++replaceIndex].buffer.join("");
13754 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13757 apply : function(){
13758 return this.applyTemplate.apply(this, arguments);
13761 compile : function(){return this;}
13765 * Alias for fill().
13768 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13770 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13771 * var tpl = Roo.MasterTemplate.from('element-id');
13772 * @param {String/HTMLElement} el
13773 * @param {Object} config
13776 Roo.MasterTemplate.from = function(el, config){
13777 el = Roo.getDom(el);
13778 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13781 * Ext JS Library 1.1.1
13782 * Copyright(c) 2006-2007, Ext JS, LLC.
13784 * Originally Released Under LGPL - original licence link has changed is not relivant.
13787 * <script type="text/javascript">
13792 * @class Roo.util.CSS
13793 * Utility class for manipulating CSS rules
13796 Roo.util.CSS = function(){
13798 var doc = document;
13800 var camelRe = /(-[a-z])/gi;
13801 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13805 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13806 * tag and appended to the HEAD of the document.
13807 * @param {String|Object} cssText The text containing the css rules
13808 * @param {String} id An id to add to the stylesheet for later removal
13809 * @return {StyleSheet}
13811 createStyleSheet : function(cssText, id){
13813 var head = doc.getElementsByTagName("head")[0];
13814 var nrules = doc.createElement("style");
13815 nrules.setAttribute("type", "text/css");
13817 nrules.setAttribute("id", id);
13819 if (typeof(cssText) != 'string') {
13820 // support object maps..
13821 // not sure if this a good idea..
13822 // perhaps it should be merged with the general css handling
13823 // and handle js style props.
13824 var cssTextNew = [];
13825 for(var n in cssText) {
13827 for(var k in cssText[n]) {
13828 citems.push( k + ' : ' +cssText[n][k] + ';' );
13830 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13833 cssText = cssTextNew.join("\n");
13839 head.appendChild(nrules);
13840 ss = nrules.styleSheet;
13841 ss.cssText = cssText;
13844 nrules.appendChild(doc.createTextNode(cssText));
13846 nrules.cssText = cssText;
13848 head.appendChild(nrules);
13849 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13851 this.cacheStyleSheet(ss);
13856 * Removes a style or link tag by id
13857 * @param {String} id The id of the tag
13859 removeStyleSheet : function(id){
13860 var existing = doc.getElementById(id);
13862 existing.parentNode.removeChild(existing);
13867 * Dynamically swaps an existing stylesheet reference for a new one
13868 * @param {String} id The id of an existing link tag to remove
13869 * @param {String} url The href of the new stylesheet to include
13871 swapStyleSheet : function(id, url){
13872 this.removeStyleSheet(id);
13873 var ss = doc.createElement("link");
13874 ss.setAttribute("rel", "stylesheet");
13875 ss.setAttribute("type", "text/css");
13876 ss.setAttribute("id", id);
13877 ss.setAttribute("href", url);
13878 doc.getElementsByTagName("head")[0].appendChild(ss);
13882 * Refresh the rule cache if you have dynamically added stylesheets
13883 * @return {Object} An object (hash) of rules indexed by selector
13885 refreshCache : function(){
13886 return this.getRules(true);
13890 cacheStyleSheet : function(stylesheet){
13894 try{// try catch for cross domain access issue
13895 var ssRules = stylesheet.cssRules || stylesheet.rules;
13896 for(var j = ssRules.length-1; j >= 0; --j){
13897 rules[ssRules[j].selectorText] = ssRules[j];
13903 * Gets all css rules for the document
13904 * @param {Boolean} refreshCache true to refresh the internal cache
13905 * @return {Object} An object (hash) of rules indexed by selector
13907 getRules : function(refreshCache){
13908 if(rules == null || refreshCache){
13910 var ds = doc.styleSheets;
13911 for(var i =0, len = ds.length; i < len; i++){
13913 this.cacheStyleSheet(ds[i]);
13921 * Gets an an individual CSS rule by selector(s)
13922 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13923 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13924 * @return {CSSRule} The CSS rule or null if one is not found
13926 getRule : function(selector, refreshCache){
13927 var rs = this.getRules(refreshCache);
13928 if(!(selector instanceof Array)){
13929 return rs[selector];
13931 for(var i = 0; i < selector.length; i++){
13932 if(rs[selector[i]]){
13933 return rs[selector[i]];
13941 * Updates a rule property
13942 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13943 * @param {String} property The css property
13944 * @param {String} value The new value for the property
13945 * @return {Boolean} true If a rule was found and updated
13947 updateRule : function(selector, property, value){
13948 if(!(selector instanceof Array)){
13949 var rule = this.getRule(selector);
13951 rule.style[property.replace(camelRe, camelFn)] = value;
13955 for(var i = 0; i < selector.length; i++){
13956 if(this.updateRule(selector[i], property, value)){
13966 * Ext JS Library 1.1.1
13967 * Copyright(c) 2006-2007, Ext JS, LLC.
13969 * Originally Released Under LGPL - original licence link has changed is not relivant.
13972 * <script type="text/javascript">
13978 * @class Roo.util.ClickRepeater
13979 * @extends Roo.util.Observable
13981 * A wrapper class which can be applied to any element. Fires a "click" event while the
13982 * mouse is pressed. The interval between firings may be specified in the config but
13983 * defaults to 10 milliseconds.
13985 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13987 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13988 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13989 * Similar to an autorepeat key delay.
13990 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13991 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13992 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13993 * "interval" and "delay" are ignored. "immediate" is honored.
13994 * @cfg {Boolean} preventDefault True to prevent the default click event
13995 * @cfg {Boolean} stopDefault True to stop the default click event
13998 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13999 * 2007-02-02 jvs Renamed to ClickRepeater
14000 * 2007-02-03 jvs Modifications for FF Mac and Safari
14003 * @param {String/HTMLElement/Element} el The element to listen on
14004 * @param {Object} config
14006 Roo.util.ClickRepeater = function(el, config)
14008 this.el = Roo.get(el);
14009 this.el.unselectable();
14011 Roo.apply(this, config);
14016 * Fires when the mouse button is depressed.
14017 * @param {Roo.util.ClickRepeater} this
14019 "mousedown" : true,
14022 * Fires on a specified interval during the time the element is pressed.
14023 * @param {Roo.util.ClickRepeater} this
14028 * Fires when the mouse key is released.
14029 * @param {Roo.util.ClickRepeater} this
14034 this.el.on("mousedown", this.handleMouseDown, this);
14035 if(this.preventDefault || this.stopDefault){
14036 this.el.on("click", function(e){
14037 if(this.preventDefault){
14038 e.preventDefault();
14040 if(this.stopDefault){
14046 // allow inline handler
14048 this.on("click", this.handler, this.scope || this);
14051 Roo.util.ClickRepeater.superclass.constructor.call(this);
14054 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14057 preventDefault : true,
14058 stopDefault : false,
14062 handleMouseDown : function(){
14063 clearTimeout(this.timer);
14065 if(this.pressClass){
14066 this.el.addClass(this.pressClass);
14068 this.mousedownTime = new Date();
14070 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14071 this.el.on("mouseout", this.handleMouseOut, this);
14073 this.fireEvent("mousedown", this);
14074 this.fireEvent("click", this);
14076 this.timer = this.click.defer(this.delay || this.interval, this);
14080 click : function(){
14081 this.fireEvent("click", this);
14082 this.timer = this.click.defer(this.getInterval(), this);
14086 getInterval: function(){
14087 if(!this.accelerate){
14088 return this.interval;
14090 var pressTime = this.mousedownTime.getElapsed();
14091 if(pressTime < 500){
14093 }else if(pressTime < 1700){
14095 }else if(pressTime < 2600){
14097 }else if(pressTime < 3500){
14099 }else if(pressTime < 4400){
14101 }else if(pressTime < 5300){
14103 }else if(pressTime < 6200){
14111 handleMouseOut : function(){
14112 clearTimeout(this.timer);
14113 if(this.pressClass){
14114 this.el.removeClass(this.pressClass);
14116 this.el.on("mouseover", this.handleMouseReturn, this);
14120 handleMouseReturn : function(){
14121 this.el.un("mouseover", this.handleMouseReturn);
14122 if(this.pressClass){
14123 this.el.addClass(this.pressClass);
14129 handleMouseUp : function(){
14130 clearTimeout(this.timer);
14131 this.el.un("mouseover", this.handleMouseReturn);
14132 this.el.un("mouseout", this.handleMouseOut);
14133 Roo.get(document).un("mouseup", this.handleMouseUp);
14134 this.el.removeClass(this.pressClass);
14135 this.fireEvent("mouseup", this);
14139 * Ext JS Library 1.1.1
14140 * Copyright(c) 2006-2007, Ext JS, LLC.
14142 * Originally Released Under LGPL - original licence link has changed is not relivant.
14145 * <script type="text/javascript">
14150 * @class Roo.KeyNav
14151 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14152 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14153 * way to implement custom navigation schemes for any UI component.</p>
14154 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14155 * pageUp, pageDown, del, home, end. Usage:</p>
14157 var nav = new Roo.KeyNav("my-element", {
14158 "left" : function(e){
14159 this.moveLeft(e.ctrlKey);
14161 "right" : function(e){
14162 this.moveRight(e.ctrlKey);
14164 "enter" : function(e){
14171 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14172 * @param {Object} config The config
14174 Roo.KeyNav = function(el, config){
14175 this.el = Roo.get(el);
14176 Roo.apply(this, config);
14177 if(!this.disabled){
14178 this.disabled = true;
14183 Roo.KeyNav.prototype = {
14185 * @cfg {Boolean} disabled
14186 * True to disable this KeyNav instance (defaults to false)
14190 * @cfg {String} defaultEventAction
14191 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14192 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14193 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14195 defaultEventAction: "stopEvent",
14197 * @cfg {Boolean} forceKeyDown
14198 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14199 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14200 * handle keydown instead of keypress.
14202 forceKeyDown : false,
14205 prepareEvent : function(e){
14206 var k = e.getKey();
14207 var h = this.keyToHandler[k];
14208 //if(h && this[h]){
14209 // e.stopPropagation();
14211 if(Roo.isSafari && h && k >= 37 && k <= 40){
14217 relay : function(e){
14218 var k = e.getKey();
14219 var h = this.keyToHandler[k];
14221 if(this.doRelay(e, this[h], h) !== true){
14222 e[this.defaultEventAction]();
14228 doRelay : function(e, h, hname){
14229 return h.call(this.scope || this, e);
14232 // possible handlers
14246 // quick lookup hash
14263 * Enable this KeyNav
14265 enable: function(){
14267 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14268 // the EventObject will normalize Safari automatically
14269 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14270 this.el.on("keydown", this.relay, this);
14272 this.el.on("keydown", this.prepareEvent, this);
14273 this.el.on("keypress", this.relay, this);
14275 this.disabled = false;
14280 * Disable this KeyNav
14282 disable: function(){
14283 if(!this.disabled){
14284 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14285 this.el.un("keydown", this.relay);
14287 this.el.un("keydown", this.prepareEvent);
14288 this.el.un("keypress", this.relay);
14290 this.disabled = true;
14295 * Ext JS Library 1.1.1
14296 * Copyright(c) 2006-2007, Ext JS, LLC.
14298 * Originally Released Under LGPL - original licence link has changed is not relivant.
14301 * <script type="text/javascript">
14306 * @class Roo.KeyMap
14307 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14308 * The constructor accepts the same config object as defined by {@link #addBinding}.
14309 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14310 * combination it will call the function with this signature (if the match is a multi-key
14311 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14312 * A KeyMap can also handle a string representation of keys.<br />
14315 // map one key by key code
14316 var map = new Roo.KeyMap("my-element", {
14317 key: 13, // or Roo.EventObject.ENTER
14322 // map multiple keys to one action by string
14323 var map = new Roo.KeyMap("my-element", {
14329 // map multiple keys to multiple actions by strings and array of codes
14330 var map = new Roo.KeyMap("my-element", [
14333 fn: function(){ alert("Return was pressed"); }
14336 fn: function(){ alert('a, b or c was pressed'); }
14341 fn: function(){ alert('Control + shift + tab was pressed.'); }
14345 * <b>Note: A KeyMap starts enabled</b>
14347 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14348 * @param {Object} config The config (see {@link #addBinding})
14349 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14351 Roo.KeyMap = function(el, config, eventName){
14352 this.el = Roo.get(el);
14353 this.eventName = eventName || "keydown";
14354 this.bindings = [];
14356 this.addBinding(config);
14361 Roo.KeyMap.prototype = {
14363 * True to stop the event from bubbling and prevent the default browser action if the
14364 * key was handled by the KeyMap (defaults to false)
14370 * Add a new binding to this KeyMap. The following config object properties are supported:
14372 Property Type Description
14373 ---------- --------------- ----------------------------------------------------------------------
14374 key String/Array A single keycode or an array of keycodes to handle
14375 shift Boolean True to handle key only when shift is pressed (defaults to false)
14376 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14377 alt Boolean True to handle key only when alt is pressed (defaults to false)
14378 fn Function The function to call when KeyMap finds the expected key combination
14379 scope Object The scope of the callback function
14385 var map = new Roo.KeyMap(document, {
14386 key: Roo.EventObject.ENTER,
14391 //Add a new binding to the existing KeyMap later
14399 * @param {Object/Array} config A single KeyMap config or an array of configs
14401 addBinding : function(config){
14402 if(config instanceof Array){
14403 for(var i = 0, len = config.length; i < len; i++){
14404 this.addBinding(config[i]);
14408 var keyCode = config.key,
14409 shift = config.shift,
14410 ctrl = config.ctrl,
14413 scope = config.scope;
14414 if(typeof keyCode == "string"){
14416 var keyString = keyCode.toUpperCase();
14417 for(var j = 0, len = keyString.length; j < len; j++){
14418 ks.push(keyString.charCodeAt(j));
14422 var keyArray = keyCode instanceof Array;
14423 var handler = function(e){
14424 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14425 var k = e.getKey();
14427 for(var i = 0, len = keyCode.length; i < len; i++){
14428 if(keyCode[i] == k){
14429 if(this.stopEvent){
14432 fn.call(scope || window, k, e);
14438 if(this.stopEvent){
14441 fn.call(scope || window, k, e);
14446 this.bindings.push(handler);
14450 * Shorthand for adding a single key listener
14451 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14452 * following options:
14453 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14454 * @param {Function} fn The function to call
14455 * @param {Object} scope (optional) The scope of the function
14457 on : function(key, fn, scope){
14458 var keyCode, shift, ctrl, alt;
14459 if(typeof key == "object" && !(key instanceof Array)){
14478 handleKeyDown : function(e){
14479 if(this.enabled){ //just in case
14480 var b = this.bindings;
14481 for(var i = 0, len = b.length; i < len; i++){
14482 b[i].call(this, e);
14488 * Returns true if this KeyMap is enabled
14489 * @return {Boolean}
14491 isEnabled : function(){
14492 return this.enabled;
14496 * Enables this KeyMap
14498 enable: function(){
14500 this.el.on(this.eventName, this.handleKeyDown, this);
14501 this.enabled = true;
14506 * Disable this KeyMap
14508 disable: function(){
14510 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14511 this.enabled = false;
14516 * Ext JS Library 1.1.1
14517 * Copyright(c) 2006-2007, Ext JS, LLC.
14519 * Originally Released Under LGPL - original licence link has changed is not relivant.
14522 * <script type="text/javascript">
14527 * @class Roo.util.TextMetrics
14528 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14529 * wide, in pixels, a given block of text will be.
14532 Roo.util.TextMetrics = function(){
14536 * Measures the size of the specified text
14537 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14538 * that can affect the size of the rendered text
14539 * @param {String} text The text to measure
14540 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14541 * in order to accurately measure the text height
14542 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14544 measure : function(el, text, fixedWidth){
14546 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14549 shared.setFixedWidth(fixedWidth || 'auto');
14550 return shared.getSize(text);
14554 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14555 * the overhead of multiple calls to initialize the style properties on each measurement.
14556 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14557 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14558 * in order to accurately measure the text height
14559 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14561 createInstance : function(el, fixedWidth){
14562 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14569 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14570 var ml = new Roo.Element(document.createElement('div'));
14571 document.body.appendChild(ml.dom);
14572 ml.position('absolute');
14573 ml.setLeftTop(-1000, -1000);
14577 ml.setWidth(fixedWidth);
14582 * Returns the size of the specified text based on the internal element's style and width properties
14583 * @memberOf Roo.util.TextMetrics.Instance#
14584 * @param {String} text The text to measure
14585 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14587 getSize : function(text){
14589 var s = ml.getSize();
14595 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14596 * that can affect the size of the rendered text
14597 * @memberOf Roo.util.TextMetrics.Instance#
14598 * @param {String/HTMLElement} el The element, dom node or id
14600 bind : function(el){
14602 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14607 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14608 * to set a fixed width in order to accurately measure the text height.
14609 * @memberOf Roo.util.TextMetrics.Instance#
14610 * @param {Number} width The width to set on the element
14612 setFixedWidth : function(width){
14613 ml.setWidth(width);
14617 * Returns the measured width of the specified text
14618 * @memberOf Roo.util.TextMetrics.Instance#
14619 * @param {String} text The text to measure
14620 * @return {Number} width The width in pixels
14622 getWidth : function(text){
14623 ml.dom.style.width = 'auto';
14624 return this.getSize(text).width;
14628 * Returns the measured height of the specified text. For multiline text, be sure to call
14629 * {@link #setFixedWidth} if necessary.
14630 * @memberOf Roo.util.TextMetrics.Instance#
14631 * @param {String} text The text to measure
14632 * @return {Number} height The height in pixels
14634 getHeight : function(text){
14635 return this.getSize(text).height;
14639 instance.bind(bindTo);
14644 // backwards compat
14645 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14647 * Ext JS Library 1.1.1
14648 * Copyright(c) 2006-2007, Ext JS, LLC.
14650 * Originally Released Under LGPL - original licence link has changed is not relivant.
14653 * <script type="text/javascript">
14657 * @class Roo.state.Provider
14658 * Abstract base class for state provider implementations. This class provides methods
14659 * for encoding and decoding <b>typed</b> variables including dates and defines the
14660 * Provider interface.
14662 Roo.state.Provider = function(){
14664 * @event statechange
14665 * Fires when a state change occurs.
14666 * @param {Provider} this This state provider
14667 * @param {String} key The state key which was changed
14668 * @param {String} value The encoded value for the state
14671 "statechange": true
14674 Roo.state.Provider.superclass.constructor.call(this);
14676 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14678 * Returns the current value for a key
14679 * @param {String} name The key name
14680 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14681 * @return {Mixed} The state data
14683 get : function(name, defaultValue){
14684 return typeof this.state[name] == "undefined" ?
14685 defaultValue : this.state[name];
14689 * Clears a value from the state
14690 * @param {String} name The key name
14692 clear : function(name){
14693 delete this.state[name];
14694 this.fireEvent("statechange", this, name, null);
14698 * Sets the value for a key
14699 * @param {String} name The key name
14700 * @param {Mixed} value The value to set
14702 set : function(name, value){
14703 this.state[name] = value;
14704 this.fireEvent("statechange", this, name, value);
14708 * Decodes a string previously encoded with {@link #encodeValue}.
14709 * @param {String} value The value to decode
14710 * @return {Mixed} The decoded value
14712 decodeValue : function(cookie){
14713 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14714 var matches = re.exec(unescape(cookie));
14715 if(!matches || !matches[1]) return; // non state cookie
14716 var type = matches[1];
14717 var v = matches[2];
14720 return parseFloat(v);
14722 return new Date(Date.parse(v));
14727 var values = v.split("^");
14728 for(var i = 0, len = values.length; i < len; i++){
14729 all.push(this.decodeValue(values[i]));
14734 var values = v.split("^");
14735 for(var i = 0, len = values.length; i < len; i++){
14736 var kv = values[i].split("=");
14737 all[kv[0]] = this.decodeValue(kv[1]);
14746 * Encodes a value including type information. Decode with {@link #decodeValue}.
14747 * @param {Mixed} value The value to encode
14748 * @return {String} The encoded value
14750 encodeValue : function(v){
14752 if(typeof v == "number"){
14754 }else if(typeof v == "boolean"){
14755 enc = "b:" + (v ? "1" : "0");
14756 }else if(v instanceof Date){
14757 enc = "d:" + v.toGMTString();
14758 }else if(v instanceof Array){
14760 for(var i = 0, len = v.length; i < len; i++){
14761 flat += this.encodeValue(v[i]);
14762 if(i != len-1) flat += "^";
14765 }else if(typeof v == "object"){
14768 if(typeof v[key] != "function"){
14769 flat += key + "=" + this.encodeValue(v[key]) + "^";
14772 enc = "o:" + flat.substring(0, flat.length-1);
14776 return escape(enc);
14782 * Ext JS Library 1.1.1
14783 * Copyright(c) 2006-2007, Ext JS, LLC.
14785 * Originally Released Under LGPL - original licence link has changed is not relivant.
14788 * <script type="text/javascript">
14791 * @class Roo.state.Manager
14792 * This is the global state manager. By default all components that are "state aware" check this class
14793 * for state information if you don't pass them a custom state provider. In order for this class
14794 * to be useful, it must be initialized with a provider when your application initializes.
14796 // in your initialization function
14798 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14800 // supposed you have a {@link Roo.BorderLayout}
14801 var layout = new Roo.BorderLayout(...);
14802 layout.restoreState();
14803 // or a {Roo.BasicDialog}
14804 var dialog = new Roo.BasicDialog(...);
14805 dialog.restoreState();
14809 Roo.state.Manager = function(){
14810 var provider = new Roo.state.Provider();
14814 * Configures the default state provider for your application
14815 * @param {Provider} stateProvider The state provider to set
14817 setProvider : function(stateProvider){
14818 provider = stateProvider;
14822 * Returns the current value for a key
14823 * @param {String} name The key name
14824 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14825 * @return {Mixed} The state data
14827 get : function(key, defaultValue){
14828 return provider.get(key, defaultValue);
14832 * Sets the value for a key
14833 * @param {String} name The key name
14834 * @param {Mixed} value The state data
14836 set : function(key, value){
14837 provider.set(key, value);
14841 * Clears a value from the state
14842 * @param {String} name The key name
14844 clear : function(key){
14845 provider.clear(key);
14849 * Gets the currently configured state provider
14850 * @return {Provider} The state provider
14852 getProvider : function(){
14859 * Ext JS Library 1.1.1
14860 * Copyright(c) 2006-2007, Ext JS, LLC.
14862 * Originally Released Under LGPL - original licence link has changed is not relivant.
14865 * <script type="text/javascript">
14868 * @class Roo.state.CookieProvider
14869 * @extends Roo.state.Provider
14870 * The default Provider implementation which saves state via cookies.
14873 var cp = new Roo.state.CookieProvider({
14875 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14876 domain: "roojs.com"
14878 Roo.state.Manager.setProvider(cp);
14880 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14881 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14882 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14883 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14884 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14885 * domain the page is running on including the 'www' like 'www.roojs.com')
14886 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14888 * Create a new CookieProvider
14889 * @param {Object} config The configuration object
14891 Roo.state.CookieProvider = function(config){
14892 Roo.state.CookieProvider.superclass.constructor.call(this);
14894 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14895 this.domain = null;
14896 this.secure = false;
14897 Roo.apply(this, config);
14898 this.state = this.readCookies();
14901 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14903 set : function(name, value){
14904 if(typeof value == "undefined" || value === null){
14908 this.setCookie(name, value);
14909 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14913 clear : function(name){
14914 this.clearCookie(name);
14915 Roo.state.CookieProvider.superclass.clear.call(this, name);
14919 readCookies : function(){
14921 var c = document.cookie + ";";
14922 var re = /\s?(.*?)=(.*?);/g;
14924 while((matches = re.exec(c)) != null){
14925 var name = matches[1];
14926 var value = matches[2];
14927 if(name && name.substring(0,3) == "ys-"){
14928 cookies[name.substr(3)] = this.decodeValue(value);
14935 setCookie : function(name, value){
14936 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14937 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14938 ((this.path == null) ? "" : ("; path=" + this.path)) +
14939 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14940 ((this.secure == true) ? "; secure" : "");
14944 clearCookie : function(name){
14945 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14946 ((this.path == null) ? "" : ("; path=" + this.path)) +
14947 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14948 ((this.secure == true) ? "; secure" : "");