4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
89 * Turn on debugging output (currently only the factory uses this)
96 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
99 enableGarbageCollector : true,
102 * True to automatically purge event listeners after uncaching an element (defaults to false).
103 * Note: this only happens if enableGarbageCollector is true.
106 enableListenerCollection:false,
109 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
110 * the IE insecure content warning (defaults to javascript:false).
113 SSL_SECURE_URL : "javascript:false",
116 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
117 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
120 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
122 emptyFn : function(){},
129 clone : function(obj){
130 if (obj === null || typeof obj !== 'object') {
134 var temp = obj.constructor(); // give temp the original obj's constructor
135 for (var key in obj) {
136 temp[key] = this.clone(obj[key]);
143 * Copies all the properties of config to obj if they don't already exist.
144 * @param {Object} obj The receiver of the properties
145 * @param {Object} config The source of the properties
146 * @return {Object} returns obj
148 applyIf : function(o, c){
151 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
158 * Applies event listeners to elements by selectors when the document is ready.
159 * The event name is specified with an @ suffix.
162 // add a listener for click on all anchors in element with id foo
163 '#foo a@click' : function(e, t){
167 // add the same listener to multiple selectors (separated by comma BEFORE the @)
168 '#foo a, #bar span.some-class@mouseover' : function(){
173 * @param {Object} obj The list of behaviors to apply
175 addBehaviors : function(o){
177 Roo.onReady(function(){
182 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
184 var parts = b.split('@');
185 if(parts[1]){ // for Object prototype breakers
188 cache[s] = Roo.select(s);
190 cache[s].on(parts[1], o[b]);
197 * Generates unique ids. If the element already has an id, it is unchanged
198 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
199 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
200 * @return {String} The generated Id.
202 id : function(el, prefix){
203 prefix = prefix || "roo-gen";
205 var id = prefix + (++idSeed);
206 return el ? (el.id ? el.id : (el.id = id)) : id;
211 * Extends one class with another class and optionally overrides members with the passed literal. This class
212 * also adds the function "override()" to the class that can be used to override
213 * members on an instance.
214 * @param {Object} subclass The class inheriting the functionality
215 * @param {Object} superclass The class being extended
216 * @param {Object} overrides (optional) A literal with members
221 var io = function(o){
226 return function(sb, sp, overrides){
227 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
230 sb = function(){sp.apply(this, arguments);};
232 var F = function(){}, sbp, spp = sp.prototype;
234 sbp = sb.prototype = new F();
238 if(spp.constructor == Object.prototype.constructor){
243 sb.override = function(o){
247 Roo.override(sb, overrides);
253 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
255 Roo.override(MyClass, {
256 newMethod1: function(){
259 newMethod2: function(foo){
264 * @param {Object} origclass The class to override
265 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
266 * containing one or more methods.
269 override : function(origclass, overrides){
271 var p = origclass.prototype;
272 for(var method in overrides){
273 p[method] = overrides[method];
278 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
280 Roo.namespace('Company', 'Company.data');
281 Company.Widget = function() { ... }
282 Company.data.CustomStore = function(config) { ... }
284 * @param {String} namespace1
285 * @param {String} namespace2
286 * @param {String} etc
289 namespace : function(){
290 var a=arguments, o=null, i, j, d, rt;
291 for (i=0; i<a.length; ++i) {
295 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
296 for (j=1; j<d.length; ++j) {
297 o[d[j]]=o[d[j]] || {};
303 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
305 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
306 Roo.factory(conf, Roo.data);
308 * @param {String} classname
309 * @param {String} namespace (optional)
313 factory : function(c, ns)
315 // no xtype, no ns or c.xns - or forced off by c.xns
316 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
319 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
320 if (c.constructor == ns[c.xtype]) {// already created...
324 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
325 var ret = new ns[c.xtype](c);
329 c.xns = false; // prevent recursion..
333 * Logs to console if it can.
335 * @param {String|Object} string
340 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
347 * 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.
351 urlEncode : function(o){
357 var ov = o[key], k = Roo.encodeURIComponent(key);
358 var type = typeof ov;
359 if(type == 'undefined'){
361 }else if(type != "function" && type != "object"){
362 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
363 }else if(ov instanceof Array){
365 for(var i = 0, len = ov.length; i < len; i++) {
366 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
377 * Safe version of encodeURIComponent
378 * @param {String} data
382 encodeURIComponent : function (data)
385 return encodeURIComponent(data);
386 } catch(e) {} // should be an uri encode error.
388 if (data == '' || data == null){
391 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
392 function nibble_to_hex(nibble){
393 var chars = '0123456789ABCDEF';
394 return chars.charAt(nibble);
396 data = data.toString();
398 for(var i=0; i<data.length; i++){
399 var c = data.charCodeAt(i);
400 var bs = new Array();
403 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
404 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
405 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
406 bs[3] = 0x80 | (c & 0x3F);
407 }else if (c > 0x800){
409 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
410 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
411 bs[2] = 0x80 | (c & 0x3F);
414 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
415 bs[1] = 0x80 | (c & 0x3F);
420 for(var j=0; j<bs.length; j++){
422 var hex = nibble_to_hex((b & 0xF0) >>> 4)
423 + nibble_to_hex(b &0x0F);
432 * 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]}.
433 * @param {String} string
434 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
435 * @return {Object} A literal with members
437 urlDecode : function(string, overwrite){
438 if(!string || !string.length){
442 var pairs = string.split('&');
443 var pair, name, value;
444 for(var i = 0, len = pairs.length; i < len; i++){
445 pair = pairs[i].split('=');
446 name = decodeURIComponent(pair[0]);
447 value = decodeURIComponent(pair[1]);
448 if(overwrite !== true){
449 if(typeof obj[name] == "undefined"){
451 }else if(typeof obj[name] == "string"){
452 obj[name] = [obj[name]];
453 obj[name].push(value);
455 obj[name].push(value);
465 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
466 * passed array is not really an array, your function is called once with it.
467 * The supplied function is called with (Object item, Number index, Array allItems).
468 * @param {Array/NodeList/Mixed} array
469 * @param {Function} fn
470 * @param {Object} scope
472 each : function(array, fn, scope){
473 if(typeof array.length == "undefined" || typeof array == "string"){
476 for(var i = 0, len = array.length; i < len; i++){
477 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
482 combine : function(){
483 var as = arguments, l = as.length, r = [];
484 for(var i = 0; i < l; i++){
486 if(a instanceof Array){
488 }else if(a.length !== undefined && !a.substr){
489 r = r.concat(Array.prototype.slice.call(a, 0));
498 * Escapes the passed string for use in a regular expression
499 * @param {String} str
502 escapeRe : function(s) {
503 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
507 callback : function(cb, scope, args, delay){
508 if(typeof cb == "function"){
510 cb.defer(delay, scope, args || []);
512 cb.apply(scope, args || []);
518 * Return the dom node for the passed string (id), dom node, or Roo.Element
519 * @param {String/HTMLElement/Roo.Element} el
520 * @return HTMLElement
522 getDom : function(el){
526 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
530 * Shorthand for {@link Roo.ComponentMgr#get}
532 * @return Roo.Component
534 getCmp : function(id){
535 return Roo.ComponentMgr.get(id);
538 num : function(v, defaultValue){
539 if(typeof v != 'number'){
545 destroy : function(){
546 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
550 as.removeAllListeners();
554 if(typeof as.purgeListeners == 'function'){
557 if(typeof as.destroy == 'function'){
564 // inpired by a similar function in mootools library
566 * Returns the type of object that is passed in. If the object passed in is null or undefined it
567 * return false otherwise it returns one of the following values:<ul>
568 * <li><b>string</b>: If the object passed is a string</li>
569 * <li><b>number</b>: If the object passed is a number</li>
570 * <li><b>boolean</b>: If the object passed is a boolean value</li>
571 * <li><b>function</b>: If the object passed is a function reference</li>
572 * <li><b>object</b>: If the object passed is an object</li>
573 * <li><b>array</b>: If the object passed is an array</li>
574 * <li><b>regexp</b>: If the object passed is a regular expression</li>
575 * <li><b>element</b>: If the object passed is a DOM Element</li>
576 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
577 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
578 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
579 * @param {Mixed} object
583 if(o === undefined || o === null){
590 if(t == 'object' && o.nodeName) {
592 case 1: return 'element';
593 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
596 if(t == 'object' || t == 'function') {
597 switch(o.constructor) {
598 case Array: return 'array';
599 case RegExp: return 'regexp';
601 if(typeof o.length == 'number' && typeof o.item == 'function') {
609 * Returns true if the passed value is null, undefined or an empty string (optional).
610 * @param {Mixed} value The value to test
611 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
614 isEmpty : function(v, allowBlank){
615 return v === null || v === undefined || (!allowBlank ? v === '' : false);
629 isBorderBox : isBorderBox,
631 isWindows : isWindows,
638 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
639 * you may want to set this to true.
642 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
647 * Selects a single element as a Roo Element
648 * This is about as close as you can get to jQuery's $('do crazy stuff')
649 * @param {String} selector The selector/xpath query
650 * @param {Node} root (optional) The start of the query (defaults to document).
651 * @return {Roo.Element}
653 selectNode : function(selector, root)
655 var node = Roo.DomQuery.selectNode(selector,root);
656 return node ? Roo.get(node) : new Roo.Element(false);
664 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
665 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
668 * Ext JS Library 1.1.1
669 * Copyright(c) 2006-2007, Ext JS, LLC.
671 * Originally Released Under LGPL - original licence link has changed is not relivant.
674 * <script type="text/javascript">
678 // wrappedn so fnCleanup is not in global scope...
680 function fnCleanUp() {
681 var p = Function.prototype;
682 delete p.createSequence;
684 delete p.createDelegate;
685 delete p.createCallback;
686 delete p.createInterceptor;
688 window.detachEvent("onunload", fnCleanUp);
690 window.attachEvent("onunload", fnCleanUp);
697 * These functions are available on every Function object (any JavaScript function).
699 Roo.apply(Function.prototype, {
701 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
702 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
703 * Will create a function that is bound to those 2 args.
704 * @return {Function} The new function
706 createCallback : function(/*args...*/){
707 // make args available, in function below
708 var args = arguments;
711 return method.apply(window, args);
716 * Creates a delegate (callback) that sets the scope to obj.
717 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
718 * Will create a function that is automatically scoped to this.
719 * @param {Object} obj (optional) The object for which the scope is set
720 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
721 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
722 * if a number the args are inserted at the specified position
723 * @return {Function} The new function
725 createDelegate : function(obj, args, appendArgs){
728 var callArgs = args || arguments;
729 if(appendArgs === true){
730 callArgs = Array.prototype.slice.call(arguments, 0);
731 callArgs = callArgs.concat(args);
732 }else if(typeof appendArgs == "number"){
733 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
734 var applyArgs = [appendArgs, 0].concat(args); // create method call params
735 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
737 return method.apply(obj || window, callArgs);
742 * Calls this function after the number of millseconds specified.
743 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
744 * @param {Object} obj (optional) The object for which the scope is set
745 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
746 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
747 * if a number the args are inserted at the specified position
748 * @return {Number} The timeout id that can be used with clearTimeout
750 defer : function(millis, obj, args, appendArgs){
751 var fn = this.createDelegate(obj, args, appendArgs);
753 return setTimeout(fn, millis);
759 * Create a combined function call sequence of the original function + the passed function.
760 * The resulting function returns the results of the original function.
761 * The passed fcn is called with the parameters of the original function
762 * @param {Function} fcn The function to sequence
763 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
764 * @return {Function} The new function
766 createSequence : function(fcn, scope){
767 if(typeof fcn != "function"){
772 var retval = method.apply(this || window, arguments);
773 fcn.apply(scope || this || window, arguments);
779 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
780 * The resulting function returns the results of the original function.
781 * The passed fcn is called with the parameters of the original function.
783 * @param {Function} fcn The function to call before the original
784 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
785 * @return {Function} The new function
787 createInterceptor : function(fcn, scope){
788 if(typeof fcn != "function"){
795 if(fcn.apply(scope || this || window, arguments) === false){
798 return method.apply(this || window, arguments);
804 * Ext JS Library 1.1.1
805 * Copyright(c) 2006-2007, Ext JS, LLC.
807 * Originally Released Under LGPL - original licence link has changed is not relivant.
810 * <script type="text/javascript">
813 Roo.applyIf(String, {
818 * Escapes the passed string for ' and \
819 * @param {String} string The string to escape
820 * @return {String} The escaped string
823 escape : function(string) {
824 return string.replace(/('|\\)/g, "\\$1");
828 * Pads the left side of a string with a specified character. This is especially useful
829 * for normalizing number and date strings. Example usage:
831 var s = String.leftPad('123', 5, '0');
832 // s now contains the string: '00123'
834 * @param {String} string The original string
835 * @param {Number} size The total length of the output string
836 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
837 * @return {String} The padded string
840 leftPad : function (val, size, ch) {
841 var result = new String(val);
842 if(ch === null || ch === undefined || ch === '') {
845 while (result.length < size) {
846 result = ch + result;
852 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
853 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
855 var cls = 'my-class', text = 'Some text';
856 var s = String.format('<div class="{0}">{1}</div>', cls, text);
857 // s now contains the string: '<div class="my-class">Some text</div>'
859 * @param {String} string The tokenized string to be formatted
860 * @param {String} value1 The value to replace token {0}
861 * @param {String} value2 Etc...
862 * @return {String} The formatted string
865 format : function(format){
866 var args = Array.prototype.slice.call(arguments, 1);
867 return format.replace(/\{(\d+)\}/g, function(m, i){
868 return Roo.util.Format.htmlEncode(args[i]);
874 * Utility function that allows you to easily switch a string between two alternating values. The passed value
875 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
876 * they are already different, the first value passed in is returned. Note that this method returns the new value
877 * but does not change the current string.
879 // alternate sort directions
880 sort = sort.toggle('ASC', 'DESC');
882 // instead of conditional logic:
883 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
885 * @param {String} value The value to compare to the current string
886 * @param {String} other The new value to use if the string already equals the first value passed in
887 * @return {String} The new value
890 String.prototype.toggle = function(value, other){
891 return this == value ? other : value;
894 * Ext JS Library 1.1.1
895 * Copyright(c) 2006-2007, Ext JS, LLC.
897 * Originally Released Under LGPL - original licence link has changed is not relivant.
900 * <script type="text/javascript">
906 Roo.applyIf(Number.prototype, {
908 * Checks whether or not the current number is within a desired range. If the number is already within the
909 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
910 * exceeded. Note that this method returns the constrained value but does not change the current number.
911 * @param {Number} min The minimum number in the range
912 * @param {Number} max The maximum number in the range
913 * @return {Number} The constrained value if outside the range, otherwise the current value
915 constrain : function(min, max){
916 return Math.min(Math.max(this, min), max);
920 * Ext JS Library 1.1.1
921 * Copyright(c) 2006-2007, Ext JS, LLC.
923 * Originally Released Under LGPL - original licence link has changed is not relivant.
926 * <script type="text/javascript">
931 Roo.applyIf(Array.prototype, {
933 * Checks whether or not the specified object exists in the array.
934 * @param {Object} o The object to check for
935 * @return {Number} The index of o in the array (or -1 if it is not found)
937 indexOf : function(o){
938 for (var i = 0, len = this.length; i < len; i++){
939 if(this[i] == o) return i;
945 * Removes the specified object from the array. If the object is not found nothing happens.
946 * @param {Object} o The object to remove
948 remove : function(o){
949 var index = this.indexOf(o);
951 this.splice(index, 1);
955 * Map (JS 1.6 compatibility)
956 * @param {Function} function to call
960 var len = this.length >>> 0;
961 if (typeof fun != "function")
962 throw new TypeError();
964 var res = new Array(len);
965 var thisp = arguments[1];
966 for (var i = 0; i < len; i++)
969 res[i] = fun.call(thisp, this[i], i, this);
980 * Ext JS Library 1.1.1
981 * Copyright(c) 2006-2007, Ext JS, LLC.
983 * Originally Released Under LGPL - original licence link has changed is not relivant.
986 * <script type="text/javascript">
992 * The date parsing and format syntax is a subset of
993 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
994 * supported will provide results equivalent to their PHP versions.
996 * Following is the list of all currently supported formats:
999 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
1001 Format Output Description
1002 ------ ---------- --------------------------------------------------------------
1003 d 10 Day of the month, 2 digits with leading zeros
1004 D Wed A textual representation of a day, three letters
1005 j 10 Day of the month without leading zeros
1006 l Wednesday A full textual representation of the day of the week
1007 S th English ordinal day of month suffix, 2 chars (use with j)
1008 w 3 Numeric representation of the day of the week
1009 z 9 The julian date, or day of the year (0-365)
1010 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
1011 F January A full textual representation of the month
1012 m 01 Numeric representation of a month, with leading zeros
1013 M Jan Month name abbreviation, three letters
1014 n 1 Numeric representation of a month, without leading zeros
1015 t 31 Number of days in the given month
1016 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1017 Y 2007 A full numeric representation of a year, 4 digits
1018 y 07 A two digit representation of a year
1019 a pm Lowercase Ante meridiem and Post meridiem
1020 A PM Uppercase Ante meridiem and Post meridiem
1021 g 3 12-hour format of an hour without leading zeros
1022 G 15 24-hour format of an hour without leading zeros
1023 h 03 12-hour format of an hour with leading zeros
1024 H 15 24-hour format of an hour with leading zeros
1025 i 05 Minutes with leading zeros
1026 s 01 Seconds, with leading zeros
1027 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1028 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1029 T CST Timezone setting of the machine running the code
1030 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1033 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1035 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1036 document.write(dt.format('Y-m-d')); //2007-01-10
1037 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1038 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
1041 * Here are some standard date/time patterns that you might find helpful. They
1042 * are not part of the source of Date.js, but to use them you can simply copy this
1043 * block of code into any script that is included after Date.js and they will also become
1044 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1047 ISO8601Long:"Y-m-d H:i:s",
1048 ISO8601Short:"Y-m-d",
1050 LongDate: "l, F d, Y",
1051 FullDateTime: "l, F d, Y g:i:s A",
1054 LongTime: "g:i:s A",
1055 SortableDateTime: "Y-m-d\\TH:i:s",
1056 UniversalSortableDateTime: "Y-m-d H:i:sO",
1063 var dt = new Date();
1064 document.write(dt.format(Date.patterns.ShortDate));
1069 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1070 * They generate precompiled functions from date formats instead of parsing and
1071 * processing the pattern every time you format a date. These functions are available
1072 * on every Date object (any javascript function).
1074 * The original article and download are here:
1075 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1082 Returns the number of milliseconds between this date and date
1083 @param {Date} date (optional) Defaults to now
1084 @return {Number} The diff in milliseconds
1085 @member Date getElapsed
1087 Date.prototype.getElapsed = function(date) {
1088 return Math.abs((date || new Date()).getTime()-this.getTime());
1090 // was in date file..
1094 Date.parseFunctions = {count:0};
1096 Date.parseRegexes = [];
1098 Date.formatFunctions = {count:0};
1101 Date.prototype.dateFormat = function(format) {
1102 if (Date.formatFunctions[format] == null) {
1103 Date.createNewFormat(format);
1105 var func = Date.formatFunctions[format];
1106 return this[func]();
1111 * Formats a date given the supplied format string
1112 * @param {String} format The format string
1113 * @return {String} The formatted date
1116 Date.prototype.format = Date.prototype.dateFormat;
1119 Date.createNewFormat = function(format) {
1120 var funcName = "format" + Date.formatFunctions.count++;
1121 Date.formatFunctions[format] = funcName;
1122 var code = "Date.prototype." + funcName + " = function(){return ";
1123 var special = false;
1125 for (var i = 0; i < format.length; ++i) {
1126 ch = format.charAt(i);
1127 if (!special && ch == "\\") {
1132 code += "'" + String.escape(ch) + "' + ";
1135 code += Date.getFormatCode(ch);
1138 /** eval:var:zzzzzzzzzzzzz */
1139 eval(code.substring(0, code.length - 3) + ";}");
1143 Date.getFormatCode = function(character) {
1144 switch (character) {
1146 return "String.leftPad(this.getDate(), 2, '0') + ";
1148 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1150 return "this.getDate() + ";
1152 return "Date.dayNames[this.getDay()] + ";
1154 return "this.getSuffix() + ";
1156 return "this.getDay() + ";
1158 return "this.getDayOfYear() + ";
1160 return "this.getWeekOfYear() + ";
1162 return "Date.monthNames[this.getMonth()] + ";
1164 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1166 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1168 return "(this.getMonth() + 1) + ";
1170 return "this.getDaysInMonth() + ";
1172 return "(this.isLeapYear() ? 1 : 0) + ";
1174 return "this.getFullYear() + ";
1176 return "('' + this.getFullYear()).substring(2, 4) + ";
1178 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1180 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1182 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1184 return "this.getHours() + ";
1186 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1188 return "String.leftPad(this.getHours(), 2, '0') + ";
1190 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1192 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1194 return "this.getGMTOffset() + ";
1196 return "this.getGMTColonOffset() + ";
1198 return "this.getTimezone() + ";
1200 return "(this.getTimezoneOffset() * -60) + ";
1202 return "'" + String.escape(character) + "' + ";
1207 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1208 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1209 * the date format that is not specified will default to the current date value for that part. Time parts can also
1210 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1211 * string or the parse operation will fail.
1214 //dt = Fri May 25 2007 (current date)
1215 var dt = new Date();
1217 //dt = Thu May 25 2006 (today's month/day in 2006)
1218 dt = Date.parseDate("2006", "Y");
1220 //dt = Sun Jan 15 2006 (all date parts specified)
1221 dt = Date.parseDate("2006-1-15", "Y-m-d");
1223 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1224 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1226 * @param {String} input The unparsed date as a string
1227 * @param {String} format The format the date is in
1228 * @return {Date} The parsed date
1231 Date.parseDate = function(input, format) {
1232 if (Date.parseFunctions[format] == null) {
1233 Date.createParser(format);
1235 var func = Date.parseFunctions[format];
1236 return Date[func](input);
1241 Date.createParser = function(format) {
1242 var funcName = "parse" + Date.parseFunctions.count++;
1243 var regexNum = Date.parseRegexes.length;
1244 var currentGroup = 1;
1245 Date.parseFunctions[format] = funcName;
1247 var code = "Date." + funcName + " = function(input){\n"
1248 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1249 + "var d = new Date();\n"
1250 + "y = d.getFullYear();\n"
1251 + "m = d.getMonth();\n"
1252 + "d = d.getDate();\n"
1253 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1254 + "if (results && results.length > 0) {";
1257 var special = false;
1259 for (var i = 0; i < format.length; ++i) {
1260 ch = format.charAt(i);
1261 if (!special && ch == "\\") {
1266 regex += String.escape(ch);
1269 var obj = Date.formatCodeToRegex(ch, currentGroup);
1270 currentGroup += obj.g;
1272 if (obj.g && obj.c) {
1278 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1279 + "{v = new Date(y, m, d, h, i, s);}\n"
1280 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1281 + "{v = new Date(y, m, d, h, i);}\n"
1282 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1283 + "{v = new Date(y, m, d, h);}\n"
1284 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1285 + "{v = new Date(y, m, d);}\n"
1286 + "else if (y >= 0 && m >= 0)\n"
1287 + "{v = new Date(y, m);}\n"
1288 + "else if (y >= 0)\n"
1289 + "{v = new Date(y);}\n"
1290 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1291 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1292 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1295 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1296 /** eval:var:zzzzzzzzzzzzz */
1301 Date.formatCodeToRegex = function(character, currentGroup) {
1302 switch (character) {
1306 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1309 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1310 s:"(\\d{1,2})"}; // day of month without leading zeroes
1313 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1314 s:"(\\d{2})"}; // day of month with leading zeroes
1318 s:"(?:" + Date.dayNames.join("|") + ")"};
1322 s:"(?:st|nd|rd|th)"};
1337 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1338 s:"(" + Date.monthNames.join("|") + ")"};
1341 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1342 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1345 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1346 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1349 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1350 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1361 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1365 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1366 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1370 c:"if (results[" + currentGroup + "] == 'am') {\n"
1371 + "if (h == 12) { h = 0; }\n"
1372 + "} else { if (h < 12) { h += 12; }}",
1376 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1377 + "if (h == 12) { h = 0; }\n"
1378 + "} else { if (h < 12) { h += 12; }}",
1383 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1384 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1388 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1389 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1392 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1396 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1401 "o = results[", currentGroup, "];\n",
1402 "var sn = o.substring(0,1);\n", // get + / - sign
1403 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1404 "var mn = o.substring(3,5) % 60;\n", // get minutes
1405 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1406 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1408 s:"([+\-]\\d{2,4})"};
1414 "o = results[", currentGroup, "];\n",
1415 "var sn = o.substring(0,1);\n",
1416 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1417 "var mn = o.substring(4,6) % 60;\n",
1418 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1419 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1425 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1428 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1429 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1430 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1434 s:String.escape(character)};
1439 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1440 * @return {String} The abbreviated timezone name (e.g. 'CST')
1442 Date.prototype.getTimezone = function() {
1443 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1447 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1448 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1450 Date.prototype.getGMTOffset = function() {
1451 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1452 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1453 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1457 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1458 * @return {String} 2-characters representing hours and 2-characters representing minutes
1459 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1461 Date.prototype.getGMTColonOffset = function() {
1462 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1463 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1465 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1469 * Get the numeric day number of the year, adjusted for leap year.
1470 * @return {Number} 0 through 364 (365 in leap years)
1472 Date.prototype.getDayOfYear = function() {
1474 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1475 for (var i = 0; i < this.getMonth(); ++i) {
1476 num += Date.daysInMonth[i];
1478 return num + this.getDate() - 1;
1482 * Get the string representation of the numeric week number of the year
1483 * (equivalent to the format specifier 'W').
1484 * @return {String} '00' through '52'
1486 Date.prototype.getWeekOfYear = function() {
1487 // Skip to Thursday of this week
1488 var now = this.getDayOfYear() + (4 - this.getDay());
1489 // Find the first Thursday of the year
1490 var jan1 = new Date(this.getFullYear(), 0, 1);
1491 var then = (7 - jan1.getDay() + 4);
1492 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1496 * Whether or not the current date is in a leap year.
1497 * @return {Boolean} True if the current date is in a leap year, else false
1499 Date.prototype.isLeapYear = function() {
1500 var year = this.getFullYear();
1501 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1505 * Get the first 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.getFirstDayOfMonth()]); //output: 'Monday'
1513 * @return {Number} The day number (0-6)
1515 Date.prototype.getFirstDayOfMonth = function() {
1516 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1517 return (day < 0) ? (day + 7) : day;
1521 * Get the last day of the current month, adjusted for leap year. The returned value
1522 * is the numeric day index within the week (0-6) which can be used in conjunction with
1523 * the {@link #monthNames} array to retrieve the textual day name.
1526 var dt = new Date('1/10/2007');
1527 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1529 * @return {Number} The day number (0-6)
1531 Date.prototype.getLastDayOfMonth = function() {
1532 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1533 return (day < 0) ? (day + 7) : day;
1538 * Get the first date of this date's month
1541 Date.prototype.getFirstDateOfMonth = function() {
1542 return new Date(this.getFullYear(), this.getMonth(), 1);
1546 * Get the last date of this date's month
1549 Date.prototype.getLastDateOfMonth = function() {
1550 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1553 * Get the number of days in the current month, adjusted for leap year.
1554 * @return {Number} The number of days in the month
1556 Date.prototype.getDaysInMonth = function() {
1557 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1558 return Date.daysInMonth[this.getMonth()];
1562 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1563 * @return {String} 'st, 'nd', 'rd' or 'th'
1565 Date.prototype.getSuffix = function() {
1566 switch (this.getDate()) {
1583 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1586 * An array of textual month names.
1587 * Override these values for international dates, for example...
1588 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1607 * An array of textual day names.
1608 * Override these values for international dates, for example...
1609 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1625 Date.monthNumbers = {
1640 * Creates and returns a new Date instance with the exact same date value as the called instance.
1641 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1642 * variable will also be changed. When the intention is to create a new variable that will not
1643 * modify the original instance, you should create a clone.
1645 * Example of correctly cloning a date:
1648 var orig = new Date('10/1/2006');
1651 document.write(orig); //returns 'Thu Oct 05 2006'!
1654 var orig = new Date('10/1/2006');
1655 var copy = orig.clone();
1657 document.write(orig); //returns 'Thu Oct 01 2006'
1659 * @return {Date} The new Date instance
1661 Date.prototype.clone = function() {
1662 return new Date(this.getTime());
1666 * Clears any time information from this date
1667 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1668 @return {Date} this or the clone
1670 Date.prototype.clearTime = function(clone){
1672 return this.clone().clearTime();
1677 this.setMilliseconds(0);
1682 // safari setMonth is broken
1684 Date.brokenSetMonth = Date.prototype.setMonth;
1685 Date.prototype.setMonth = function(num){
1687 var n = Math.ceil(-num);
1688 var back_year = Math.ceil(n/12);
1689 var month = (n % 12) ? 12 - n % 12 : 0 ;
1690 this.setFullYear(this.getFullYear() - back_year);
1691 return Date.brokenSetMonth.call(this, month);
1693 return Date.brokenSetMonth.apply(this, arguments);
1698 /** Date interval constant
1702 /** Date interval constant
1706 /** Date interval constant
1710 /** Date interval constant
1714 /** Date interval constant
1718 /** Date interval constant
1722 /** Date interval constant
1728 * Provides a convenient method of performing basic date arithmetic. This method
1729 * does not modify the Date instance being called - it creates and returns
1730 * a new Date instance containing the resulting date value.
1735 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1736 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1738 //Negative values will subtract correctly:
1739 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1740 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1742 //You can even chain several calls together in one line!
1743 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1744 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1747 * @param {String} interval A valid date interval enum value
1748 * @param {Number} value The amount to add to the current date
1749 * @return {Date} The new Date instance
1751 Date.prototype.add = function(interval, value){
1752 var d = this.clone();
1753 if (!interval || value === 0) return d;
1754 switch(interval.toLowerCase()){
1756 d.setMilliseconds(this.getMilliseconds() + value);
1759 d.setSeconds(this.getSeconds() + value);
1762 d.setMinutes(this.getMinutes() + value);
1765 d.setHours(this.getHours() + value);
1768 d.setDate(this.getDate() + value);
1771 var day = this.getDate();
1773 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1776 d.setMonth(this.getMonth() + value);
1779 d.setFullYear(this.getFullYear() + value);
1786 * Ext JS Library 1.1.1
1787 * Copyright(c) 2006-2007, Ext JS, LLC.
1789 * Originally Released Under LGPL - original licence link has changed is not relivant.
1792 * <script type="text/javascript">
1796 * @class Roo.lib.Dom
1799 * Dom utils (from YIU afaik)
1804 * Get the view width
1805 * @param {Boolean} full True will get the full document, otherwise it's the view width
1806 * @return {Number} The width
1809 getViewWidth : function(full) {
1810 return full ? this.getDocumentWidth() : this.getViewportWidth();
1813 * Get the view height
1814 * @param {Boolean} full True will get the full document, otherwise it's the view height
1815 * @return {Number} The height
1817 getViewHeight : function(full) {
1818 return full ? this.getDocumentHeight() : this.getViewportHeight();
1821 getDocumentHeight: function() {
1822 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1823 return Math.max(scrollHeight, this.getViewportHeight());
1826 getDocumentWidth: function() {
1827 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1828 return Math.max(scrollWidth, this.getViewportWidth());
1831 getViewportHeight: function() {
1832 var height = self.innerHeight;
1833 var mode = document.compatMode;
1835 if ((mode || Roo.isIE) && !Roo.isOpera) {
1836 height = (mode == "CSS1Compat") ?
1837 document.documentElement.clientHeight :
1838 document.body.clientHeight;
1844 getViewportWidth: function() {
1845 var width = self.innerWidth;
1846 var mode = document.compatMode;
1848 if (mode || Roo.isIE) {
1849 width = (mode == "CSS1Compat") ?
1850 document.documentElement.clientWidth :
1851 document.body.clientWidth;
1856 isAncestor : function(p, c) {
1863 if (p.contains && !Roo.isSafari) {
1864 return p.contains(c);
1865 } else if (p.compareDocumentPosition) {
1866 return !!(p.compareDocumentPosition(c) & 16);
1868 var parent = c.parentNode;
1873 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1876 parent = parent.parentNode;
1882 getRegion : function(el) {
1883 return Roo.lib.Region.getRegion(el);
1886 getY : function(el) {
1887 return this.getXY(el)[1];
1890 getX : function(el) {
1891 return this.getXY(el)[0];
1894 getXY : function(el) {
1895 var p, pe, b, scroll, bd = document.body;
1896 el = Roo.getDom(el);
1897 var fly = Roo.lib.AnimBase.fly;
1898 if (el.getBoundingClientRect) {
1899 b = el.getBoundingClientRect();
1900 scroll = fly(document).getScroll();
1901 return [b.left + scroll.left, b.top + scroll.top];
1907 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1914 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1921 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1922 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1929 if (p != el && pe.getStyle('overflow') != 'visible') {
1937 if (Roo.isSafari && hasAbsolute) {
1942 if (Roo.isGecko && !hasAbsolute) {
1944 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1945 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1949 while (p && p != bd) {
1950 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1962 setXY : function(el, xy) {
1963 el = Roo.fly(el, '_setXY');
1965 var pts = el.translatePoints(xy);
1966 if (xy[0] !== false) {
1967 el.dom.style.left = pts.left + "px";
1969 if (xy[1] !== false) {
1970 el.dom.style.top = pts.top + "px";
1974 setX : function(el, x) {
1975 this.setXY(el, [x, false]);
1978 setY : function(el, y) {
1979 this.setXY(el, [false, y]);
1983 * Portions of this file are based on pieces of Yahoo User Interface Library
1984 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1985 * YUI licensed under the BSD License:
1986 * http://developer.yahoo.net/yui/license.txt
1987 * <script type="text/javascript">
1991 Roo.lib.Event = function() {
1992 var loadComplete = false;
1994 var unloadListeners = [];
1996 var onAvailStack = [];
1998 var lastError = null;
2011 startInterval: function() {
2012 if (!this._interval) {
2014 var callback = function() {
2015 self._tryPreloadAttach();
2017 this._interval = setInterval(callback, this.POLL_INTERVAL);
2022 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2023 onAvailStack.push({ id: p_id,
2026 override: p_override,
2027 checkReady: false });
2029 retryCount = this.POLL_RETRYS;
2030 this.startInterval();
2034 addListener: function(el, eventName, fn) {
2035 el = Roo.getDom(el);
2040 if ("unload" == eventName) {
2041 unloadListeners[unloadListeners.length] =
2042 [el, eventName, fn];
2046 var wrappedFn = function(e) {
2047 return fn(Roo.lib.Event.getEvent(e));
2050 var li = [el, eventName, fn, wrappedFn];
2052 var index = listeners.length;
2053 listeners[index] = li;
2055 this.doAdd(el, eventName, wrappedFn, false);
2061 removeListener: function(el, eventName, fn) {
2064 el = Roo.getDom(el);
2067 return this.purgeElement(el, false, eventName);
2071 if ("unload" == eventName) {
2073 for (i = 0,len = unloadListeners.length; i < len; i++) {
2074 var li = unloadListeners[i];
2077 li[1] == eventName &&
2079 unloadListeners.splice(i, 1);
2087 var cacheItem = null;
2090 var index = arguments[3];
2092 if ("undefined" == typeof index) {
2093 index = this._getCacheIndex(el, eventName, fn);
2097 cacheItem = listeners[index];
2100 if (!el || !cacheItem) {
2104 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2106 delete listeners[index][this.WFN];
2107 delete listeners[index][this.FN];
2108 listeners.splice(index, 1);
2115 getTarget: function(ev, resolveTextNode) {
2116 ev = ev.browserEvent || ev;
2117 var t = ev.target || ev.srcElement;
2118 return this.resolveTextNode(t);
2122 resolveTextNode: function(node) {
2123 if (Roo.isSafari && node && 3 == node.nodeType) {
2124 return node.parentNode;
2131 getPageX: function(ev) {
2132 ev = ev.browserEvent || ev;
2134 if (!x && 0 !== x) {
2135 x = ev.clientX || 0;
2138 x += this.getScroll()[1];
2146 getPageY: function(ev) {
2147 ev = ev.browserEvent || ev;
2149 if (!y && 0 !== y) {
2150 y = ev.clientY || 0;
2153 y += this.getScroll()[0];
2162 getXY: function(ev) {
2163 ev = ev.browserEvent || ev;
2164 return [this.getPageX(ev), this.getPageY(ev)];
2168 getRelatedTarget: function(ev) {
2169 ev = ev.browserEvent || ev;
2170 var t = ev.relatedTarget;
2172 if (ev.type == "mouseout") {
2174 } else if (ev.type == "mouseover") {
2179 return this.resolveTextNode(t);
2183 getTime: function(ev) {
2184 ev = ev.browserEvent || ev;
2186 var t = new Date().getTime();
2190 this.lastError = ex;
2199 stopEvent: function(ev) {
2200 this.stopPropagation(ev);
2201 this.preventDefault(ev);
2205 stopPropagation: function(ev) {
2206 ev = ev.browserEvent || ev;
2207 if (ev.stopPropagation) {
2208 ev.stopPropagation();
2210 ev.cancelBubble = true;
2215 preventDefault: function(ev) {
2216 ev = ev.browserEvent || ev;
2217 if(ev.preventDefault) {
2218 ev.preventDefault();
2220 ev.returnValue = false;
2225 getEvent: function(e) {
2226 var ev = e || window.event;
2228 var c = this.getEvent.caller;
2230 ev = c.arguments[0];
2231 if (ev && Event == ev.constructor) {
2241 getCharCode: function(ev) {
2242 ev = ev.browserEvent || ev;
2243 return ev.charCode || ev.keyCode || 0;
2247 _getCacheIndex: function(el, eventName, fn) {
2248 for (var i = 0,len = listeners.length; i < len; ++i) {
2249 var li = listeners[i];
2251 li[this.FN] == fn &&
2252 li[this.EL] == el &&
2253 li[this.TYPE] == eventName) {
2265 getEl: function(id) {
2266 return document.getElementById(id);
2270 clearCache: function() {
2274 _load: function(e) {
2275 loadComplete = true;
2276 var EU = Roo.lib.Event;
2280 EU.doRemove(window, "load", EU._load);
2285 _tryPreloadAttach: function() {
2294 var tryAgain = !loadComplete;
2296 tryAgain = (retryCount > 0);
2301 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2302 var item = onAvailStack[i];
2304 var el = this.getEl(item.id);
2307 if (!item.checkReady ||
2310 (document && document.body)) {
2313 if (item.override) {
2314 if (item.override === true) {
2317 scope = item.override;
2320 item.fn.call(scope, item.obj);
2321 onAvailStack[i] = null;
2324 notAvail.push(item);
2329 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2333 this.startInterval();
2335 clearInterval(this._interval);
2336 this._interval = null;
2339 this.locked = false;
2346 purgeElement: function(el, recurse, eventName) {
2347 var elListeners = this.getListeners(el, eventName);
2349 for (var i = 0,len = elListeners.length; i < len; ++i) {
2350 var l = elListeners[i];
2351 this.removeListener(el, l.type, l.fn);
2355 if (recurse && el && el.childNodes) {
2356 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2357 this.purgeElement(el.childNodes[i], recurse, eventName);
2363 getListeners: function(el, eventName) {
2364 var results = [], searchLists;
2366 searchLists = [listeners, unloadListeners];
2367 } else if (eventName == "unload") {
2368 searchLists = [unloadListeners];
2370 searchLists = [listeners];
2373 for (var j = 0; j < searchLists.length; ++j) {
2374 var searchList = searchLists[j];
2375 if (searchList && searchList.length > 0) {
2376 for (var i = 0,len = searchList.length; i < len; ++i) {
2377 var l = searchList[i];
2378 if (l && l[this.EL] === el &&
2379 (!eventName || eventName === l[this.TYPE])) {
2384 adjust: l[this.ADJ_SCOPE],
2392 return (results.length) ? results : null;
2396 _unload: function(e) {
2398 var EU = Roo.lib.Event, i, j, l, len, index;
2400 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2401 l = unloadListeners[i];
2404 if (l[EU.ADJ_SCOPE]) {
2405 if (l[EU.ADJ_SCOPE] === true) {
2408 scope = l[EU.ADJ_SCOPE];
2411 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2412 unloadListeners[i] = null;
2418 unloadListeners = null;
2420 if (listeners && listeners.length > 0) {
2421 j = listeners.length;
2424 l = listeners[index];
2426 EU.removeListener(l[EU.EL], l[EU.TYPE],
2436 EU.doRemove(window, "unload", EU._unload);
2441 getScroll: function() {
2442 var dd = document.documentElement, db = document.body;
2443 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2444 return [dd.scrollTop, dd.scrollLeft];
2446 return [db.scrollTop, db.scrollLeft];
2453 doAdd: function () {
2454 if (window.addEventListener) {
2455 return function(el, eventName, fn, capture) {
2456 el.addEventListener(eventName, fn, (capture));
2458 } else if (window.attachEvent) {
2459 return function(el, eventName, fn, capture) {
2460 el.attachEvent("on" + eventName, fn);
2469 doRemove: function() {
2470 if (window.removeEventListener) {
2471 return function (el, eventName, fn, capture) {
2472 el.removeEventListener(eventName, fn, (capture));
2474 } else if (window.detachEvent) {
2475 return function (el, eventName, fn) {
2476 el.detachEvent("on" + eventName, fn);
2488 var E = Roo.lib.Event;
2489 E.on = E.addListener;
2490 E.un = E.removeListener;
2492 if (document && document.body) {
2495 E.doAdd(window, "load", E._load);
2497 E.doAdd(window, "unload", E._unload);
2498 E._tryPreloadAttach();
2502 * Portions of this file are based on pieces of Yahoo User Interface Library
2503 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2504 * YUI licensed under the BSD License:
2505 * http://developer.yahoo.net/yui/license.txt
2506 * <script type="text/javascript">
2512 * @class Roo.lib.Ajax
2519 request : function(method, uri, cb, data, options) {
2521 var hs = options.headers;
2524 if(hs.hasOwnProperty(h)){
2525 this.initHeader(h, hs[h], false);
2529 if(options.xmlData){
2530 this.initHeader('Content-Type', 'text/xml', false);
2532 data = options.xmlData;
2536 return this.asyncRequest(method, uri, cb, data);
2539 serializeForm : function(form) {
2540 if(typeof form == 'string') {
2541 form = (document.getElementById(form) || document.forms[form]);
2544 var el, name, val, disabled, data = '', hasSubmit = false;
2545 for (var i = 0; i < form.elements.length; i++) {
2546 el = form.elements[i];
2547 disabled = form.elements[i].disabled;
2548 name = form.elements[i].name;
2549 val = form.elements[i].value;
2551 if (!disabled && name){
2555 case 'select-multiple':
2556 for (var j = 0; j < el.options.length; j++) {
2557 if (el.options[j].selected) {
2559 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2562 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2570 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2583 if(hasSubmit == false) {
2584 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2589 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2594 data = data.substr(0, data.length - 1);
2602 useDefaultHeader:true,
2604 defaultPostHeader:'application/x-www-form-urlencoded',
2606 useDefaultXhrHeader:true,
2608 defaultXhrHeader:'XMLHttpRequest',
2610 hasDefaultHeaders:true,
2622 setProgId:function(id)
2624 this.activeX.unshift(id);
2627 setDefaultPostHeader:function(b)
2629 this.useDefaultHeader = b;
2632 setDefaultXhrHeader:function(b)
2634 this.useDefaultXhrHeader = b;
2637 setPollingInterval:function(i)
2639 if (typeof i == 'number' && isFinite(i)) {
2640 this.pollInterval = i;
2644 createXhrObject:function(transactionId)
2650 http = new XMLHttpRequest();
2652 obj = { conn:http, tId:transactionId };
2656 for (var i = 0; i < this.activeX.length; ++i) {
2660 http = new ActiveXObject(this.activeX[i]);
2662 obj = { conn:http, tId:transactionId };
2675 getConnectionObject:function()
2678 var tId = this.transactionId;
2682 o = this.createXhrObject(tId);
2684 this.transactionId++;
2695 asyncRequest:function(method, uri, callback, postData)
2697 var o = this.getConnectionObject();
2703 o.conn.open(method, uri, true);
2705 if (this.useDefaultXhrHeader) {
2706 if (!this.defaultHeaders['X-Requested-With']) {
2707 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2711 if(postData && this.useDefaultHeader){
2712 this.initHeader('Content-Type', this.defaultPostHeader);
2715 if (this.hasDefaultHeaders || this.hasHeaders) {
2719 this.handleReadyState(o, callback);
2720 o.conn.send(postData || null);
2726 handleReadyState:function(o, callback)
2730 if (callback && callback.timeout) {
2732 this.timeout[o.tId] = window.setTimeout(function() {
2733 oConn.abort(o, callback, true);
2734 }, callback.timeout);
2737 this.poll[o.tId] = window.setInterval(
2739 if (o.conn && o.conn.readyState == 4) {
2740 window.clearInterval(oConn.poll[o.tId]);
2741 delete oConn.poll[o.tId];
2743 if(callback && callback.timeout) {
2744 window.clearTimeout(oConn.timeout[o.tId]);
2745 delete oConn.timeout[o.tId];
2748 oConn.handleTransactionResponse(o, callback);
2751 , this.pollInterval);
2754 handleTransactionResponse:function(o, callback, isAbort)
2758 this.releaseObject(o);
2762 var httpStatus, responseObject;
2766 if (o.conn.status !== undefined && o.conn.status != 0) {
2767 httpStatus = o.conn.status;
2779 if (httpStatus >= 200 && httpStatus < 300) {
2780 responseObject = this.createResponseObject(o, callback.argument);
2781 if (callback.success) {
2782 if (!callback.scope) {
2783 callback.success(responseObject);
2788 callback.success.apply(callback.scope, [responseObject]);
2793 switch (httpStatus) {
2801 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2802 if (callback.failure) {
2803 if (!callback.scope) {
2804 callback.failure(responseObject);
2807 callback.failure.apply(callback.scope, [responseObject]);
2812 responseObject = this.createResponseObject(o, callback.argument);
2813 if (callback.failure) {
2814 if (!callback.scope) {
2815 callback.failure(responseObject);
2818 callback.failure.apply(callback.scope, [responseObject]);
2824 this.releaseObject(o);
2825 responseObject = null;
2828 createResponseObject:function(o, callbackArg)
2835 var headerStr = o.conn.getAllResponseHeaders();
2836 var header = headerStr.split('\n');
2837 for (var i = 0; i < header.length; i++) {
2838 var delimitPos = header[i].indexOf(':');
2839 if (delimitPos != -1) {
2840 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2848 obj.status = o.conn.status;
2849 obj.statusText = o.conn.statusText;
2850 obj.getResponseHeader = headerObj;
2851 obj.getAllResponseHeaders = headerStr;
2852 obj.responseText = o.conn.responseText;
2853 obj.responseXML = o.conn.responseXML;
2855 if (typeof callbackArg !== undefined) {
2856 obj.argument = callbackArg;
2862 createExceptionObject:function(tId, callbackArg, isAbort)
2865 var COMM_ERROR = 'communication failure';
2866 var ABORT_CODE = -1;
2867 var ABORT_ERROR = 'transaction aborted';
2873 obj.status = ABORT_CODE;
2874 obj.statusText = ABORT_ERROR;
2877 obj.status = COMM_CODE;
2878 obj.statusText = COMM_ERROR;
2882 obj.argument = callbackArg;
2888 initHeader:function(label, value, isDefault)
2890 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2892 if (headerObj[label] === undefined) {
2893 headerObj[label] = value;
2898 headerObj[label] = value + "," + headerObj[label];
2902 this.hasDefaultHeaders = true;
2905 this.hasHeaders = true;
2910 setHeader:function(o)
2912 if (this.hasDefaultHeaders) {
2913 for (var prop in this.defaultHeaders) {
2914 if (this.defaultHeaders.hasOwnProperty(prop)) {
2915 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2920 if (this.hasHeaders) {
2921 for (var prop in this.headers) {
2922 if (this.headers.hasOwnProperty(prop)) {
2923 o.conn.setRequestHeader(prop, this.headers[prop]);
2927 this.hasHeaders = false;
2931 resetDefaultHeaders:function() {
2932 delete this.defaultHeaders;
2933 this.defaultHeaders = {};
2934 this.hasDefaultHeaders = false;
2937 abort:function(o, callback, isTimeout)
2939 if(this.isCallInProgress(o)) {
2941 window.clearInterval(this.poll[o.tId]);
2942 delete this.poll[o.tId];
2944 delete this.timeout[o.tId];
2947 this.handleTransactionResponse(o, callback, true);
2957 isCallInProgress:function(o)
2960 return o.conn.readyState != 4 && o.conn.readyState != 0;
2969 releaseObject:function(o)
2978 'MSXML2.XMLHTTP.3.0',
2986 * Portions of this file are based on pieces of Yahoo User Interface Library
2987 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2988 * YUI licensed under the BSD License:
2989 * http://developer.yahoo.net/yui/license.txt
2990 * <script type="text/javascript">
2994 Roo.lib.Region = function(t, r, b, l) {
3004 Roo.lib.Region.prototype = {
3005 contains : function(region) {
3006 return ( region.left >= this.left &&
3007 region.right <= this.right &&
3008 region.top >= this.top &&
3009 region.bottom <= this.bottom );
3013 getArea : function() {
3014 return ( (this.bottom - this.top) * (this.right - this.left) );
3017 intersect : function(region) {
3018 var t = Math.max(this.top, region.top);
3019 var r = Math.min(this.right, region.right);
3020 var b = Math.min(this.bottom, region.bottom);
3021 var l = Math.max(this.left, region.left);
3023 if (b >= t && r >= l) {
3024 return new Roo.lib.Region(t, r, b, l);
3029 union : function(region) {
3030 var t = Math.min(this.top, region.top);
3031 var r = Math.max(this.right, region.right);
3032 var b = Math.max(this.bottom, region.bottom);
3033 var l = Math.min(this.left, region.left);
3035 return new Roo.lib.Region(t, r, b, l);
3038 adjust : function(t, l, b, r) {
3047 Roo.lib.Region.getRegion = function(el) {
3048 var p = Roo.lib.Dom.getXY(el);
3051 var r = p[0] + el.offsetWidth;
3052 var b = p[1] + el.offsetHeight;
3055 return new Roo.lib.Region(t, r, b, l);
3058 * Portions of this file are based on pieces of Yahoo User Interface Library
3059 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3060 * YUI licensed under the BSD License:
3061 * http://developer.yahoo.net/yui/license.txt
3062 * <script type="text/javascript">
3065 //@@dep Roo.lib.Region
3068 Roo.lib.Point = function(x, y) {
3069 if (x instanceof Array) {
3073 this.x = this.right = this.left = this[0] = x;
3074 this.y = this.top = this.bottom = this[1] = y;
3077 Roo.lib.Point.prototype = new Roo.lib.Region();
3079 * Portions of this file are based on pieces of Yahoo User Interface Library
3080 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3081 * YUI licensed under the BSD License:
3082 * http://developer.yahoo.net/yui/license.txt
3083 * <script type="text/javascript">
3090 scroll : function(el, args, duration, easing, cb, scope) {
3091 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3094 motion : function(el, args, duration, easing, cb, scope) {
3095 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3098 color : function(el, args, duration, easing, cb, scope) {
3099 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3102 run : function(el, args, duration, easing, cb, scope, type) {
3103 type = type || Roo.lib.AnimBase;
3104 if (typeof easing == "string") {
3105 easing = Roo.lib.Easing[easing];
3107 var anim = new type(el, args, duration, easing);
3108 anim.animateX(function() {
3109 Roo.callback(cb, scope);
3115 * Portions of this file are based on pieces of Yahoo User Interface Library
3116 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3117 * YUI licensed under the BSD License:
3118 * http://developer.yahoo.net/yui/license.txt
3119 * <script type="text/javascript">
3127 if (!libFlyweight) {
3128 libFlyweight = new Roo.Element.Flyweight();
3130 libFlyweight.dom = el;
3131 return libFlyweight;
3134 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3138 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3140 this.init(el, attributes, duration, method);
3144 Roo.lib.AnimBase.fly = fly;
3148 Roo.lib.AnimBase.prototype = {
3150 toString: function() {
3151 var el = this.getEl();
3152 var id = el.id || el.tagName;
3153 return ("Anim " + id);
3157 noNegatives: /width|height|opacity|padding/i,
3158 offsetAttribute: /^((width|height)|(top|left))$/,
3159 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3160 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3164 doMethod: function(attr, start, end) {
3165 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3169 setAttribute: function(attr, val, unit) {
3170 if (this.patterns.noNegatives.test(attr)) {
3171 val = (val > 0) ? val : 0;
3174 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3178 getAttribute: function(attr) {
3179 var el = this.getEl();
3180 var val = fly(el).getStyle(attr);
3182 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3183 return parseFloat(val);
3186 var a = this.patterns.offsetAttribute.exec(attr) || [];
3187 var pos = !!( a[3] );
3188 var box = !!( a[2] );
3191 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3192 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3201 getDefaultUnit: function(attr) {
3202 if (this.patterns.defaultUnit.test(attr)) {
3209 animateX : function(callback, scope) {
3210 var f = function() {
3211 this.onComplete.removeListener(f);
3212 if (typeof callback == "function") {
3213 callback.call(scope || this, this);
3216 this.onComplete.addListener(f, this);
3221 setRuntimeAttribute: function(attr) {
3224 var attributes = this.attributes;
3226 this.runtimeAttributes[attr] = {};
3228 var isset = function(prop) {
3229 return (typeof prop !== 'undefined');
3232 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3236 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3239 if (isset(attributes[attr]['to'])) {
3240 end = attributes[attr]['to'];
3241 } else if (isset(attributes[attr]['by'])) {
3242 if (start.constructor == Array) {
3244 for (var i = 0, len = start.length; i < len; ++i) {
3245 end[i] = start[i] + attributes[attr]['by'][i];
3248 end = start + attributes[attr]['by'];
3252 this.runtimeAttributes[attr].start = start;
3253 this.runtimeAttributes[attr].end = end;
3256 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3260 init: function(el, attributes, duration, method) {
3262 var isAnimated = false;
3265 var startTime = null;
3268 var actualFrames = 0;
3271 el = Roo.getDom(el);
3274 this.attributes = attributes || {};
3277 this.duration = duration || 1;
3280 this.method = method || Roo.lib.Easing.easeNone;
3283 this.useSeconds = true;
3286 this.currentFrame = 0;
3289 this.totalFrames = Roo.lib.AnimMgr.fps;
3292 this.getEl = function() {
3297 this.isAnimated = function() {
3302 this.getStartTime = function() {
3306 this.runtimeAttributes = {};
3309 this.animate = function() {
3310 if (this.isAnimated()) {
3314 this.currentFrame = 0;
3316 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3318 Roo.lib.AnimMgr.registerElement(this);
3322 this.stop = function(finish) {
3324 this.currentFrame = this.totalFrames;
3325 this._onTween.fire();
3327 Roo.lib.AnimMgr.stop(this);
3330 var onStart = function() {
3331 this.onStart.fire();
3333 this.runtimeAttributes = {};
3334 for (var attr in this.attributes) {
3335 this.setRuntimeAttribute(attr);
3340 startTime = new Date();
3344 var onTween = function() {
3346 duration: new Date() - this.getStartTime(),
3347 currentFrame: this.currentFrame
3350 data.toString = function() {
3352 'duration: ' + data.duration +
3353 ', currentFrame: ' + data.currentFrame
3357 this.onTween.fire(data);
3359 var runtimeAttributes = this.runtimeAttributes;
3361 for (var attr in runtimeAttributes) {
3362 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3368 var onComplete = function() {
3369 var actual_duration = (new Date() - startTime) / 1000 ;
3372 duration: actual_duration,
3373 frames: actualFrames,
3374 fps: actualFrames / actual_duration
3377 data.toString = function() {
3379 'duration: ' + data.duration +
3380 ', frames: ' + data.frames +
3381 ', fps: ' + data.fps
3387 this.onComplete.fire(data);
3391 this._onStart = new Roo.util.Event(this);
3392 this.onStart = new Roo.util.Event(this);
3393 this.onTween = new Roo.util.Event(this);
3394 this._onTween = new Roo.util.Event(this);
3395 this.onComplete = new Roo.util.Event(this);
3396 this._onComplete = new Roo.util.Event(this);
3397 this._onStart.addListener(onStart);
3398 this._onTween.addListener(onTween);
3399 this._onComplete.addListener(onComplete);
3404 * Portions of this file are based on pieces of Yahoo User Interface Library
3405 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3406 * YUI licensed under the BSD License:
3407 * http://developer.yahoo.net/yui/license.txt
3408 * <script type="text/javascript">
3412 Roo.lib.AnimMgr = new function() {
3429 this.registerElement = function(tween) {
3430 queue[queue.length] = tween;
3432 tween._onStart.fire();
3437 this.unRegister = function(tween, index) {
3438 tween._onComplete.fire();
3439 index = index || getIndex(tween);
3441 queue.splice(index, 1);
3445 if (tweenCount <= 0) {
3451 this.start = function() {
3452 if (thread === null) {
3453 thread = setInterval(this.run, this.delay);
3458 this.stop = function(tween) {
3460 clearInterval(thread);
3462 for (var i = 0, len = queue.length; i < len; ++i) {
3463 if (queue[0].isAnimated()) {
3464 this.unRegister(queue[0], 0);
3473 this.unRegister(tween);
3478 this.run = function() {
3479 for (var i = 0, len = queue.length; i < len; ++i) {
3480 var tween = queue[i];
3481 if (!tween || !tween.isAnimated()) {
3485 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3487 tween.currentFrame += 1;
3489 if (tween.useSeconds) {
3490 correctFrame(tween);
3492 tween._onTween.fire();
3495 Roo.lib.AnimMgr.stop(tween, i);
3500 var getIndex = function(anim) {
3501 for (var i = 0, len = queue.length; i < len; ++i) {
3502 if (queue[i] == anim) {
3510 var correctFrame = function(tween) {
3511 var frames = tween.totalFrames;
3512 var frame = tween.currentFrame;
3513 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3514 var elapsed = (new Date() - tween.getStartTime());
3517 if (elapsed < tween.duration * 1000) {
3518 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3520 tweak = frames - (frame + 1);
3522 if (tweak > 0 && isFinite(tweak)) {
3523 if (tween.currentFrame + tweak >= frames) {
3524 tweak = frames - (frame + 1);
3527 tween.currentFrame += tweak;
3531 * Portions of this file are based on pieces of Yahoo User Interface Library
3532 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3533 * YUI licensed under the BSD License:
3534 * http://developer.yahoo.net/yui/license.txt
3535 * <script type="text/javascript">
3538 Roo.lib.Bezier = new function() {
3540 this.getPosition = function(points, t) {
3541 var n = points.length;
3544 for (var i = 0; i < n; ++i) {
3545 tmp[i] = [points[i][0], points[i][1]];
3548 for (var j = 1; j < n; ++j) {
3549 for (i = 0; i < n - j; ++i) {
3550 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3551 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3555 return [ tmp[0][0], tmp[0][1] ];
3559 * Portions of this file are based on pieces of Yahoo User Interface Library
3560 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3561 * YUI licensed under the BSD License:
3562 * http://developer.yahoo.net/yui/license.txt
3563 * <script type="text/javascript">
3568 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3569 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3572 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3574 var fly = Roo.lib.AnimBase.fly;
3576 var superclass = Y.ColorAnim.superclass;
3577 var proto = Y.ColorAnim.prototype;
3579 proto.toString = function() {
3580 var el = this.getEl();
3581 var id = el.id || el.tagName;
3582 return ("ColorAnim " + id);
3585 proto.patterns.color = /color$/i;
3586 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3587 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3588 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3589 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3592 proto.parseColor = function(s) {
3593 if (s.length == 3) {
3597 var c = this.patterns.hex.exec(s);
3598 if (c && c.length == 4) {
3599 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3602 c = this.patterns.rgb.exec(s);
3603 if (c && c.length == 4) {
3604 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3607 c = this.patterns.hex3.exec(s);
3608 if (c && c.length == 4) {
3609 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3614 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3615 proto.getAttribute = function(attr) {
3616 var el = this.getEl();
3617 if (this.patterns.color.test(attr)) {
3618 var val = fly(el).getStyle(attr);
3620 if (this.patterns.transparent.test(val)) {
3621 var parent = el.parentNode;
3622 val = fly(parent).getStyle(attr);
3624 while (parent && this.patterns.transparent.test(val)) {
3625 parent = parent.parentNode;
3626 val = fly(parent).getStyle(attr);
3627 if (parent.tagName.toUpperCase() == 'HTML') {
3633 val = superclass.getAttribute.call(this, attr);
3638 proto.getAttribute = function(attr) {
3639 var el = this.getEl();
3640 if (this.patterns.color.test(attr)) {
3641 var val = fly(el).getStyle(attr);
3643 if (this.patterns.transparent.test(val)) {
3644 var parent = el.parentNode;
3645 val = fly(parent).getStyle(attr);
3647 while (parent && this.patterns.transparent.test(val)) {
3648 parent = parent.parentNode;
3649 val = fly(parent).getStyle(attr);
3650 if (parent.tagName.toUpperCase() == 'HTML') {
3656 val = superclass.getAttribute.call(this, attr);
3662 proto.doMethod = function(attr, start, end) {
3665 if (this.patterns.color.test(attr)) {
3667 for (var i = 0, len = start.length; i < len; ++i) {
3668 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3671 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3674 val = superclass.doMethod.call(this, attr, start, end);
3680 proto.setRuntimeAttribute = function(attr) {
3681 superclass.setRuntimeAttribute.call(this, attr);
3683 if (this.patterns.color.test(attr)) {
3684 var attributes = this.attributes;
3685 var start = this.parseColor(this.runtimeAttributes[attr].start);
3686 var end = this.parseColor(this.runtimeAttributes[attr].end);
3688 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3689 end = this.parseColor(attributes[attr].by);
3691 for (var i = 0, len = start.length; i < len; ++i) {
3692 end[i] = start[i] + end[i];
3696 this.runtimeAttributes[attr].start = start;
3697 this.runtimeAttributes[attr].end = end;
3703 * Portions of this file are based on pieces of Yahoo User Interface Library
3704 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3705 * YUI licensed under the BSD License:
3706 * http://developer.yahoo.net/yui/license.txt
3707 * <script type="text/javascript">
3713 easeNone: function (t, b, c, d) {
3714 return c * t / d + b;
3718 easeIn: function (t, b, c, d) {
3719 return c * (t /= d) * t + b;
3723 easeOut: function (t, b, c, d) {
3724 return -c * (t /= d) * (t - 2) + b;
3728 easeBoth: function (t, b, c, d) {
3729 if ((t /= d / 2) < 1) {
3730 return c / 2 * t * t + b;
3733 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3737 easeInStrong: function (t, b, c, d) {
3738 return c * (t /= d) * t * t * t + b;
3742 easeOutStrong: function (t, b, c, d) {
3743 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3747 easeBothStrong: function (t, b, c, d) {
3748 if ((t /= d / 2) < 1) {
3749 return c / 2 * t * t * t * t + b;
3752 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3757 elasticIn: function (t, b, c, d, a, p) {
3761 if ((t /= d) == 1) {
3768 if (!a || a < Math.abs(c)) {
3773 var s = p / (2 * Math.PI) * Math.asin(c / a);
3776 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3780 elasticOut: function (t, b, c, d, a, p) {
3784 if ((t /= d) == 1) {
3791 if (!a || a < Math.abs(c)) {
3796 var s = p / (2 * Math.PI) * Math.asin(c / a);
3799 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3803 elasticBoth: function (t, b, c, d, a, p) {
3808 if ((t /= d / 2) == 2) {
3816 if (!a || a < Math.abs(c)) {
3821 var s = p / (2 * Math.PI) * Math.asin(c / a);
3825 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3826 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3828 return a * Math.pow(2, -10 * (t -= 1)) *
3829 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3834 backIn: function (t, b, c, d, s) {
3835 if (typeof s == 'undefined') {
3838 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3842 backOut: function (t, b, c, d, s) {
3843 if (typeof s == 'undefined') {
3846 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3850 backBoth: function (t, b, c, d, s) {
3851 if (typeof s == 'undefined') {
3855 if ((t /= d / 2 ) < 1) {
3856 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3858 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3862 bounceIn: function (t, b, c, d) {
3863 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3867 bounceOut: function (t, b, c, d) {
3868 if ((t /= d) < (1 / 2.75)) {
3869 return c * (7.5625 * t * t) + b;
3870 } else if (t < (2 / 2.75)) {
3871 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3872 } else if (t < (2.5 / 2.75)) {
3873 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3875 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3879 bounceBoth: function (t, b, c, d) {
3881 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3883 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3886 * Portions of this file are based on pieces of Yahoo User Interface Library
3887 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3888 * YUI licensed under the BSD License:
3889 * http://developer.yahoo.net/yui/license.txt
3890 * <script type="text/javascript">
3894 Roo.lib.Motion = function(el, attributes, duration, method) {
3896 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3900 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3904 var superclass = Y.Motion.superclass;
3905 var proto = Y.Motion.prototype;
3907 proto.toString = function() {
3908 var el = this.getEl();
3909 var id = el.id || el.tagName;
3910 return ("Motion " + id);
3913 proto.patterns.points = /^points$/i;
3915 proto.setAttribute = function(attr, val, unit) {
3916 if (this.patterns.points.test(attr)) {
3917 unit = unit || 'px';
3918 superclass.setAttribute.call(this, 'left', val[0], unit);
3919 superclass.setAttribute.call(this, 'top', val[1], unit);
3921 superclass.setAttribute.call(this, attr, val, unit);
3925 proto.getAttribute = function(attr) {
3926 if (this.patterns.points.test(attr)) {
3928 superclass.getAttribute.call(this, 'left'),
3929 superclass.getAttribute.call(this, 'top')
3932 val = superclass.getAttribute.call(this, attr);
3938 proto.doMethod = function(attr, start, end) {
3941 if (this.patterns.points.test(attr)) {
3942 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3943 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3945 val = superclass.doMethod.call(this, attr, start, end);
3950 proto.setRuntimeAttribute = function(attr) {
3951 if (this.patterns.points.test(attr)) {
3952 var el = this.getEl();
3953 var attributes = this.attributes;
3955 var control = attributes['points']['control'] || [];
3959 if (control.length > 0 && !(control[0] instanceof Array)) {
3960 control = [control];
3963 for (i = 0,len = control.length; i < len; ++i) {
3964 tmp[i] = control[i];
3969 Roo.fly(el).position();
3971 if (isset(attributes['points']['from'])) {
3972 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3975 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3978 start = this.getAttribute('points');
3981 if (isset(attributes['points']['to'])) {
3982 end = translateValues.call(this, attributes['points']['to'], start);
3984 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3985 for (i = 0,len = control.length; i < len; ++i) {
3986 control[i] = translateValues.call(this, control[i], start);
3990 } else if (isset(attributes['points']['by'])) {
3991 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3993 for (i = 0,len = control.length; i < len; ++i) {
3994 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3998 this.runtimeAttributes[attr] = [start];
4000 if (control.length > 0) {
4001 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4004 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4007 superclass.setRuntimeAttribute.call(this, attr);
4011 var translateValues = function(val, start) {
4012 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4013 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4018 var isset = function(prop) {
4019 return (typeof prop !== 'undefined');
4023 * Portions of this file are based on pieces of Yahoo User Interface Library
4024 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4025 * YUI licensed under the BSD License:
4026 * http://developer.yahoo.net/yui/license.txt
4027 * <script type="text/javascript">
4031 Roo.lib.Scroll = function(el, attributes, duration, method) {
4033 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4037 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4041 var superclass = Y.Scroll.superclass;
4042 var proto = Y.Scroll.prototype;
4044 proto.toString = function() {
4045 var el = this.getEl();
4046 var id = el.id || el.tagName;
4047 return ("Scroll " + id);
4050 proto.doMethod = function(attr, start, end) {
4053 if (attr == 'scroll') {
4055 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4056 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4060 val = superclass.doMethod.call(this, attr, start, end);
4065 proto.getAttribute = function(attr) {
4067 var el = this.getEl();
4069 if (attr == 'scroll') {
4070 val = [ el.scrollLeft, el.scrollTop ];
4072 val = superclass.getAttribute.call(this, attr);
4078 proto.setAttribute = function(attr, val, unit) {
4079 var el = this.getEl();
4081 if (attr == 'scroll') {
4082 el.scrollLeft = val[0];
4083 el.scrollTop = val[1];
4085 superclass.setAttribute.call(this, attr, val, unit);
4091 * Ext JS Library 1.1.1
4092 * Copyright(c) 2006-2007, Ext JS, LLC.
4094 * Originally Released Under LGPL - original licence link has changed is not relivant.
4097 * <script type="text/javascript">
4101 // nasty IE9 hack - what a pile of crap that is..
4103 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4104 Range.prototype.createContextualFragment = function (html) {
4105 var doc = window.document;
4106 var container = doc.createElement("div");
4107 container.innerHTML = html;
4108 var frag = doc.createDocumentFragment(), n;
4109 while ((n = container.firstChild)) {
4110 frag.appendChild(n);
4117 * @class Roo.DomHelper
4118 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4119 * 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>.
4122 Roo.DomHelper = function(){
4123 var tempTableEl = null;
4124 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4125 var tableRe = /^table|tbody|tr|td$/i;
4127 // build as innerHTML where available
4129 var createHtml = function(o){
4130 if(typeof o == 'string'){
4139 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4140 if(attr == "style"){
4142 if(typeof s == "function"){
4145 if(typeof s == "string"){
4146 b += ' style="' + s + '"';
4147 }else if(typeof s == "object"){
4150 if(typeof s[key] != "function"){
4151 b += key + ":" + s[key] + ";";
4158 b += ' class="' + o["cls"] + '"';
4159 }else if(attr == "htmlFor"){
4160 b += ' for="' + o["htmlFor"] + '"';
4162 b += " " + attr + '="' + o[attr] + '"';
4166 if(emptyTags.test(o.tag)){
4170 var cn = o.children || o.cn;
4172 //http://bugs.kde.org/show_bug.cgi?id=71506
4173 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4174 for(var i = 0, len = cn.length; i < len; i++) {
4175 b += createHtml(cn[i], b);
4178 b += createHtml(cn, b);
4184 b += "</" + o.tag + ">";
4191 var createDom = function(o, parentNode){
4193 // defininition craeted..
4195 if (o.ns && o.ns != 'html') {
4197 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4198 xmlns[o.ns] = o.xmlns;
4201 if (typeof(xmlns[o.ns]) == 'undefined') {
4202 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4208 if (typeof(o) == 'string') {
4209 return parentNode.appendChild(document.createTextNode(o));
4211 o.tag = o.tag || div;
4212 if (o.ns && Roo.isIE) {
4214 o.tag = o.ns + ':' + o.tag;
4217 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4218 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4221 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4222 attr == "style" || typeof o[attr] == "function") continue;
4224 if(attr=="cls" && Roo.isIE){
4225 el.className = o["cls"];
4227 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4228 else el[attr] = o[attr];
4231 Roo.DomHelper.applyStyles(el, o.style);
4232 var cn = o.children || o.cn;
4234 //http://bugs.kde.org/show_bug.cgi?id=71506
4235 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4236 for(var i = 0, len = cn.length; i < len; i++) {
4237 createDom(cn[i], el);
4244 el.innerHTML = o.html;
4247 parentNode.appendChild(el);
4252 var ieTable = function(depth, s, h, e){
4253 tempTableEl.innerHTML = [s, h, e].join('');
4254 var i = -1, el = tempTableEl;
4261 // kill repeat to save bytes
4265 tbe = '</tbody>'+te,
4271 * Nasty code for IE's broken table implementation
4273 var insertIntoTable = function(tag, where, el, html){
4275 tempTableEl = document.createElement('div');
4280 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4283 if(where == 'beforebegin'){
4287 before = el.nextSibling;
4290 node = ieTable(4, trs, html, tre);
4292 else if(tag == 'tr'){
4293 if(where == 'beforebegin'){
4296 node = ieTable(3, tbs, html, tbe);
4297 } else if(where == 'afterend'){
4298 before = el.nextSibling;
4300 node = ieTable(3, tbs, html, tbe);
4301 } else{ // INTO a TR
4302 if(where == 'afterbegin'){
4303 before = el.firstChild;
4305 node = ieTable(4, trs, html, tre);
4307 } else if(tag == 'tbody'){
4308 if(where == 'beforebegin'){
4311 node = ieTable(2, ts, html, te);
4312 } else if(where == 'afterend'){
4313 before = el.nextSibling;
4315 node = ieTable(2, ts, html, te);
4317 if(where == 'afterbegin'){
4318 before = el.firstChild;
4320 node = ieTable(3, tbs, html, tbe);
4323 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4326 if(where == 'afterbegin'){
4327 before = el.firstChild;
4329 node = ieTable(2, ts, html, te);
4331 el.insertBefore(node, before);
4336 /** True to force the use of DOM instead of html fragments @type Boolean */
4340 * Returns the markup for the passed Element(s) config
4341 * @param {Object} o The Dom object spec (and children)
4344 markup : function(o){
4345 return createHtml(o);
4349 * Applies a style specification to an element
4350 * @param {String/HTMLElement} el The element to apply styles to
4351 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4352 * a function which returns such a specification.
4354 applyStyles : function(el, styles){
4357 if(typeof styles == "string"){
4358 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4360 while ((matches = re.exec(styles)) != null){
4361 el.setStyle(matches[1], matches[2]);
4363 }else if (typeof styles == "object"){
4364 for (var style in styles){
4365 el.setStyle(style, styles[style]);
4367 }else if (typeof styles == "function"){
4368 Roo.DomHelper.applyStyles(el, styles.call());
4374 * Inserts an HTML fragment into the Dom
4375 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4376 * @param {HTMLElement} el The context element
4377 * @param {String} html The HTML fragmenet
4378 * @return {HTMLElement} The new node
4380 insertHtml : function(where, el, html){
4381 where = where.toLowerCase();
4382 if(el.insertAdjacentHTML){
4383 if(tableRe.test(el.tagName)){
4385 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4391 el.insertAdjacentHTML('BeforeBegin', html);
4392 return el.previousSibling;
4394 el.insertAdjacentHTML('AfterBegin', html);
4395 return el.firstChild;
4397 el.insertAdjacentHTML('BeforeEnd', html);
4398 return el.lastChild;
4400 el.insertAdjacentHTML('AfterEnd', html);
4401 return el.nextSibling;
4403 throw 'Illegal insertion point -> "' + where + '"';
4405 var range = el.ownerDocument.createRange();
4409 range.setStartBefore(el);
4410 frag = range.createContextualFragment(html);
4411 el.parentNode.insertBefore(frag, el);
4412 return el.previousSibling;
4415 range.setStartBefore(el.firstChild);
4416 frag = range.createContextualFragment(html);
4417 el.insertBefore(frag, el.firstChild);
4418 return el.firstChild;
4420 el.innerHTML = html;
4421 return el.firstChild;
4425 range.setStartAfter(el.lastChild);
4426 frag = range.createContextualFragment(html);
4427 el.appendChild(frag);
4428 return el.lastChild;
4430 el.innerHTML = html;
4431 return el.lastChild;
4434 range.setStartAfter(el);
4435 frag = range.createContextualFragment(html);
4436 el.parentNode.insertBefore(frag, el.nextSibling);
4437 return el.nextSibling;
4439 throw 'Illegal insertion point -> "' + where + '"';
4443 * Creates new Dom element(s) and inserts them before el
4444 * @param {String/HTMLElement/Element} el The context element
4445 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4446 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4447 * @return {HTMLElement/Roo.Element} The new node
4449 insertBefore : function(el, o, returnElement){
4450 return this.doInsert(el, o, returnElement, "beforeBegin");
4454 * Creates new Dom element(s) and inserts them after el
4455 * @param {String/HTMLElement/Element} el The context element
4456 * @param {Object} o The Dom object spec (and children)
4457 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4458 * @return {HTMLElement/Roo.Element} The new node
4460 insertAfter : function(el, o, returnElement){
4461 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4465 * Creates new Dom element(s) and inserts them as the first child of el
4466 * @param {String/HTMLElement/Element} el The context element
4467 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4468 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4469 * @return {HTMLElement/Roo.Element} The new node
4471 insertFirst : function(el, o, returnElement){
4472 return this.doInsert(el, o, returnElement, "afterBegin");
4476 doInsert : function(el, o, returnElement, pos, sibling){
4477 el = Roo.getDom(el);
4479 if(this.useDom || o.ns){
4480 newNode = createDom(o, null);
4481 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4483 var html = createHtml(o);
4484 newNode = this.insertHtml(pos, el, html);
4486 return returnElement ? Roo.get(newNode, true) : newNode;
4490 * Creates new Dom element(s) and appends them to el
4491 * @param {String/HTMLElement/Element} el The context element
4492 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4493 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4494 * @return {HTMLElement/Roo.Element} The new node
4496 append : function(el, o, returnElement){
4497 el = Roo.getDom(el);
4499 if(this.useDom || o.ns){
4500 newNode = createDom(o, null);
4501 el.appendChild(newNode);
4503 var html = createHtml(o);
4504 newNode = this.insertHtml("beforeEnd", el, html);
4506 return returnElement ? Roo.get(newNode, true) : newNode;
4510 * Creates new Dom element(s) and overwrites the contents of el with them
4511 * @param {String/HTMLElement/Element} el The context element
4512 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4513 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4514 * @return {HTMLElement/Roo.Element} The new node
4516 overwrite : function(el, o, returnElement){
4517 el = Roo.getDom(el);
4520 while (el.childNodes.length) {
4521 el.removeChild(el.firstChild);
4525 el.innerHTML = createHtml(o);
4528 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4532 * Creates a new Roo.DomHelper.Template from the Dom object spec
4533 * @param {Object} o The Dom object spec (and children)
4534 * @return {Roo.DomHelper.Template} The new template
4536 createTemplate : function(o){
4537 var html = createHtml(o);
4538 return new Roo.Template(html);
4544 * Ext JS Library 1.1.1
4545 * Copyright(c) 2006-2007, Ext JS, LLC.
4547 * Originally Released Under LGPL - original licence link has changed is not relivant.
4550 * <script type="text/javascript">
4554 * @class Roo.Template
4555 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4556 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4559 var t = new Roo.Template({
4560 html : '<div name="{id}">' +
4561 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4563 myformat: function (value, allValues) {
4564 return 'XX' + value;
4567 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4569 * For more information see this blog post with examples:
4570 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4571 - Create Elements using DOM, HTML fragments and Templates</a>.
4573 * @param {Object} cfg - Configuration object.
4575 Roo.Template = function(cfg){
4577 if(cfg instanceof Array){
4579 }else if(arguments.length > 1){
4580 cfg = Array.prototype.join.call(arguments, "");
4584 if (typeof(cfg) == 'object') {
4595 Roo.Template.prototype = {
4598 * @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..
4599 * it should be fixed so that template is observable...
4603 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4607 * Returns an HTML fragment of this template with the specified values applied.
4608 * @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'})
4609 * @return {String} The HTML fragment
4611 applyTemplate : function(values){
4615 return this.compiled(values);
4617 var useF = this.disableFormats !== true;
4618 var fm = Roo.util.Format, tpl = this;
4619 var fn = function(m, name, format, args){
4621 if(format.substr(0, 5) == "this."){
4622 return tpl.call(format.substr(5), values[name], values);
4625 // quoted values are required for strings in compiled templates,
4626 // but for non compiled we need to strip them
4627 // quoted reversed for jsmin
4628 var re = /^\s*['"](.*)["']\s*$/;
4629 args = args.split(',');
4630 for(var i = 0, len = args.length; i < len; i++){
4631 args[i] = args[i].replace(re, "$1");
4633 args = [values[name]].concat(args);
4635 args = [values[name]];
4637 return fm[format].apply(fm, args);
4640 return values[name] !== undefined ? values[name] : "";
4643 return this.html.replace(this.re, fn);
4661 this.loading = true;
4662 this.compiled = false;
4664 var cx = new Roo.data.Connection();
4668 success : function (response) {
4670 _t.html = response.responseText;
4674 failure : function(response) {
4675 Roo.log("Template failed to load from " + _t.url);
4682 * Sets the HTML used as the template and optionally compiles it.
4683 * @param {String} html
4684 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4685 * @return {Roo.Template} this
4687 set : function(html, compile){
4689 this.compiled = null;
4697 * True to disable format functions (defaults to false)
4700 disableFormats : false,
4703 * The regular expression used to match template variables
4707 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4710 * Compiles the template into an internal function, eliminating the RegEx overhead.
4711 * @return {Roo.Template} this
4713 compile : function(){
4714 var fm = Roo.util.Format;
4715 var useF = this.disableFormats !== true;
4716 var sep = Roo.isGecko ? "+" : ",";
4717 var fn = function(m, name, format, args){
4719 args = args ? ',' + args : "";
4720 if(format.substr(0, 5) != "this."){
4721 format = "fm." + format + '(';
4723 format = 'this.call("'+ format.substr(5) + '", ';
4727 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4729 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4732 // branched to use + in gecko and [].join() in others
4734 body = "this.compiled = function(values){ return '" +
4735 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4738 body = ["this.compiled = function(values){ return ['"];
4739 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4740 body.push("'].join('');};");
4741 body = body.join('');
4751 // private function used to call members
4752 call : function(fnName, value, allValues){
4753 return this[fnName](value, allValues);
4757 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4758 * @param {String/HTMLElement/Roo.Element} el The context element
4759 * @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'})
4760 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4761 * @return {HTMLElement/Roo.Element} The new node or Element
4763 insertFirst: function(el, values, returnElement){
4764 return this.doInsert('afterBegin', el, values, returnElement);
4768 * Applies the supplied values to the template and inserts the new node(s) before el.
4769 * @param {String/HTMLElement/Roo.Element} el The context element
4770 * @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'})
4771 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4772 * @return {HTMLElement/Roo.Element} The new node or Element
4774 insertBefore: function(el, values, returnElement){
4775 return this.doInsert('beforeBegin', el, values, returnElement);
4779 * Applies the supplied values to the template and inserts the new node(s) after el.
4780 * @param {String/HTMLElement/Roo.Element} el The context element
4781 * @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'})
4782 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4783 * @return {HTMLElement/Roo.Element} The new node or Element
4785 insertAfter : function(el, values, returnElement){
4786 return this.doInsert('afterEnd', el, values, returnElement);
4790 * Applies the supplied values to the template and appends the new node(s) to el.
4791 * @param {String/HTMLElement/Roo.Element} el The context element
4792 * @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'})
4793 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4794 * @return {HTMLElement/Roo.Element} The new node or Element
4796 append : function(el, values, returnElement){
4797 return this.doInsert('beforeEnd', el, values, returnElement);
4800 doInsert : function(where, el, values, returnEl){
4801 el = Roo.getDom(el);
4802 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4803 return returnEl ? Roo.get(newNode, true) : newNode;
4807 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4808 * @param {String/HTMLElement/Roo.Element} el The context element
4809 * @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'})
4810 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4811 * @return {HTMLElement/Roo.Element} The new node or Element
4813 overwrite : function(el, values, returnElement){
4814 el = Roo.getDom(el);
4815 el.innerHTML = this.applyTemplate(values);
4816 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4820 * Alias for {@link #applyTemplate}
4823 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4826 Roo.DomHelper.Template = Roo.Template;
4829 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4830 * @param {String/HTMLElement} el A DOM element or its id
4831 * @returns {Roo.Template} The created template
4834 Roo.Template.from = function(el){
4835 el = Roo.getDom(el);
4836 return new Roo.Template(el.value || el.innerHTML);
4839 * Ext JS Library 1.1.1
4840 * Copyright(c) 2006-2007, Ext JS, LLC.
4842 * Originally Released Under LGPL - original licence link has changed is not relivant.
4845 * <script type="text/javascript">
4850 * This is code is also distributed under MIT license for use
4851 * with jQuery and prototype JavaScript libraries.
4854 * @class Roo.DomQuery
4855 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).
4857 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>
4860 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.
4862 <h4>Element Selectors:</h4>
4864 <li> <b>*</b> any element</li>
4865 <li> <b>E</b> an element with the tag E</li>
4866 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4867 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4868 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4869 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4871 <h4>Attribute Selectors:</h4>
4872 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4874 <li> <b>E[foo]</b> has an attribute "foo"</li>
4875 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4876 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4877 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4878 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4879 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4880 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4882 <h4>Pseudo Classes:</h4>
4884 <li> <b>E:first-child</b> E is the first child of its parent</li>
4885 <li> <b>E:last-child</b> E is the last child of its parent</li>
4886 <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>
4887 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4888 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4889 <li> <b>E:only-child</b> E is the only child of its parent</li>
4890 <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>
4891 <li> <b>E:first</b> the first E in the resultset</li>
4892 <li> <b>E:last</b> the last E in the resultset</li>
4893 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4894 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4895 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4896 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4897 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4898 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4899 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4900 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4901 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4903 <h4>CSS Value Selectors:</h4>
4905 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4906 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4907 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4908 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4909 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4910 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4914 Roo.DomQuery = function(){
4915 var cache = {}, simpleCache = {}, valueCache = {};
4916 var nonSpace = /\S/;
4917 var trimRe = /^\s+|\s+$/g;
4918 var tplRe = /\{(\d+)\}/g;
4919 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4920 var tagTokenRe = /^(#)?([\w-\*]+)/;
4921 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4923 function child(p, index){
4925 var n = p.firstChild;
4927 if(n.nodeType == 1){
4938 while((n = n.nextSibling) && n.nodeType != 1);
4943 while((n = n.previousSibling) && n.nodeType != 1);
4947 function children(d){
4948 var n = d.firstChild, ni = -1;
4950 var nx = n.nextSibling;
4951 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4961 function byClassName(c, a, v){
4965 var r = [], ri = -1, cn;
4966 for(var i = 0, ci; ci = c[i]; i++){
4967 if((' '+ci.className+' ').indexOf(v) != -1){
4974 function attrValue(n, attr){
4975 if(!n.tagName && typeof n.length != "undefined"){
4984 if(attr == "class" || attr == "className"){
4987 return n.getAttribute(attr) || n[attr];
4991 function getNodes(ns, mode, tagName){
4992 var result = [], ri = -1, cs;
4996 tagName = tagName || "*";
4997 if(typeof ns.getElementsByTagName != "undefined"){
5001 for(var i = 0, ni; ni = ns[i]; i++){
5002 cs = ni.getElementsByTagName(tagName);
5003 for(var j = 0, ci; ci = cs[j]; j++){
5007 }else if(mode == "/" || mode == ">"){
5008 var utag = tagName.toUpperCase();
5009 for(var i = 0, ni, cn; ni = ns[i]; i++){
5010 cn = ni.children || ni.childNodes;
5011 for(var j = 0, cj; cj = cn[j]; j++){
5012 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5017 }else if(mode == "+"){
5018 var utag = tagName.toUpperCase();
5019 for(var i = 0, n; n = ns[i]; i++){
5020 while((n = n.nextSibling) && n.nodeType != 1);
5021 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5025 }else if(mode == "~"){
5026 for(var i = 0, n; n = ns[i]; i++){
5027 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5036 function concat(a, b){
5040 for(var i = 0, l = b.length; i < l; i++){
5046 function byTag(cs, tagName){
5047 if(cs.tagName || cs == document){
5053 var r = [], ri = -1;
5054 tagName = tagName.toLowerCase();
5055 for(var i = 0, ci; ci = cs[i]; i++){
5056 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5063 function byId(cs, attr, id){
5064 if(cs.tagName || cs == document){
5070 var r = [], ri = -1;
5071 for(var i = 0,ci; ci = cs[i]; i++){
5072 if(ci && ci.id == id){
5080 function byAttribute(cs, attr, value, op, custom){
5081 var r = [], ri = -1, st = custom=="{";
5082 var f = Roo.DomQuery.operators[op];
5083 for(var i = 0, ci; ci = cs[i]; i++){
5086 a = Roo.DomQuery.getStyle(ci, attr);
5088 else if(attr == "class" || attr == "className"){
5090 }else if(attr == "for"){
5092 }else if(attr == "href"){
5093 a = ci.getAttribute("href", 2);
5095 a = ci.getAttribute(attr);
5097 if((f && f(a, value)) || (!f && a)){
5104 function byPseudo(cs, name, value){
5105 return Roo.DomQuery.pseudos[name](cs, value);
5108 // This is for IE MSXML which does not support expandos.
5109 // IE runs the same speed using setAttribute, however FF slows way down
5110 // and Safari completely fails so they need to continue to use expandos.
5111 var isIE = window.ActiveXObject ? true : false;
5113 // this eval is stop the compressor from
5114 // renaming the variable to something shorter
5116 /** eval:var:batch */
5121 function nodupIEXml(cs){
5123 cs[0].setAttribute("_nodup", d);
5125 for(var i = 1, len = cs.length; i < len; i++){
5127 if(!c.getAttribute("_nodup") != d){
5128 c.setAttribute("_nodup", d);
5132 for(var i = 0, len = cs.length; i < len; i++){
5133 cs[i].removeAttribute("_nodup");
5142 var len = cs.length, c, i, r = cs, cj, ri = -1;
5143 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5146 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5147 return nodupIEXml(cs);
5151 for(i = 1; c = cs[i]; i++){
5156 for(var j = 0; j < i; j++){
5159 for(j = i+1; cj = cs[j]; j++){
5171 function quickDiffIEXml(c1, c2){
5173 for(var i = 0, len = c1.length; i < len; i++){
5174 c1[i].setAttribute("_qdiff", d);
5177 for(var i = 0, len = c2.length; i < len; i++){
5178 if(c2[i].getAttribute("_qdiff") != d){
5179 r[r.length] = c2[i];
5182 for(var i = 0, len = c1.length; i < len; i++){
5183 c1[i].removeAttribute("_qdiff");
5188 function quickDiff(c1, c2){
5189 var len1 = c1.length;
5193 if(isIE && c1[0].selectSingleNode){
5194 return quickDiffIEXml(c1, c2);
5197 for(var i = 0; i < len1; i++){
5201 for(var i = 0, len = c2.length; i < len; i++){
5202 if(c2[i]._qdiff != d){
5203 r[r.length] = c2[i];
5209 function quickId(ns, mode, root, id){
5211 var d = root.ownerDocument || root;
5212 return d.getElementById(id);
5214 ns = getNodes(ns, mode, "*");
5215 return byId(ns, null, id);
5219 getStyle : function(el, name){
5220 return Roo.fly(el).getStyle(name);
5223 * Compiles a selector/xpath query into a reusable function. The returned function
5224 * takes one parameter "root" (optional), which is the context node from where the query should start.
5225 * @param {String} selector The selector/xpath query
5226 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5227 * @return {Function}
5229 compile : function(path, type){
5230 type = type || "select";
5232 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5233 var q = path, mode, lq;
5234 var tk = Roo.DomQuery.matchers;
5235 var tklen = tk.length;
5238 // accept leading mode switch
5239 var lmode = q.match(modeRe);
5240 if(lmode && lmode[1]){
5241 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5242 q = q.replace(lmode[1], "");
5244 // strip leading slashes
5245 while(path.substr(0, 1)=="/"){
5246 path = path.substr(1);
5249 while(q && lq != q){
5251 var tm = q.match(tagTokenRe);
5252 if(type == "select"){
5255 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5257 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5259 q = q.replace(tm[0], "");
5260 }else if(q.substr(0, 1) != '@'){
5261 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5266 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5268 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5270 q = q.replace(tm[0], "");
5273 while(!(mm = q.match(modeRe))){
5274 var matched = false;
5275 for(var j = 0; j < tklen; j++){
5277 var m = q.match(t.re);
5279 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5282 q = q.replace(m[0], "");
5287 // prevent infinite loop on bad selector
5289 throw 'Error parsing selector, parsing failed at "' + q + '"';
5293 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5294 q = q.replace(mm[1], "");
5297 fn[fn.length] = "return nodup(n);\n}";
5300 * list of variables that need from compression as they are used by eval.
5310 * eval:var:byClassName
5312 * eval:var:byAttribute
5313 * eval:var:attrValue
5321 * Selects a group of elements.
5322 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5323 * @param {Node} root (optional) The start of the query (defaults to document).
5326 select : function(path, root, type){
5327 if(!root || root == document){
5330 if(typeof root == "string"){
5331 root = document.getElementById(root);
5333 var paths = path.split(",");
5335 for(var i = 0, len = paths.length; i < len; i++){
5336 var p = paths[i].replace(trimRe, "");
5338 cache[p] = Roo.DomQuery.compile(p);
5340 throw p + " is not a valid selector";
5343 var result = cache[p](root);
5344 if(result && result != document){
5345 results = results.concat(result);
5348 if(paths.length > 1){
5349 return nodup(results);
5355 * Selects a single element.
5356 * @param {String} selector The selector/xpath query
5357 * @param {Node} root (optional) The start of the query (defaults to document).
5360 selectNode : function(path, root){
5361 return Roo.DomQuery.select(path, root)[0];
5365 * Selects the value of a node, optionally replacing null with the defaultValue.
5366 * @param {String} selector The selector/xpath query
5367 * @param {Node} root (optional) The start of the query (defaults to document).
5368 * @param {String} defaultValue
5370 selectValue : function(path, root, defaultValue){
5371 path = path.replace(trimRe, "");
5372 if(!valueCache[path]){
5373 valueCache[path] = Roo.DomQuery.compile(path, "select");
5375 var n = valueCache[path](root);
5376 n = n[0] ? n[0] : n;
5377 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5378 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5382 * Selects the value of a node, parsing integers and floats.
5383 * @param {String} selector The selector/xpath query
5384 * @param {Node} root (optional) The start of the query (defaults to document).
5385 * @param {Number} defaultValue
5388 selectNumber : function(path, root, defaultValue){
5389 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5390 return parseFloat(v);
5394 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5395 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5396 * @param {String} selector The simple selector to test
5399 is : function(el, ss){
5400 if(typeof el == "string"){
5401 el = document.getElementById(el);
5403 var isArray = (el instanceof Array);
5404 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5405 return isArray ? (result.length == el.length) : (result.length > 0);
5409 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5410 * @param {Array} el An array of elements to filter
5411 * @param {String} selector The simple selector to test
5412 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5413 * the selector instead of the ones that match
5416 filter : function(els, ss, nonMatches){
5417 ss = ss.replace(trimRe, "");
5418 if(!simpleCache[ss]){
5419 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5421 var result = simpleCache[ss](els);
5422 return nonMatches ? quickDiff(result, els) : result;
5426 * Collection of matching regular expressions and code snippets.
5430 select: 'n = byClassName(n, null, " {1} ");'
5432 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5433 select: 'n = byPseudo(n, "{1}", "{2}");'
5435 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5436 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5439 select: 'n = byId(n, null, "{1}");'
5442 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5447 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5448 * 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, > <.
5451 "=" : function(a, v){
5454 "!=" : function(a, v){
5457 "^=" : function(a, v){
5458 return a && a.substr(0, v.length) == v;
5460 "$=" : function(a, v){
5461 return a && a.substr(a.length-v.length) == v;
5463 "*=" : function(a, v){
5464 return a && a.indexOf(v) !== -1;
5466 "%=" : function(a, v){
5467 return (a % v) == 0;
5469 "|=" : function(a, v){
5470 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5472 "~=" : function(a, v){
5473 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5478 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5479 * and the argument (if any) supplied in the selector.
5482 "first-child" : function(c){
5483 var r = [], ri = -1, n;
5484 for(var i = 0, ci; ci = n = c[i]; i++){
5485 while((n = n.previousSibling) && n.nodeType != 1);
5493 "last-child" : function(c){
5494 var r = [], ri = -1, n;
5495 for(var i = 0, ci; ci = n = c[i]; i++){
5496 while((n = n.nextSibling) && n.nodeType != 1);
5504 "nth-child" : function(c, a) {
5505 var r = [], ri = -1;
5506 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5507 var f = (m[1] || 1) - 0, l = m[2] - 0;
5508 for(var i = 0, n; n = c[i]; i++){
5509 var pn = n.parentNode;
5510 if (batch != pn._batch) {
5512 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5513 if(cn.nodeType == 1){
5520 if (l == 0 || n.nodeIndex == l){
5523 } else if ((n.nodeIndex + l) % f == 0){
5531 "only-child" : function(c){
5532 var r = [], ri = -1;;
5533 for(var i = 0, ci; ci = c[i]; i++){
5534 if(!prev(ci) && !next(ci)){
5541 "empty" : function(c){
5542 var r = [], ri = -1;
5543 for(var i = 0, ci; ci = c[i]; i++){
5544 var cns = ci.childNodes, j = 0, cn, empty = true;
5547 if(cn.nodeType == 1 || cn.nodeType == 3){
5559 "contains" : function(c, v){
5560 var r = [], ri = -1;
5561 for(var i = 0, ci; ci = c[i]; i++){
5562 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5569 "nodeValue" : function(c, v){
5570 var r = [], ri = -1;
5571 for(var i = 0, ci; ci = c[i]; i++){
5572 if(ci.firstChild && ci.firstChild.nodeValue == v){
5579 "checked" : function(c){
5580 var r = [], ri = -1;
5581 for(var i = 0, ci; ci = c[i]; i++){
5582 if(ci.checked == true){
5589 "not" : function(c, ss){
5590 return Roo.DomQuery.filter(c, ss, true);
5593 "odd" : function(c){
5594 return this["nth-child"](c, "odd");
5597 "even" : function(c){
5598 return this["nth-child"](c, "even");
5601 "nth" : function(c, a){
5602 return c[a-1] || [];
5605 "first" : function(c){
5609 "last" : function(c){
5610 return c[c.length-1] || [];
5613 "has" : function(c, ss){
5614 var s = Roo.DomQuery.select;
5615 var r = [], ri = -1;
5616 for(var i = 0, ci; ci = c[i]; i++){
5617 if(s(ss, ci).length > 0){
5624 "next" : function(c, ss){
5625 var is = Roo.DomQuery.is;
5626 var r = [], ri = -1;
5627 for(var i = 0, ci; ci = c[i]; i++){
5636 "prev" : function(c, ss){
5637 var is = Roo.DomQuery.is;
5638 var r = [], ri = -1;
5639 for(var i = 0, ci; ci = c[i]; i++){
5652 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5653 * @param {String} path The selector/xpath query
5654 * @param {Node} root (optional) The start of the query (defaults to document).
5659 Roo.query = Roo.DomQuery.select;
5662 * Ext JS Library 1.1.1
5663 * Copyright(c) 2006-2007, Ext JS, LLC.
5665 * Originally Released Under LGPL - original licence link has changed is not relivant.
5668 * <script type="text/javascript">
5672 * @class Roo.util.Observable
5673 * Base class that provides a common interface for publishing events. Subclasses are expected to
5674 * to have a property "events" with all the events defined.<br>
5677 Employee = function(name){
5684 Roo.extend(Employee, Roo.util.Observable);
5686 * @param {Object} config properties to use (incuding events / listeners)
5689 Roo.util.Observable = function(cfg){
5692 this.addEvents(cfg.events || {});
5694 delete cfg.events; // make sure
5697 Roo.apply(this, cfg);
5700 this.on(this.listeners);
5701 delete this.listeners;
5704 Roo.util.Observable.prototype = {
5706 * @cfg {Object} listeners list of events and functions to call for this object,
5710 'click' : function(e) {
5720 * Fires the specified event with the passed parameters (minus the event name).
5721 * @param {String} eventName
5722 * @param {Object...} args Variable number of parameters are passed to handlers
5723 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5725 fireEvent : function(){
5726 var ce = this.events[arguments[0].toLowerCase()];
5727 if(typeof ce == "object"){
5728 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5735 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5738 * Appends an event handler to this component
5739 * @param {String} eventName The type of event to listen for
5740 * @param {Function} handler The method the event invokes
5741 * @param {Object} scope (optional) The scope in which to execute the handler
5742 * function. The handler function's "this" context.
5743 * @param {Object} options (optional) An object containing handler configuration
5744 * properties. This may contain any of the following properties:<ul>
5745 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5746 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5747 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5748 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5749 * by the specified number of milliseconds. If the event fires again within that time, the original
5750 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5753 * <b>Combining Options</b><br>
5754 * Using the options argument, it is possible to combine different types of listeners:<br>
5756 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5758 el.on('click', this.onClick, this, {
5765 * <b>Attaching multiple handlers in 1 call</b><br>
5766 * The method also allows for a single argument to be passed which is a config object containing properties
5767 * which specify multiple handlers.
5776 fn: this.onMouseOver,
5780 fn: this.onMouseOut,
5786 * Or a shorthand syntax which passes the same scope object to all handlers:
5789 'click': this.onClick,
5790 'mouseover': this.onMouseOver,
5791 'mouseout': this.onMouseOut,
5796 addListener : function(eventName, fn, scope, o){
5797 if(typeof eventName == "object"){
5800 if(this.filterOptRe.test(e)){
5803 if(typeof o[e] == "function"){
5805 this.addListener(e, o[e], o.scope, o);
5807 // individual options
5808 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5813 o = (!o || typeof o == "boolean") ? {} : o;
5814 eventName = eventName.toLowerCase();
5815 var ce = this.events[eventName] || true;
5816 if(typeof ce == "boolean"){
5817 ce = new Roo.util.Event(this, eventName);
5818 this.events[eventName] = ce;
5820 ce.addListener(fn, scope, o);
5824 * Removes a listener
5825 * @param {String} eventName The type of event to listen for
5826 * @param {Function} handler The handler to remove
5827 * @param {Object} scope (optional) The scope (this object) for the handler
5829 removeListener : function(eventName, fn, scope){
5830 var ce = this.events[eventName.toLowerCase()];
5831 if(typeof ce == "object"){
5832 ce.removeListener(fn, scope);
5837 * Removes all listeners for this object
5839 purgeListeners : function(){
5840 for(var evt in this.events){
5841 if(typeof this.events[evt] == "object"){
5842 this.events[evt].clearListeners();
5847 relayEvents : function(o, events){
5848 var createHandler = function(ename){
5850 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5853 for(var i = 0, len = events.length; i < len; i++){
5854 var ename = events[i];
5855 if(!this.events[ename]){ this.events[ename] = true; };
5856 o.on(ename, createHandler(ename), this);
5861 * Used to define events on this Observable
5862 * @param {Object} object The object with the events defined
5864 addEvents : function(o){
5868 Roo.applyIf(this.events, o);
5872 * Checks to see if this object has any listeners for a specified event
5873 * @param {String} eventName The name of the event to check for
5874 * @return {Boolean} True if the event is being listened for, else false
5876 hasListener : function(eventName){
5877 var e = this.events[eventName];
5878 return typeof e == "object" && e.listeners.length > 0;
5882 * Appends an event handler to this element (shorthand for addListener)
5883 * @param {String} eventName The type of event to listen for
5884 * @param {Function} handler The method the event invokes
5885 * @param {Object} scope (optional) The scope in which to execute the handler
5886 * function. The handler function's "this" context.
5887 * @param {Object} options (optional)
5890 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5892 * Removes a listener (shorthand for removeListener)
5893 * @param {String} eventName The type of event to listen for
5894 * @param {Function} handler The handler to remove
5895 * @param {Object} scope (optional) The scope (this object) for the handler
5898 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5901 * Starts capture on the specified Observable. All events will be passed
5902 * to the supplied function with the event name + standard signature of the event
5903 * <b>before</b> the event is fired. If the supplied function returns false,
5904 * the event will not fire.
5905 * @param {Observable} o The Observable to capture
5906 * @param {Function} fn The function to call
5907 * @param {Object} scope (optional) The scope (this object) for the fn
5910 Roo.util.Observable.capture = function(o, fn, scope){
5911 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5915 * Removes <b>all</b> added captures from the Observable.
5916 * @param {Observable} o The Observable to release
5919 Roo.util.Observable.releaseCapture = function(o){
5920 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5925 var createBuffered = function(h, o, scope){
5926 var task = new Roo.util.DelayedTask();
5928 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5932 var createSingle = function(h, e, fn, scope){
5934 e.removeListener(fn, scope);
5935 return h.apply(scope, arguments);
5939 var createDelayed = function(h, o, scope){
5941 var args = Array.prototype.slice.call(arguments, 0);
5942 setTimeout(function(){
5943 h.apply(scope, args);
5948 Roo.util.Event = function(obj, name){
5951 this.listeners = [];
5954 Roo.util.Event.prototype = {
5955 addListener : function(fn, scope, options){
5956 var o = options || {};
5957 scope = scope || this.obj;
5958 if(!this.isListening(fn, scope)){
5959 var l = {fn: fn, scope: scope, options: o};
5962 h = createDelayed(h, o, scope);
5965 h = createSingle(h, this, fn, scope);
5968 h = createBuffered(h, o, scope);
5971 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5972 this.listeners.push(l);
5974 this.listeners = this.listeners.slice(0);
5975 this.listeners.push(l);
5980 findListener : function(fn, scope){
5981 scope = scope || this.obj;
5982 var ls = this.listeners;
5983 for(var i = 0, len = ls.length; i < len; i++){
5985 if(l.fn == fn && l.scope == scope){
5992 isListening : function(fn, scope){
5993 return this.findListener(fn, scope) != -1;
5996 removeListener : function(fn, scope){
5998 if((index = this.findListener(fn, scope)) != -1){
6000 this.listeners.splice(index, 1);
6002 this.listeners = this.listeners.slice(0);
6003 this.listeners.splice(index, 1);
6010 clearListeners : function(){
6011 this.listeners = [];
6015 var ls = this.listeners, scope, len = ls.length;
6018 var args = Array.prototype.slice.call(arguments, 0);
6019 for(var i = 0; i < len; i++){
6021 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6022 this.firing = false;
6026 this.firing = false;
6033 * Ext JS Library 1.1.1
6034 * Copyright(c) 2006-2007, Ext JS, LLC.
6036 * Originally Released Under LGPL - original licence link has changed is not relivant.
6039 * <script type="text/javascript">
6043 * @class Roo.EventManager
6044 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6045 * several useful events directly.
6046 * See {@link Roo.EventObject} for more details on normalized event objects.
6049 Roo.EventManager = function(){
6050 var docReadyEvent, docReadyProcId, docReadyState = false;
6051 var resizeEvent, resizeTask, textEvent, textSize;
6052 var E = Roo.lib.Event;
6053 var D = Roo.lib.Dom;
6056 var fireDocReady = function(){
6058 docReadyState = true;
6061 clearInterval(docReadyProcId);
6063 if(Roo.isGecko || Roo.isOpera) {
6064 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6067 var defer = document.getElementById("ie-deferred-loader");
6069 defer.onreadystatechange = null;
6070 defer.parentNode.removeChild(defer);
6074 docReadyEvent.fire();
6075 docReadyEvent.clearListeners();
6080 var initDocReady = function(){
6081 docReadyEvent = new Roo.util.Event();
6082 if(Roo.isGecko || Roo.isOpera) {
6083 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6085 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6086 var defer = document.getElementById("ie-deferred-loader");
6087 defer.onreadystatechange = function(){
6088 if(this.readyState == "complete"){
6092 }else if(Roo.isSafari){
6093 docReadyProcId = setInterval(function(){
6094 var rs = document.readyState;
6095 if(rs == "complete") {
6100 // no matter what, make sure it fires on load
6101 E.on(window, "load", fireDocReady);
6104 var createBuffered = function(h, o){
6105 var task = new Roo.util.DelayedTask(h);
6107 // create new event object impl so new events don't wipe out properties
6108 e = new Roo.EventObjectImpl(e);
6109 task.delay(o.buffer, h, null, [e]);
6113 var createSingle = function(h, el, ename, fn){
6115 Roo.EventManager.removeListener(el, ename, fn);
6120 var createDelayed = function(h, o){
6122 // create new event object impl so new events don't wipe out properties
6123 e = new Roo.EventObjectImpl(e);
6124 setTimeout(function(){
6130 var listen = function(element, ename, opt, fn, scope){
6131 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6132 fn = fn || o.fn; scope = scope || o.scope;
6133 var el = Roo.getDom(element);
6135 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6137 var h = function(e){
6138 e = Roo.EventObject.setEvent(e);
6141 t = e.getTarget(o.delegate, el);
6148 if(o.stopEvent === true){
6151 if(o.preventDefault === true){
6154 if(o.stopPropagation === true){
6155 e.stopPropagation();
6158 if(o.normalized === false){
6162 fn.call(scope || el, e, t, o);
6165 h = createDelayed(h, o);
6168 h = createSingle(h, el, ename, fn);
6171 h = createBuffered(h, o);
6173 fn._handlers = fn._handlers || [];
6174 fn._handlers.push([Roo.id(el), ename, h]);
6177 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6178 el.addEventListener("DOMMouseScroll", h, false);
6179 E.on(window, 'unload', function(){
6180 el.removeEventListener("DOMMouseScroll", h, false);
6183 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6184 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6189 var stopListening = function(el, ename, fn){
6190 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6192 for(var i = 0, len = hds.length; i < len; i++){
6194 if(h[0] == id && h[1] == ename){
6201 E.un(el, ename, hd);
6202 el = Roo.getDom(el);
6203 if(ename == "mousewheel" && el.addEventListener){
6204 el.removeEventListener("DOMMouseScroll", hd, false);
6206 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6207 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6211 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6218 * @scope Roo.EventManager
6223 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6224 * object with a Roo.EventObject
6225 * @param {Function} fn The method the event invokes
6226 * @param {Object} scope An object that becomes the scope of the handler
6227 * @param {boolean} override If true, the obj passed in becomes
6228 * the execution scope of the listener
6229 * @return {Function} The wrapped function
6232 wrap : function(fn, scope, override){
6234 Roo.EventObject.setEvent(e);
6235 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6240 * Appends an event handler to an element (shorthand for addListener)
6241 * @param {String/HTMLElement} element The html element or id to assign the
6242 * @param {String} eventName The type of event to listen for
6243 * @param {Function} handler The method the event invokes
6244 * @param {Object} scope (optional) The scope in which to execute the handler
6245 * function. The handler function's "this" context.
6246 * @param {Object} options (optional) An object containing handler configuration
6247 * properties. This may contain any of the following properties:<ul>
6248 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6249 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6250 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6251 * <li>preventDefault {Boolean} True to prevent the default action</li>
6252 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6253 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6254 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6255 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6256 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6257 * by the specified number of milliseconds. If the event fires again within that time, the original
6258 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6261 * <b>Combining Options</b><br>
6262 * Using the options argument, it is possible to combine different types of listeners:<br>
6264 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6266 el.on('click', this.onClick, this, {
6273 * <b>Attaching multiple handlers in 1 call</b><br>
6274 * The method also allows for a single argument to be passed which is a config object containing properties
6275 * which specify multiple handlers.
6285 fn: this.onMouseOver
6294 * Or a shorthand syntax:<br>
6297 'click' : this.onClick,
6298 'mouseover' : this.onMouseOver,
6299 'mouseout' : this.onMouseOut
6303 addListener : function(element, eventName, fn, scope, options){
6304 if(typeof eventName == "object"){
6310 if(typeof o[e] == "function"){
6312 listen(element, e, o, o[e], o.scope);
6314 // individual options
6315 listen(element, e, o[e]);
6320 return listen(element, eventName, options, fn, scope);
6324 * Removes an event handler
6326 * @param {String/HTMLElement} element The id or html element to remove the
6328 * @param {String} eventName The type of event
6329 * @param {Function} fn
6330 * @return {Boolean} True if a listener was actually removed
6332 removeListener : function(element, eventName, fn){
6333 return stopListening(element, eventName, fn);
6337 * Fires when the document is ready (before onload and before images are loaded). Can be
6338 * accessed shorthanded Roo.onReady().
6339 * @param {Function} fn The method the event invokes
6340 * @param {Object} scope An object that becomes the scope of the handler
6341 * @param {boolean} options
6343 onDocumentReady : function(fn, scope, options){
6344 if(docReadyState){ // if it already fired
6345 docReadyEvent.addListener(fn, scope, options);
6346 docReadyEvent.fire();
6347 docReadyEvent.clearListeners();
6353 docReadyEvent.addListener(fn, scope, options);
6357 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6358 * @param {Function} fn The method the event invokes
6359 * @param {Object} scope An object that becomes the scope of the handler
6360 * @param {boolean} options
6362 onWindowResize : function(fn, scope, options){
6364 resizeEvent = new Roo.util.Event();
6365 resizeTask = new Roo.util.DelayedTask(function(){
6366 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6368 E.on(window, "resize", function(){
6370 resizeTask.delay(50);
6372 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6376 resizeEvent.addListener(fn, scope, options);
6380 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6381 * @param {Function} fn The method the event invokes
6382 * @param {Object} scope An object that becomes the scope of the handler
6383 * @param {boolean} options
6385 onTextResize : function(fn, scope, options){
6387 textEvent = new Roo.util.Event();
6388 var textEl = new Roo.Element(document.createElement('div'));
6389 textEl.dom.className = 'x-text-resize';
6390 textEl.dom.innerHTML = 'X';
6391 textEl.appendTo(document.body);
6392 textSize = textEl.dom.offsetHeight;
6393 setInterval(function(){
6394 if(textEl.dom.offsetHeight != textSize){
6395 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6397 }, this.textResizeInterval);
6399 textEvent.addListener(fn, scope, options);
6403 * Removes the passed window resize listener.
6404 * @param {Function} fn The method the event invokes
6405 * @param {Object} scope The scope of handler
6407 removeResizeListener : function(fn, scope){
6409 resizeEvent.removeListener(fn, scope);
6414 fireResize : function(){
6416 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6420 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6424 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6426 textResizeInterval : 50
6431 * @scopeAlias pub=Roo.EventManager
6435 * Appends an event handler to an element (shorthand for addListener)
6436 * @param {String/HTMLElement} element The html element or id to assign the
6437 * @param {String} eventName The type of event to listen for
6438 * @param {Function} handler The method the event invokes
6439 * @param {Object} scope (optional) The scope in which to execute the handler
6440 * function. The handler function's "this" context.
6441 * @param {Object} options (optional) An object containing handler configuration
6442 * properties. This may contain any of the following properties:<ul>
6443 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6444 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6445 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6446 * <li>preventDefault {Boolean} True to prevent the default action</li>
6447 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6448 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6449 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6450 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6451 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6452 * by the specified number of milliseconds. If the event fires again within that time, the original
6453 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6456 * <b>Combining Options</b><br>
6457 * Using the options argument, it is possible to combine different types of listeners:<br>
6459 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6461 el.on('click', this.onClick, this, {
6468 * <b>Attaching multiple handlers in 1 call</b><br>
6469 * The method also allows for a single argument to be passed which is a config object containing properties
6470 * which specify multiple handlers.
6480 fn: this.onMouseOver
6489 * Or a shorthand syntax:<br>
6492 'click' : this.onClick,
6493 'mouseover' : this.onMouseOver,
6494 'mouseout' : this.onMouseOut
6498 pub.on = pub.addListener;
6499 pub.un = pub.removeListener;
6501 pub.stoppedMouseDownEvent = new Roo.util.Event();
6505 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6506 * @param {Function} fn The method the event invokes
6507 * @param {Object} scope An object that becomes the scope of the handler
6508 * @param {boolean} override If true, the obj passed in becomes
6509 * the execution scope of the listener
6513 Roo.onReady = Roo.EventManager.onDocumentReady;
6515 Roo.onReady(function(){
6516 var bd = Roo.get(document.body);
6521 : Roo.isGecko ? "roo-gecko"
6522 : Roo.isOpera ? "roo-opera"
6523 : Roo.isSafari ? "roo-safari" : ""];
6526 cls.push("roo-mac");
6529 cls.push("roo-linux");
6531 if(Roo.isBorderBox){
6532 cls.push('roo-border-box');
6534 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6535 var p = bd.dom.parentNode;
6537 p.className += ' roo-strict';
6540 bd.addClass(cls.join(' '));
6544 * @class Roo.EventObject
6545 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6546 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6549 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6551 var target = e.getTarget();
6554 var myDiv = Roo.get("myDiv");
6555 myDiv.on("click", handleClick);
6557 Roo.EventManager.on("myDiv", 'click', handleClick);
6558 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6562 Roo.EventObject = function(){
6564 var E = Roo.lib.Event;
6566 // safari keypress events for special keys return bad keycodes
6569 63235 : 39, // right
6572 63276 : 33, // page up
6573 63277 : 34, // page down
6574 63272 : 46, // delete
6579 // normalize button clicks
6580 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6581 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6583 Roo.EventObjectImpl = function(e){
6585 this.setEvent(e.browserEvent || e);
6588 Roo.EventObjectImpl.prototype = {
6590 * Used to fix doc tools.
6591 * @scope Roo.EventObject.prototype
6597 /** The normal browser event */
6598 browserEvent : null,
6599 /** The button pressed in a mouse event */
6601 /** True if the shift key was down during the event */
6603 /** True if the control key was down during the event */
6605 /** True if the alt key was down during the event */
6664 setEvent : function(e){
6665 if(e == this || (e && e.browserEvent)){ // already wrapped
6668 this.browserEvent = e;
6670 // normalize buttons
6671 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6672 if(e.type == 'click' && this.button == -1){
6676 this.shiftKey = e.shiftKey;
6677 // mac metaKey behaves like ctrlKey
6678 this.ctrlKey = e.ctrlKey || e.metaKey;
6679 this.altKey = e.altKey;
6680 // in getKey these will be normalized for the mac
6681 this.keyCode = e.keyCode;
6682 // keyup warnings on firefox.
6683 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6684 // cache the target for the delayed and or buffered events
6685 this.target = E.getTarget(e);
6687 this.xy = E.getXY(e);
6690 this.shiftKey = false;
6691 this.ctrlKey = false;
6692 this.altKey = false;
6702 * Stop the event (preventDefault and stopPropagation)
6704 stopEvent : function(){
6705 if(this.browserEvent){
6706 if(this.browserEvent.type == 'mousedown'){
6707 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6709 E.stopEvent(this.browserEvent);
6714 * Prevents the browsers default handling of the event.
6716 preventDefault : function(){
6717 if(this.browserEvent){
6718 E.preventDefault(this.browserEvent);
6723 isNavKeyPress : function(){
6724 var k = this.keyCode;
6725 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6726 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6729 isSpecialKey : function(){
6730 var k = this.keyCode;
6731 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6732 (k == 16) || (k == 17) ||
6733 (k >= 18 && k <= 20) ||
6734 (k >= 33 && k <= 35) ||
6735 (k >= 36 && k <= 39) ||
6736 (k >= 44 && k <= 45);
6739 * Cancels bubbling of the event.
6741 stopPropagation : function(){
6742 if(this.browserEvent){
6743 if(this.type == 'mousedown'){
6744 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6746 E.stopPropagation(this.browserEvent);
6751 * Gets the key code for the event.
6754 getCharCode : function(){
6755 return this.charCode || this.keyCode;
6759 * Returns a normalized keyCode for the event.
6760 * @return {Number} The key code
6762 getKey : function(){
6763 var k = this.keyCode || this.charCode;
6764 return Roo.isSafari ? (safariKeys[k] || k) : k;
6768 * Gets the x coordinate of the event.
6771 getPageX : function(){
6776 * Gets the y coordinate of the event.
6779 getPageY : function(){
6784 * Gets the time of the event.
6787 getTime : function(){
6788 if(this.browserEvent){
6789 return E.getTime(this.browserEvent);
6795 * Gets the page coordinates of the event.
6796 * @return {Array} The xy values like [x, y]
6803 * Gets the target for the event.
6804 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6805 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6806 search as a number or element (defaults to 10 || document.body)
6807 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6808 * @return {HTMLelement}
6810 getTarget : function(selector, maxDepth, returnEl){
6811 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6814 * Gets the related target.
6815 * @return {HTMLElement}
6817 getRelatedTarget : function(){
6818 if(this.browserEvent){
6819 return E.getRelatedTarget(this.browserEvent);
6825 * Normalizes mouse wheel delta across browsers
6826 * @return {Number} The delta
6828 getWheelDelta : function(){
6829 var e = this.browserEvent;
6831 if(e.wheelDelta){ /* IE/Opera. */
6832 delta = e.wheelDelta/120;
6833 }else if(e.detail){ /* Mozilla case. */
6834 delta = -e.detail/3;
6840 * Returns true if the control, meta, shift or alt key was pressed during this event.
6843 hasModifier : function(){
6844 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6848 * Returns true if the target of this event equals el or is a child of el
6849 * @param {String/HTMLElement/Element} el
6850 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6853 within : function(el, related){
6854 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6855 return t && Roo.fly(el).contains(t);
6858 getPoint : function(){
6859 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6863 return new Roo.EventObjectImpl();
6868 * Ext JS Library 1.1.1
6869 * Copyright(c) 2006-2007, Ext JS, LLC.
6871 * Originally Released Under LGPL - original licence link has changed is not relivant.
6874 * <script type="text/javascript">
6878 // was in Composite Element!??!?!
6881 var D = Roo.lib.Dom;
6882 var E = Roo.lib.Event;
6883 var A = Roo.lib.Anim;
6885 // local style camelizing for speed
6887 var camelRe = /(-[a-z])/gi;
6888 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6889 var view = document.defaultView;
6892 * @class Roo.Element
6893 * Represents an Element in the DOM.<br><br>
6896 var el = Roo.get("my-div");
6899 var el = getEl("my-div");
6901 // or with a DOM element
6902 var el = Roo.get(myDivElement);
6904 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6905 * each call instead of constructing a new one.<br><br>
6906 * <b>Animations</b><br />
6907 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6908 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6910 Option Default Description
6911 --------- -------- ---------------------------------------------
6912 duration .35 The duration of the animation in seconds
6913 easing easeOut The YUI easing method
6914 callback none A function to execute when the anim completes
6915 scope this The scope (this) of the callback function
6917 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6918 * manipulate the animation. Here's an example:
6920 var el = Roo.get("my-div");
6925 // default animation
6926 el.setWidth(100, true);
6928 // animation with some options set
6935 // using the "anim" property to get the Anim object
6941 el.setWidth(100, opt);
6943 if(opt.anim.isAnimated()){
6947 * <b> Composite (Collections of) Elements</b><br />
6948 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6949 * @constructor Create a new Element directly.
6950 * @param {String/HTMLElement} element
6951 * @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).
6953 Roo.Element = function(element, forceNew){
6954 var dom = typeof element == "string" ?
6955 document.getElementById(element) : element;
6956 if(!dom){ // invalid id/element
6960 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6961 return Roo.Element.cache[id];
6971 * The DOM element ID
6974 this.id = id || Roo.id(dom);
6977 var El = Roo.Element;
6981 * The element's default display mode (defaults to "")
6984 originalDisplay : "",
6988 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6993 * Sets the element's visibility mode. When setVisible() is called it
6994 * will use this to determine whether to set the visibility or the display property.
6995 * @param visMode Element.VISIBILITY or Element.DISPLAY
6996 * @return {Roo.Element} this
6998 setVisibilityMode : function(visMode){
6999 this.visibilityMode = visMode;
7003 * Convenience method for setVisibilityMode(Element.DISPLAY)
7004 * @param {String} display (optional) What to set display to when visible
7005 * @return {Roo.Element} this
7007 enableDisplayMode : function(display){
7008 this.setVisibilityMode(El.DISPLAY);
7009 if(typeof display != "undefined") this.originalDisplay = display;
7014 * 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)
7015 * @param {String} selector The simple selector to test
7016 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7017 search as a number or element (defaults to 10 || document.body)
7018 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7019 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7021 findParent : function(simpleSelector, maxDepth, returnEl){
7022 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7023 maxDepth = maxDepth || 50;
7024 if(typeof maxDepth != "number"){
7025 stopEl = Roo.getDom(maxDepth);
7028 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7029 if(dq.is(p, simpleSelector)){
7030 return returnEl ? Roo.get(p) : p;
7040 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7041 * @param {String} selector The simple selector to test
7042 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7043 search as a number or element (defaults to 10 || document.body)
7044 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7045 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7047 findParentNode : function(simpleSelector, maxDepth, returnEl){
7048 var p = Roo.fly(this.dom.parentNode, '_internal');
7049 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7053 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7054 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7055 * @param {String} selector The simple selector to test
7056 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7057 search as a number or element (defaults to 10 || document.body)
7058 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7060 up : function(simpleSelector, maxDepth){
7061 return this.findParentNode(simpleSelector, maxDepth, true);
7067 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7068 * @param {String} selector The simple selector to test
7069 * @return {Boolean} True if this element matches the selector, else false
7071 is : function(simpleSelector){
7072 return Roo.DomQuery.is(this.dom, simpleSelector);
7076 * Perform animation on this element.
7077 * @param {Object} args The YUI animation control args
7078 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7079 * @param {Function} onComplete (optional) Function to call when animation completes
7080 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7081 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7082 * @return {Roo.Element} this
7084 animate : function(args, duration, onComplete, easing, animType){
7085 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7090 * @private Internal animation call
7092 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7093 animType = animType || 'run';
7095 var anim = Roo.lib.Anim[animType](
7097 (opt.duration || defaultDur) || .35,
7098 (opt.easing || defaultEase) || 'easeOut',
7100 Roo.callback(cb, this);
7101 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7109 // private legacy anim prep
7110 preanim : function(a, i){
7111 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7115 * Removes worthless text nodes
7116 * @param {Boolean} forceReclean (optional) By default the element
7117 * keeps track if it has been cleaned already so
7118 * you can call this over and over. However, if you update the element and
7119 * need to force a reclean, you can pass true.
7121 clean : function(forceReclean){
7122 if(this.isCleaned && forceReclean !== true){
7126 var d = this.dom, n = d.firstChild, ni = -1;
7128 var nx = n.nextSibling;
7129 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7136 this.isCleaned = true;
7141 calcOffsetsTo : function(el){
7144 var restorePos = false;
7145 if(el.getStyle('position') == 'static'){
7146 el.position('relative');
7151 while(op && op != d && op.tagName != 'HTML'){
7154 op = op.offsetParent;
7157 el.position('static');
7163 * Scrolls this element into view within the passed container.
7164 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7165 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7166 * @return {Roo.Element} this
7168 scrollIntoView : function(container, hscroll){
7169 var c = Roo.getDom(container) || document.body;
7172 var o = this.calcOffsetsTo(c),
7175 b = t+el.offsetHeight,
7176 r = l+el.offsetWidth;
7178 var ch = c.clientHeight;
7179 var ct = parseInt(c.scrollTop, 10);
7180 var cl = parseInt(c.scrollLeft, 10);
7182 var cr = cl + c.clientWidth;
7190 if(hscroll !== false){
7194 c.scrollLeft = r-c.clientWidth;
7201 scrollChildIntoView : function(child, hscroll){
7202 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7206 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7207 * the new height may not be available immediately.
7208 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7209 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7210 * @param {Function} onComplete (optional) Function to call when animation completes
7211 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7212 * @return {Roo.Element} this
7214 autoHeight : function(animate, duration, onComplete, easing){
7215 var oldHeight = this.getHeight();
7217 this.setHeight(1); // force clipping
7218 setTimeout(function(){
7219 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7221 this.setHeight(height);
7223 if(typeof onComplete == "function"){
7227 this.setHeight(oldHeight); // restore original height
7228 this.setHeight(height, animate, duration, function(){
7230 if(typeof onComplete == "function") onComplete();
7231 }.createDelegate(this), easing);
7233 }.createDelegate(this), 0);
7238 * Returns true if this element is an ancestor of the passed element
7239 * @param {HTMLElement/String} el The element to check
7240 * @return {Boolean} True if this element is an ancestor of el, else false
7242 contains : function(el){
7243 if(!el){return false;}
7244 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7248 * Checks whether the element is currently visible using both visibility and display properties.
7249 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7250 * @return {Boolean} True if the element is currently visible, else false
7252 isVisible : function(deep) {
7253 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7254 if(deep !== true || !vis){
7257 var p = this.dom.parentNode;
7258 while(p && p.tagName.toLowerCase() != "body"){
7259 if(!Roo.fly(p, '_isVisible').isVisible()){
7268 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7269 * @param {String} selector The CSS selector
7270 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7271 * @return {CompositeElement/CompositeElementLite} The composite element
7273 select : function(selector, unique){
7274 return El.select(selector, unique, this.dom);
7278 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7279 * @param {String} selector The CSS selector
7280 * @return {Array} An array of the matched nodes
7282 query : function(selector, unique){
7283 return Roo.DomQuery.select(selector, this.dom);
7287 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7288 * @param {String} selector The CSS selector
7289 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7290 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7292 child : function(selector, returnDom){
7293 var n = Roo.DomQuery.selectNode(selector, this.dom);
7294 return returnDom ? n : Roo.get(n);
7298 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7299 * @param {String} selector The CSS selector
7300 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7301 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7303 down : function(selector, returnDom){
7304 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7305 return returnDom ? n : Roo.get(n);
7309 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7310 * @param {String} group The group the DD object is member of
7311 * @param {Object} config The DD config object
7312 * @param {Object} overrides An object containing methods to override/implement on the DD object
7313 * @return {Roo.dd.DD} The DD object
7315 initDD : function(group, config, overrides){
7316 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7317 return Roo.apply(dd, overrides);
7321 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7322 * @param {String} group The group the DDProxy object is member of
7323 * @param {Object} config The DDProxy config object
7324 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7325 * @return {Roo.dd.DDProxy} The DDProxy object
7327 initDDProxy : function(group, config, overrides){
7328 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7329 return Roo.apply(dd, overrides);
7333 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7334 * @param {String} group The group the DDTarget object is member of
7335 * @param {Object} config The DDTarget config object
7336 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7337 * @return {Roo.dd.DDTarget} The DDTarget object
7339 initDDTarget : function(group, config, overrides){
7340 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7341 return Roo.apply(dd, overrides);
7345 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7346 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7347 * @param {Boolean} visible Whether the element is visible
7348 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7349 * @return {Roo.Element} this
7351 setVisible : function(visible, animate){
7353 if(this.visibilityMode == El.DISPLAY){
7354 this.setDisplayed(visible);
7357 this.dom.style.visibility = visible ? "visible" : "hidden";
7360 // closure for composites
7362 var visMode = this.visibilityMode;
7364 this.setOpacity(.01);
7365 this.setVisible(true);
7367 this.anim({opacity: { to: (visible?1:0) }},
7368 this.preanim(arguments, 1),
7369 null, .35, 'easeIn', function(){
7371 if(visMode == El.DISPLAY){
7372 dom.style.display = "none";
7374 dom.style.visibility = "hidden";
7376 Roo.get(dom).setOpacity(1);
7384 * Returns true if display is not "none"
7387 isDisplayed : function() {
7388 return this.getStyle("display") != "none";
7392 * Toggles the element's visibility or display, depending on visibility mode.
7393 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7394 * @return {Roo.Element} this
7396 toggle : function(animate){
7397 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7402 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7403 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7404 * @return {Roo.Element} this
7406 setDisplayed : function(value) {
7407 if(typeof value == "boolean"){
7408 value = value ? this.originalDisplay : "none";
7410 this.setStyle("display", value);
7415 * Tries to focus the element. Any exceptions are caught and ignored.
7416 * @return {Roo.Element} this
7418 focus : function() {
7426 * Tries to blur the element. Any exceptions are caught and ignored.
7427 * @return {Roo.Element} this
7437 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7438 * @param {String/Array} className The CSS class to add, or an array of classes
7439 * @return {Roo.Element} this
7441 addClass : function(className){
7442 if(className instanceof Array){
7443 for(var i = 0, len = className.length; i < len; i++) {
7444 this.addClass(className[i]);
7447 if(className && !this.hasClass(className)){
7448 this.dom.className = this.dom.className + " " + className;
7455 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7456 * @param {String/Array} className The CSS class to add, or an array of classes
7457 * @return {Roo.Element} this
7459 radioClass : function(className){
7460 var siblings = this.dom.parentNode.childNodes;
7461 for(var i = 0; i < siblings.length; i++) {
7462 var s = siblings[i];
7463 if(s.nodeType == 1){
7464 Roo.get(s).removeClass(className);
7467 this.addClass(className);
7472 * Removes one or more CSS classes from the element.
7473 * @param {String/Array} className The CSS class to remove, or an array of classes
7474 * @return {Roo.Element} this
7476 removeClass : function(className){
7477 if(!className || !this.dom.className){
7480 if(className instanceof Array){
7481 for(var i = 0, len = className.length; i < len; i++) {
7482 this.removeClass(className[i]);
7485 if(this.hasClass(className)){
7486 var re = this.classReCache[className];
7488 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7489 this.classReCache[className] = re;
7491 this.dom.className =
7492 this.dom.className.replace(re, " ");
7502 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7503 * @param {String} className The CSS class to toggle
7504 * @return {Roo.Element} this
7506 toggleClass : function(className){
7507 if(this.hasClass(className)){
7508 this.removeClass(className);
7510 this.addClass(className);
7516 * Checks if the specified CSS class exists on this element's DOM node.
7517 * @param {String} className The CSS class to check for
7518 * @return {Boolean} True if the class exists, else false
7520 hasClass : function(className){
7521 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7525 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7526 * @param {String} oldClassName The CSS class to replace
7527 * @param {String} newClassName The replacement CSS class
7528 * @return {Roo.Element} this
7530 replaceClass : function(oldClassName, newClassName){
7531 this.removeClass(oldClassName);
7532 this.addClass(newClassName);
7537 * Returns an object with properties matching the styles requested.
7538 * For example, el.getStyles('color', 'font-size', 'width') might return
7539 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7540 * @param {String} style1 A style name
7541 * @param {String} style2 A style name
7542 * @param {String} etc.
7543 * @return {Object} The style object
7545 getStyles : function(){
7546 var a = arguments, len = a.length, r = {};
7547 for(var i = 0; i < len; i++){
7548 r[a[i]] = this.getStyle(a[i]);
7554 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7555 * @param {String} property The style property whose value is returned.
7556 * @return {String} The current value of the style property for this element.
7558 getStyle : function(){
7559 return view && view.getComputedStyle ?
7561 var el = this.dom, v, cs, camel;
7562 if(prop == 'float'){
7565 if(el.style && (v = el.style[prop])){
7568 if(cs = view.getComputedStyle(el, "")){
7569 if(!(camel = propCache[prop])){
7570 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7577 var el = this.dom, v, cs, camel;
7578 if(prop == 'opacity'){
7579 if(typeof el.style.filter == 'string'){
7580 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7582 var fv = parseFloat(m[1]);
7584 return fv ? fv / 100 : 0;
7589 }else if(prop == 'float'){
7590 prop = "styleFloat";
7592 if(!(camel = propCache[prop])){
7593 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7595 if(v = el.style[camel]){
7598 if(cs = el.currentStyle){
7606 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7607 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7608 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7609 * @return {Roo.Element} this
7611 setStyle : function(prop, value){
7612 if(typeof prop == "string"){
7614 if (prop == 'float') {
7615 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7620 if(!(camel = propCache[prop])){
7621 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7624 if(camel == 'opacity') {
7625 this.setOpacity(value);
7627 this.dom.style[camel] = value;
7630 for(var style in prop){
7631 if(typeof prop[style] != "function"){
7632 this.setStyle(style, prop[style]);
7640 * More flexible version of {@link #setStyle} for setting style properties.
7641 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7642 * a function which returns such a specification.
7643 * @return {Roo.Element} this
7645 applyStyles : function(style){
7646 Roo.DomHelper.applyStyles(this.dom, style);
7651 * 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).
7652 * @return {Number} The X position of the element
7655 return D.getX(this.dom);
7659 * 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).
7660 * @return {Number} The Y position of the element
7663 return D.getY(this.dom);
7667 * 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).
7668 * @return {Array} The XY position of the element
7671 return D.getXY(this.dom);
7675 * 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).
7676 * @param {Number} The X position of the element
7677 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7678 * @return {Roo.Element} this
7680 setX : function(x, animate){
7682 D.setX(this.dom, x);
7684 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7690 * 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).
7691 * @param {Number} The Y position of the element
7692 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7693 * @return {Roo.Element} this
7695 setY : function(y, animate){
7697 D.setY(this.dom, y);
7699 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7705 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7706 * @param {String} left The left CSS property value
7707 * @return {Roo.Element} this
7709 setLeft : function(left){
7710 this.setStyle("left", this.addUnits(left));
7715 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7716 * @param {String} top The top CSS property value
7717 * @return {Roo.Element} this
7719 setTop : function(top){
7720 this.setStyle("top", this.addUnits(top));
7725 * Sets the element's CSS right style.
7726 * @param {String} right The right CSS property value
7727 * @return {Roo.Element} this
7729 setRight : function(right){
7730 this.setStyle("right", this.addUnits(right));
7735 * Sets the element's CSS bottom style.
7736 * @param {String} bottom The bottom CSS property value
7737 * @return {Roo.Element} this
7739 setBottom : function(bottom){
7740 this.setStyle("bottom", this.addUnits(bottom));
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 {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7748 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7749 * @return {Roo.Element} this
7751 setXY : function(pos, animate){
7753 D.setXY(this.dom, pos);
7755 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7761 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7762 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7763 * @param {Number} x X value for new position (coordinates are page-based)
7764 * @param {Number} y Y value for new position (coordinates are page-based)
7765 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7766 * @return {Roo.Element} this
7768 setLocation : function(x, y, animate){
7769 this.setXY([x, y], this.preanim(arguments, 2));
7774 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7775 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7776 * @param {Number} x X value for new position (coordinates are page-based)
7777 * @param {Number} y Y value for new position (coordinates are page-based)
7778 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7779 * @return {Roo.Element} this
7781 moveTo : function(x, y, animate){
7782 this.setXY([x, y], this.preanim(arguments, 2));
7787 * Returns the region of the given element.
7788 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7789 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7791 getRegion : function(){
7792 return D.getRegion(this.dom);
7796 * Returns the offset height of the element
7797 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7798 * @return {Number} The element's height
7800 getHeight : function(contentHeight){
7801 var h = this.dom.offsetHeight || 0;
7802 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7806 * Returns the offset width of the element
7807 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7808 * @return {Number} The element's width
7810 getWidth : function(contentWidth){
7811 var w = this.dom.offsetWidth || 0;
7812 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7816 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7817 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7818 * if a height has not been set using CSS.
7821 getComputedHeight : function(){
7822 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7824 h = parseInt(this.getStyle('height'), 10) || 0;
7825 if(!this.isBorderBox()){
7826 h += this.getFrameWidth('tb');
7833 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7834 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7835 * if a width has not been set using CSS.
7838 getComputedWidth : function(){
7839 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7841 w = parseInt(this.getStyle('width'), 10) || 0;
7842 if(!this.isBorderBox()){
7843 w += this.getFrameWidth('lr');
7850 * Returns the size of the element.
7851 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7852 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7854 getSize : function(contentSize){
7855 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7859 * Returns the width and height of the viewport.
7860 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7862 getViewSize : function(){
7863 var d = this.dom, doc = document, aw = 0, ah = 0;
7864 if(d == doc || d == doc.body){
7865 return {width : D.getViewWidth(), height: D.getViewHeight()};
7868 width : d.clientWidth,
7869 height: d.clientHeight
7875 * Returns the value of the "value" attribute
7876 * @param {Boolean} asNumber true to parse the value as a number
7877 * @return {String/Number}
7879 getValue : function(asNumber){
7880 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7884 adjustWidth : function(width){
7885 if(typeof width == "number"){
7886 if(this.autoBoxAdjust && !this.isBorderBox()){
7887 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7897 adjustHeight : function(height){
7898 if(typeof height == "number"){
7899 if(this.autoBoxAdjust && !this.isBorderBox()){
7900 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7910 * Set the width of the element
7911 * @param {Number} width The new width
7912 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7913 * @return {Roo.Element} this
7915 setWidth : function(width, animate){
7916 width = this.adjustWidth(width);
7918 this.dom.style.width = this.addUnits(width);
7920 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7926 * Set the height of the element
7927 * @param {Number} height The new height
7928 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7929 * @return {Roo.Element} this
7931 setHeight : function(height, animate){
7932 height = this.adjustHeight(height);
7934 this.dom.style.height = this.addUnits(height);
7936 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7942 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7943 * @param {Number} width The new width
7944 * @param {Number} height The new height
7945 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7946 * @return {Roo.Element} this
7948 setSize : function(width, height, animate){
7949 if(typeof width == "object"){ // in case of object from getSize()
7950 height = width.height; width = width.width;
7952 width = this.adjustWidth(width); height = this.adjustHeight(height);
7954 this.dom.style.width = this.addUnits(width);
7955 this.dom.style.height = this.addUnits(height);
7957 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7963 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7964 * @param {Number} x X value for new position (coordinates are page-based)
7965 * @param {Number} y Y value for new position (coordinates are page-based)
7966 * @param {Number} width The new width
7967 * @param {Number} height The new height
7968 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7969 * @return {Roo.Element} this
7971 setBounds : function(x, y, width, height, animate){
7973 this.setSize(width, height);
7974 this.setLocation(x, y);
7976 width = this.adjustWidth(width); height = this.adjustHeight(height);
7977 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7978 this.preanim(arguments, 4), 'motion');
7984 * 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.
7985 * @param {Roo.lib.Region} region The region to fill
7986 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7987 * @return {Roo.Element} this
7989 setRegion : function(region, animate){
7990 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7995 * Appends an event handler
7997 * @param {String} eventName The type of event to append
7998 * @param {Function} fn The method the event invokes
7999 * @param {Object} scope (optional) The scope (this object) of the fn
8000 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8002 addListener : function(eventName, fn, scope, options){
8004 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8009 * Removes an event handler from this element
8010 * @param {String} eventName the type of event to remove
8011 * @param {Function} fn the method the event invokes
8012 * @return {Roo.Element} this
8014 removeListener : function(eventName, fn){
8015 Roo.EventManager.removeListener(this.dom, eventName, fn);
8020 * Removes all previous added listeners from this element
8021 * @return {Roo.Element} this
8023 removeAllListeners : function(){
8024 E.purgeElement(this.dom);
8028 relayEvent : function(eventName, observable){
8029 this.on(eventName, function(e){
8030 observable.fireEvent(eventName, e);
8035 * Set the opacity of the element
8036 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8037 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8038 * @return {Roo.Element} this
8040 setOpacity : function(opacity, animate){
8042 var s = this.dom.style;
8045 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8046 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8048 s.opacity = opacity;
8051 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8057 * Gets the left X coordinate
8058 * @param {Boolean} local True to get the local css position instead of page coordinate
8061 getLeft : function(local){
8065 return parseInt(this.getStyle("left"), 10) || 0;
8070 * Gets the right X coordinate of the element (element X position + element width)
8071 * @param {Boolean} local True to get the local css position instead of page coordinate
8074 getRight : function(local){
8076 return this.getX() + this.getWidth();
8078 return (this.getLeft(true) + this.getWidth()) || 0;
8083 * Gets the top Y coordinate
8084 * @param {Boolean} local True to get the local css position instead of page coordinate
8087 getTop : function(local) {
8091 return parseInt(this.getStyle("top"), 10) || 0;
8096 * Gets the bottom Y coordinate of the element (element Y position + element height)
8097 * @param {Boolean} local True to get the local css position instead of page coordinate
8100 getBottom : function(local){
8102 return this.getY() + this.getHeight();
8104 return (this.getTop(true) + this.getHeight()) || 0;
8109 * Initializes positioning on this element. If a desired position is not passed, it will make the
8110 * the element positioned relative IF it is not already positioned.
8111 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8112 * @param {Number} zIndex (optional) The zIndex to apply
8113 * @param {Number} x (optional) Set the page X position
8114 * @param {Number} y (optional) Set the page Y position
8116 position : function(pos, zIndex, x, y){
8118 if(this.getStyle('position') == 'static'){
8119 this.setStyle('position', 'relative');
8122 this.setStyle("position", pos);
8125 this.setStyle("z-index", zIndex);
8127 if(x !== undefined && y !== undefined){
8129 }else if(x !== undefined){
8131 }else if(y !== undefined){
8137 * Clear positioning back to the default when the document was loaded
8138 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8139 * @return {Roo.Element} this
8141 clearPositioning : function(value){
8149 "position" : "static"
8155 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8156 * snapshot before performing an update and then restoring the element.
8159 getPositioning : function(){
8160 var l = this.getStyle("left");
8161 var t = this.getStyle("top");
8163 "position" : this.getStyle("position"),
8165 "right" : l ? "" : this.getStyle("right"),
8167 "bottom" : t ? "" : this.getStyle("bottom"),
8168 "z-index" : this.getStyle("z-index")
8173 * Gets the width of the border(s) for the specified side(s)
8174 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8175 * passing lr would get the border (l)eft width + the border (r)ight width.
8176 * @return {Number} The width of the sides passed added together
8178 getBorderWidth : function(side){
8179 return this.addStyles(side, El.borders);
8183 * Gets the width of the padding(s) for the specified side(s)
8184 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8185 * passing lr would get the padding (l)eft + the padding (r)ight.
8186 * @return {Number} The padding of the sides passed added together
8188 getPadding : function(side){
8189 return this.addStyles(side, El.paddings);
8193 * Set positioning with an object returned by getPositioning().
8194 * @param {Object} posCfg
8195 * @return {Roo.Element} this
8197 setPositioning : function(pc){
8198 this.applyStyles(pc);
8199 if(pc.right == "auto"){
8200 this.dom.style.right = "";
8202 if(pc.bottom == "auto"){
8203 this.dom.style.bottom = "";
8209 fixDisplay : function(){
8210 if(this.getStyle("display") == "none"){
8211 this.setStyle("visibility", "hidden");
8212 this.setStyle("display", this.originalDisplay); // first try reverting to default
8213 if(this.getStyle("display") == "none"){ // if that fails, default to block
8214 this.setStyle("display", "block");
8220 * Quick set left and top adding default units
8221 * @param {String} left The left CSS property value
8222 * @param {String} top The top CSS property value
8223 * @return {Roo.Element} this
8225 setLeftTop : function(left, top){
8226 this.dom.style.left = this.addUnits(left);
8227 this.dom.style.top = this.addUnits(top);
8232 * Move this element relative to its current position.
8233 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8234 * @param {Number} distance How far to move the element in pixels
8235 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8236 * @return {Roo.Element} this
8238 move : function(direction, distance, animate){
8239 var xy = this.getXY();
8240 direction = direction.toLowerCase();
8244 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8248 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8253 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8258 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8265 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8266 * @return {Roo.Element} this
8269 if(!this.isClipped){
8270 this.isClipped = true;
8271 this.originalClip = {
8272 "o": this.getStyle("overflow"),
8273 "x": this.getStyle("overflow-x"),
8274 "y": this.getStyle("overflow-y")
8276 this.setStyle("overflow", "hidden");
8277 this.setStyle("overflow-x", "hidden");
8278 this.setStyle("overflow-y", "hidden");
8284 * Return clipping (overflow) to original clipping before clip() was called
8285 * @return {Roo.Element} this
8287 unclip : function(){
8289 this.isClipped = false;
8290 var o = this.originalClip;
8291 if(o.o){this.setStyle("overflow", o.o);}
8292 if(o.x){this.setStyle("overflow-x", o.x);}
8293 if(o.y){this.setStyle("overflow-y", o.y);}
8300 * Gets the x,y coordinates specified by the anchor position on the element.
8301 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8302 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8303 * {width: (target width), height: (target height)} (defaults to the element's current size)
8304 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8305 * @return {Array} [x, y] An array containing the element's x and y coordinates
8307 getAnchorXY : function(anchor, local, s){
8308 //Passing a different size is useful for pre-calculating anchors,
8309 //especially for anchored animations that change the el size.
8311 var w, h, vp = false;
8314 if(d == document.body || d == document){
8316 w = D.getViewWidth(); h = D.getViewHeight();
8318 w = this.getWidth(); h = this.getHeight();
8321 w = s.width; h = s.height;
8323 var x = 0, y = 0, r = Math.round;
8324 switch((anchor || "tl").toLowerCase()){
8366 var sc = this.getScroll();
8367 return [x + sc.left, y + sc.top];
8369 //Add the element's offset xy
8370 var o = this.getXY();
8371 return [x+o[0], y+o[1]];
8375 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8376 * supported position values.
8377 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8378 * @param {String} position The position to align to.
8379 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8380 * @return {Array} [x, y]
8382 getAlignToXY : function(el, p, o){
8386 throw "Element.alignTo with an element that doesn't exist";
8388 var c = false; //constrain to viewport
8389 var p1 = "", p2 = "";
8396 }else if(p.indexOf("-") == -1){
8399 p = p.toLowerCase();
8400 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8402 throw "Element.alignTo with an invalid alignment " + p;
8404 p1 = m[1]; p2 = m[2]; c = !!m[3];
8406 //Subtract the aligned el's internal xy from the target's offset xy
8407 //plus custom offset to get the aligned el's new offset xy
8408 var a1 = this.getAnchorXY(p1, true);
8409 var a2 = el.getAnchorXY(p2, false);
8410 var x = a2[0] - a1[0] + o[0];
8411 var y = a2[1] - a1[1] + o[1];
8413 //constrain the aligned el to viewport if necessary
8414 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8415 // 5px of margin for ie
8416 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8418 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8419 //perpendicular to the vp border, allow the aligned el to slide on that border,
8420 //otherwise swap the aligned el to the opposite border of the target.
8421 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8422 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8423 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8424 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8427 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8428 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8430 if((x+w) > dw + scrollX){
8431 x = swapX ? r.left-w : dw+scrollX-w;
8434 x = swapX ? r.right : scrollX;
8436 if((y+h) > dh + scrollY){
8437 y = swapY ? r.top-h : dh+scrollY-h;
8440 y = swapY ? r.bottom : scrollY;
8447 getConstrainToXY : function(){
8448 var os = {top:0, left:0, bottom:0, right: 0};
8450 return function(el, local, offsets, proposedXY){
8452 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8454 var vw, vh, vx = 0, vy = 0;
8455 if(el.dom == document.body || el.dom == document){
8456 vw = Roo.lib.Dom.getViewWidth();
8457 vh = Roo.lib.Dom.getViewHeight();
8459 vw = el.dom.clientWidth;
8460 vh = el.dom.clientHeight;
8462 var vxy = el.getXY();
8468 var s = el.getScroll();
8470 vx += offsets.left + s.left;
8471 vy += offsets.top + s.top;
8473 vw -= offsets.right;
8474 vh -= offsets.bottom;
8479 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8480 var x = xy[0], y = xy[1];
8481 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8483 // only move it if it needs it
8486 // first validate right/bottom
8495 // then make sure top/left isn't negative
8504 return moved ? [x, y] : false;
8509 adjustForConstraints : function(xy, parent, offsets){
8510 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8514 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8515 * document it aligns it to the viewport.
8516 * The position parameter is optional, and can be specified in any one of the following formats:
8518 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8519 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8520 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8521 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8522 * <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
8523 * element's anchor point, and the second value is used as the target's anchor point.</li>
8525 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8526 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8527 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8528 * that specified in order to enforce the viewport constraints.
8529 * Following are all of the supported anchor positions:
8532 ----- -----------------------------
8533 tl The top left corner (default)
8534 t The center of the top edge
8535 tr The top right corner
8536 l The center of the left edge
8537 c In the center of the element
8538 r The center of the right edge
8539 bl The bottom left corner
8540 b The center of the bottom edge
8541 br The bottom right corner
8545 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8546 el.alignTo("other-el");
8548 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8549 el.alignTo("other-el", "tr?");
8551 // align the bottom right corner of el with the center left edge of other-el
8552 el.alignTo("other-el", "br-l?");
8554 // align the center of el with the bottom left corner of other-el and
8555 // adjust the x position by -6 pixels (and the y position by 0)
8556 el.alignTo("other-el", "c-bl", [-6, 0]);
8558 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8559 * @param {String} position The position to align to.
8560 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8561 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8562 * @return {Roo.Element} this
8564 alignTo : function(element, position, offsets, animate){
8565 var xy = this.getAlignToXY(element, position, offsets);
8566 this.setXY(xy, this.preanim(arguments, 3));
8571 * Anchors an element to another element and realigns it when the window is resized.
8572 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8573 * @param {String} position The position to align to.
8574 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8575 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8576 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8577 * is a number, it is used as the buffer delay (defaults to 50ms).
8578 * @param {Function} callback The function to call after the animation finishes
8579 * @return {Roo.Element} this
8581 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8582 var action = function(){
8583 this.alignTo(el, alignment, offsets, animate);
8584 Roo.callback(callback, this);
8586 Roo.EventManager.onWindowResize(action, this);
8587 var tm = typeof monitorScroll;
8588 if(tm != 'undefined'){
8589 Roo.EventManager.on(window, 'scroll', action, this,
8590 {buffer: tm == 'number' ? monitorScroll : 50});
8592 action.call(this); // align immediately
8596 * Clears any opacity settings from this element. Required in some cases for IE.
8597 * @return {Roo.Element} this
8599 clearOpacity : function(){
8600 if (window.ActiveXObject) {
8601 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8602 this.dom.style.filter = "";
8605 this.dom.style.opacity = "";
8606 this.dom.style["-moz-opacity"] = "";
8607 this.dom.style["-khtml-opacity"] = "";
8613 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8614 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8615 * @return {Roo.Element} this
8617 hide : function(animate){
8618 this.setVisible(false, this.preanim(arguments, 0));
8623 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8624 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8625 * @return {Roo.Element} this
8627 show : function(animate){
8628 this.setVisible(true, this.preanim(arguments, 0));
8633 * @private Test if size has a unit, otherwise appends the default
8635 addUnits : function(size){
8636 return Roo.Element.addUnits(size, this.defaultUnit);
8640 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8641 * @return {Roo.Element} this
8643 beginMeasure : function(){
8645 if(el.offsetWidth || el.offsetHeight){
8646 return this; // offsets work already
8649 var p = this.dom, b = document.body; // start with this element
8650 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8651 var pe = Roo.get(p);
8652 if(pe.getStyle('display') == 'none'){
8653 changed.push({el: p, visibility: pe.getStyle("visibility")});
8654 p.style.visibility = "hidden";
8655 p.style.display = "block";
8659 this._measureChanged = changed;
8665 * Restores displays to before beginMeasure was called
8666 * @return {Roo.Element} this
8668 endMeasure : function(){
8669 var changed = this._measureChanged;
8671 for(var i = 0, len = changed.length; i < len; i++) {
8673 r.el.style.visibility = r.visibility;
8674 r.el.style.display = "none";
8676 this._measureChanged = null;
8682 * Update the innerHTML of this element, optionally searching for and processing scripts
8683 * @param {String} html The new HTML
8684 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8685 * @param {Function} callback For async script loading you can be noticed when the update completes
8686 * @return {Roo.Element} this
8688 update : function(html, loadScripts, callback){
8689 if(typeof html == "undefined"){
8692 if(loadScripts !== true){
8693 this.dom.innerHTML = html;
8694 if(typeof callback == "function"){
8702 html += '<span id="' + id + '"></span>';
8704 E.onAvailable(id, function(){
8705 var hd = document.getElementsByTagName("head")[0];
8706 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8707 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8708 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8711 while(match = re.exec(html)){
8712 var attrs = match[1];
8713 var srcMatch = attrs ? attrs.match(srcRe) : false;
8714 if(srcMatch && srcMatch[2]){
8715 var s = document.createElement("script");
8716 s.src = srcMatch[2];
8717 var typeMatch = attrs.match(typeRe);
8718 if(typeMatch && typeMatch[2]){
8719 s.type = typeMatch[2];
8722 }else if(match[2] && match[2].length > 0){
8723 if(window.execScript) {
8724 window.execScript(match[2]);
8732 window.eval(match[2]);
8736 var el = document.getElementById(id);
8737 if(el){el.parentNode.removeChild(el);}
8738 if(typeof callback == "function"){
8742 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8747 * Direct access to the UpdateManager update() method (takes the same parameters).
8748 * @param {String/Function} url The url for this request or a function to call to get the url
8749 * @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}
8750 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8751 * @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.
8752 * @return {Roo.Element} this
8755 var um = this.getUpdateManager();
8756 um.update.apply(um, arguments);
8761 * Gets this element's UpdateManager
8762 * @return {Roo.UpdateManager} The UpdateManager
8764 getUpdateManager : function(){
8765 if(!this.updateManager){
8766 this.updateManager = new Roo.UpdateManager(this);
8768 return this.updateManager;
8772 * Disables text selection for this element (normalized across browsers)
8773 * @return {Roo.Element} this
8775 unselectable : function(){
8776 this.dom.unselectable = "on";
8777 this.swallowEvent("selectstart", true);
8778 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8779 this.addClass("x-unselectable");
8784 * Calculates the x, y to center this element on the screen
8785 * @return {Array} The x, y values [x, y]
8787 getCenterXY : function(){
8788 return this.getAlignToXY(document, 'c-c');
8792 * Centers the Element in either the viewport, or another Element.
8793 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8795 center : function(centerIn){
8796 this.alignTo(centerIn || document, 'c-c');
8801 * Tests various css rules/browsers to determine if this element uses a border box
8804 isBorderBox : function(){
8805 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8809 * Return a box {x, y, width, height} that can be used to set another elements
8810 * size/location to match this element.
8811 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8812 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8813 * @return {Object} box An object in the format {x, y, width, height}
8815 getBox : function(contentBox, local){
8820 var left = parseInt(this.getStyle("left"), 10) || 0;
8821 var top = parseInt(this.getStyle("top"), 10) || 0;
8824 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8826 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8828 var l = this.getBorderWidth("l")+this.getPadding("l");
8829 var r = this.getBorderWidth("r")+this.getPadding("r");
8830 var t = this.getBorderWidth("t")+this.getPadding("t");
8831 var b = this.getBorderWidth("b")+this.getPadding("b");
8832 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)};
8834 bx.right = bx.x + bx.width;
8835 bx.bottom = bx.y + bx.height;
8840 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8841 for more information about the sides.
8842 * @param {String} sides
8845 getFrameWidth : function(sides, onlyContentBox){
8846 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8850 * 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.
8851 * @param {Object} box The box to fill {x, y, width, height}
8852 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8853 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8854 * @return {Roo.Element} this
8856 setBox : function(box, adjust, animate){
8857 var w = box.width, h = box.height;
8858 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8859 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8860 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8862 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8867 * Forces the browser to repaint this element
8868 * @return {Roo.Element} this
8870 repaint : function(){
8872 this.addClass("x-repaint");
8873 setTimeout(function(){
8874 Roo.get(dom).removeClass("x-repaint");
8880 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8881 * then it returns the calculated width of the sides (see getPadding)
8882 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8883 * @return {Object/Number}
8885 getMargins : function(side){
8888 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8889 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8890 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8891 right: parseInt(this.getStyle("margin-right"), 10) || 0
8894 return this.addStyles(side, El.margins);
8899 addStyles : function(sides, styles){
8901 for(var i = 0, len = sides.length; i < len; i++){
8902 v = this.getStyle(styles[sides.charAt(i)]);
8904 w = parseInt(v, 10);
8912 * Creates a proxy element of this element
8913 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8914 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8915 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8916 * @return {Roo.Element} The new proxy element
8918 createProxy : function(config, renderTo, matchBox){
8920 renderTo = Roo.getDom(renderTo);
8922 renderTo = document.body;
8924 config = typeof config == "object" ?
8925 config : {tag : "div", cls: config};
8926 var proxy = Roo.DomHelper.append(renderTo, config, true);
8928 proxy.setBox(this.getBox());
8934 * Puts a mask over this element to disable user interaction. Requires core.css.
8935 * This method can only be applied to elements which accept child nodes.
8936 * @param {String} msg (optional) A message to display in the mask
8937 * @param {String} msgCls (optional) A css class to apply to the msg element
8938 * @return {Element} The mask element
8940 mask : function(msg, msgCls)
8942 if(this.getStyle("position") == "static"){
8943 this.setStyle("position", "relative");
8946 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8948 this.addClass("x-masked");
8949 this._mask.setDisplayed(true);
8954 while (dom && dom.style) {
8955 if (!isNaN(parseInt(dom.style.zIndex))) {
8956 z = Math.max(z, parseInt(dom.style.zIndex));
8958 dom = dom.parentNode;
8960 // if we are masking the body - then it hides everything..
8961 if (this.dom == document.body) {
8963 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
8964 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
8967 if(typeof msg == 'string'){
8969 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8971 var mm = this._maskMsg;
8972 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8973 mm.dom.firstChild.innerHTML = msg;
8974 mm.setDisplayed(true);
8976 mm.setStyle('z-index', z + 102);
8978 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8979 this._mask.setHeight(this.getHeight());
8981 this._mask.setStyle('z-index', z + 100);
8987 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8988 * it is cached for reuse.
8990 unmask : function(removeEl){
8992 if(removeEl === true){
8993 this._mask.remove();
8996 this._maskMsg.remove();
8997 delete this._maskMsg;
9000 this._mask.setDisplayed(false);
9002 this._maskMsg.setDisplayed(false);
9006 this.removeClass("x-masked");
9010 * Returns true if this element is masked
9013 isMasked : function(){
9014 return this._mask && this._mask.isVisible();
9018 * Creates an iframe shim for this element to keep selects and other windowed objects from
9020 * @return {Roo.Element} The new shim element
9022 createShim : function(){
9023 var el = document.createElement('iframe');
9024 el.frameBorder = 'no';
9025 el.className = 'roo-shim';
9026 if(Roo.isIE && Roo.isSecure){
9027 el.src = Roo.SSL_SECURE_URL;
9029 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9030 shim.autoBoxAdjust = false;
9035 * Removes this element from the DOM and deletes it from the cache
9037 remove : function(){
9038 if(this.dom.parentNode){
9039 this.dom.parentNode.removeChild(this.dom);
9041 delete El.cache[this.dom.id];
9045 * Sets up event handlers to add and remove a css class when the mouse is over this element
9046 * @param {String} className
9047 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9048 * mouseout events for children elements
9049 * @return {Roo.Element} this
9051 addClassOnOver : function(className, preventFlicker){
9052 this.on("mouseover", function(){
9053 Roo.fly(this, '_internal').addClass(className);
9055 var removeFn = function(e){
9056 if(preventFlicker !== true || !e.within(this, true)){
9057 Roo.fly(this, '_internal').removeClass(className);
9060 this.on("mouseout", removeFn, this.dom);
9065 * Sets up event handlers to add and remove a css class when this element has the focus
9066 * @param {String} className
9067 * @return {Roo.Element} this
9069 addClassOnFocus : function(className){
9070 this.on("focus", function(){
9071 Roo.fly(this, '_internal').addClass(className);
9073 this.on("blur", function(){
9074 Roo.fly(this, '_internal').removeClass(className);
9079 * 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)
9080 * @param {String} className
9081 * @return {Roo.Element} this
9083 addClassOnClick : function(className){
9085 this.on("mousedown", function(){
9086 Roo.fly(dom, '_internal').addClass(className);
9087 var d = Roo.get(document);
9088 var fn = function(){
9089 Roo.fly(dom, '_internal').removeClass(className);
9090 d.removeListener("mouseup", fn);
9092 d.on("mouseup", fn);
9098 * Stops the specified event from bubbling and optionally prevents the default action
9099 * @param {String} eventName
9100 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9101 * @return {Roo.Element} this
9103 swallowEvent : function(eventName, preventDefault){
9104 var fn = function(e){
9105 e.stopPropagation();
9110 if(eventName instanceof Array){
9111 for(var i = 0, len = eventName.length; i < len; i++){
9112 this.on(eventName[i], fn);
9116 this.on(eventName, fn);
9123 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9126 * Sizes this element to its parent element's dimensions performing
9127 * neccessary box adjustments.
9128 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9129 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9130 * @return {Roo.Element} this
9132 fitToParent : function(monitorResize, targetParent) {
9133 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9134 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9135 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9138 var p = Roo.get(targetParent || this.dom.parentNode);
9139 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9140 if (monitorResize === true) {
9141 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9142 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9148 * Gets the next sibling, skipping text nodes
9149 * @return {HTMLElement} The next sibling or null
9151 getNextSibling : function(){
9152 var n = this.dom.nextSibling;
9153 while(n && n.nodeType != 1){
9160 * Gets the previous sibling, skipping text nodes
9161 * @return {HTMLElement} The previous sibling or null
9163 getPrevSibling : function(){
9164 var n = this.dom.previousSibling;
9165 while(n && n.nodeType != 1){
9166 n = n.previousSibling;
9173 * Appends the passed element(s) to this element
9174 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9175 * @return {Roo.Element} this
9177 appendChild: function(el){
9184 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9185 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9186 * automatically generated with the specified attributes.
9187 * @param {HTMLElement} insertBefore (optional) a child element of this element
9188 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9189 * @return {Roo.Element} The new child element
9191 createChild: function(config, insertBefore, returnDom){
9192 config = config || {tag:'div'};
9194 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9196 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9200 * Appends this element to the passed element
9201 * @param {String/HTMLElement/Element} el The new parent element
9202 * @return {Roo.Element} this
9204 appendTo: function(el){
9205 el = Roo.getDom(el);
9206 el.appendChild(this.dom);
9211 * Inserts this element before the passed element in the DOM
9212 * @param {String/HTMLElement/Element} el The element to insert before
9213 * @return {Roo.Element} this
9215 insertBefore: function(el){
9216 el = Roo.getDom(el);
9217 el.parentNode.insertBefore(this.dom, el);
9222 * Inserts this element after the passed element in the DOM
9223 * @param {String/HTMLElement/Element} el The element to insert after
9224 * @return {Roo.Element} this
9226 insertAfter: function(el){
9227 el = Roo.getDom(el);
9228 el.parentNode.insertBefore(this.dom, el.nextSibling);
9233 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9234 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9235 * @return {Roo.Element} The new child
9237 insertFirst: function(el, returnDom){
9239 if(typeof el == 'object' && !el.nodeType){ // dh config
9240 return this.createChild(el, this.dom.firstChild, returnDom);
9242 el = Roo.getDom(el);
9243 this.dom.insertBefore(el, this.dom.firstChild);
9244 return !returnDom ? Roo.get(el) : el;
9249 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9250 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9251 * @param {String} where (optional) 'before' or 'after' defaults to before
9252 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9253 * @return {Roo.Element} the inserted Element
9255 insertSibling: function(el, where, returnDom){
9256 where = where ? where.toLowerCase() : 'before';
9258 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9260 if(typeof el == 'object' && !el.nodeType){ // dh config
9261 if(where == 'after' && !this.dom.nextSibling){
9262 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9264 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9268 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9269 where == 'before' ? this.dom : this.dom.nextSibling);
9278 * Creates and wraps this element with another element
9279 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9280 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9281 * @return {HTMLElement/Element} The newly created wrapper element
9283 wrap: function(config, returnDom){
9285 config = {tag: "div"};
9287 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9288 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9293 * Replaces the passed element with this element
9294 * @param {String/HTMLElement/Element} el The element to replace
9295 * @return {Roo.Element} this
9297 replace: function(el){
9299 this.insertBefore(el);
9305 * Inserts an html fragment into this element
9306 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9307 * @param {String} html The HTML fragment
9308 * @param {Boolean} returnEl True to return an Roo.Element
9309 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9311 insertHtml : function(where, html, returnEl){
9312 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9313 return returnEl ? Roo.get(el) : el;
9317 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9318 * @param {Object} o The object with the attributes
9319 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9320 * @return {Roo.Element} this
9322 set : function(o, useSet){
9324 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9326 if(attr == "style" || typeof o[attr] == "function") continue;
9328 el.className = o["cls"];
9330 if(useSet) el.setAttribute(attr, o[attr]);
9331 else el[attr] = o[attr];
9335 Roo.DomHelper.applyStyles(el, o.style);
9341 * Convenience method for constructing a KeyMap
9342 * @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:
9343 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9344 * @param {Function} fn The function to call
9345 * @param {Object} scope (optional) The scope of the function
9346 * @return {Roo.KeyMap} The KeyMap created
9348 addKeyListener : function(key, fn, scope){
9350 if(typeof key != "object" || key instanceof Array){
9366 return new Roo.KeyMap(this, config);
9370 * Creates a KeyMap for this element
9371 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9372 * @return {Roo.KeyMap} The KeyMap created
9374 addKeyMap : function(config){
9375 return new Roo.KeyMap(this, config);
9379 * Returns true if this element is scrollable.
9382 isScrollable : function(){
9384 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9388 * 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().
9389 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9390 * @param {Number} value The new scroll value
9391 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9392 * @return {Element} this
9395 scrollTo : function(side, value, animate){
9396 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9398 this.dom[prop] = value;
9400 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9401 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9407 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9408 * within this element's scrollable range.
9409 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9410 * @param {Number} distance How far to scroll the element in pixels
9411 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9412 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9413 * was scrolled as far as it could go.
9415 scroll : function(direction, distance, animate){
9416 if(!this.isScrollable()){
9420 var l = el.scrollLeft, t = el.scrollTop;
9421 var w = el.scrollWidth, h = el.scrollHeight;
9422 var cw = el.clientWidth, ch = el.clientHeight;
9423 direction = direction.toLowerCase();
9424 var scrolled = false;
9425 var a = this.preanim(arguments, 2);
9430 var v = Math.min(l + distance, w-cw);
9431 this.scrollTo("left", v, a);
9438 var v = Math.max(l - distance, 0);
9439 this.scrollTo("left", v, a);
9447 var v = Math.max(t - distance, 0);
9448 this.scrollTo("top", v, a);
9456 var v = Math.min(t + distance, h-ch);
9457 this.scrollTo("top", v, a);
9466 * Translates the passed page coordinates into left/top css values for this element
9467 * @param {Number/Array} x The page x or an array containing [x, y]
9468 * @param {Number} y The page y
9469 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9471 translatePoints : function(x, y){
9472 if(typeof x == 'object' || x instanceof Array){
9475 var p = this.getStyle('position');
9476 var o = this.getXY();
9478 var l = parseInt(this.getStyle('left'), 10);
9479 var t = parseInt(this.getStyle('top'), 10);
9482 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9485 t = (p == "relative") ? 0 : this.dom.offsetTop;
9488 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9492 * Returns the current scroll position of the element.
9493 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9495 getScroll : function(){
9496 var d = this.dom, doc = document;
9497 if(d == doc || d == doc.body){
9498 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9499 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9500 return {left: l, top: t};
9502 return {left: d.scrollLeft, top: d.scrollTop};
9507 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9508 * are convert to standard 6 digit hex color.
9509 * @param {String} attr The css attribute
9510 * @param {String} defaultValue The default value to use when a valid color isn't found
9511 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9514 getColor : function(attr, defaultValue, prefix){
9515 var v = this.getStyle(attr);
9516 if(!v || v == "transparent" || v == "inherit") {
9517 return defaultValue;
9519 var color = typeof prefix == "undefined" ? "#" : prefix;
9520 if(v.substr(0, 4) == "rgb("){
9521 var rvs = v.slice(4, v.length -1).split(",");
9522 for(var i = 0; i < 3; i++){
9523 var h = parseInt(rvs[i]).toString(16);
9530 if(v.substr(0, 1) == "#"){
9532 for(var i = 1; i < 4; i++){
9533 var c = v.charAt(i);
9536 }else if(v.length == 7){
9537 color += v.substr(1);
9541 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9545 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9546 * gradient background, rounded corners and a 4-way shadow.
9547 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9548 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9549 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9550 * @return {Roo.Element} this
9552 boxWrap : function(cls){
9553 cls = cls || 'x-box';
9554 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9555 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9560 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9561 * @param {String} namespace The namespace in which to look for the attribute
9562 * @param {String} name The attribute name
9563 * @return {String} The attribute value
9565 getAttributeNS : Roo.isIE ? function(ns, name){
9567 var type = typeof d[ns+":"+name];
9568 if(type != 'undefined' && type != 'unknown'){
9569 return d[ns+":"+name];
9572 } : function(ns, name){
9574 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9579 * Sets or Returns the value the dom attribute value
9580 * @param {String} name The attribute name
9581 * @param {String} value (optional) The value to set the attribute to
9582 * @return {String} The attribute value
9584 attr : function(name){
9585 if (arguments.length > 1) {
9586 this.dom.setAttribute(name, arguments[1]);
9587 return arguments[1];
9589 if (!this.dom.hasAttribute(name)) {
9592 return this.dom.getAttribute(name);
9599 var ep = El.prototype;
9602 * Appends an event handler (Shorthand for addListener)
9603 * @param {String} eventName The type of event to append
9604 * @param {Function} fn The method the event invokes
9605 * @param {Object} scope (optional) The scope (this object) of the fn
9606 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9609 ep.on = ep.addListener;
9611 ep.mon = ep.addListener;
9614 * Removes an event handler from this element (shorthand for removeListener)
9615 * @param {String} eventName the type of event to remove
9616 * @param {Function} fn the method the event invokes
9617 * @return {Roo.Element} this
9620 ep.un = ep.removeListener;
9623 * true to automatically adjust width and height settings for box-model issues (default to true)
9625 ep.autoBoxAdjust = true;
9628 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9631 El.addUnits = function(v, defaultUnit){
9632 if(v === "" || v == "auto"){
9635 if(v === undefined){
9638 if(typeof v == "number" || !El.unitPattern.test(v)){
9639 return v + (defaultUnit || 'px');
9644 // special markup used throughout Roo when box wrapping elements
9645 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>';
9647 * Visibility mode constant - Use visibility to hide element
9653 * Visibility mode constant - Use display to hide element
9659 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9660 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9661 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9673 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9674 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9675 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9676 * @return {Element} The Element object
9679 El.get = function(el){
9681 if(!el){ return null; }
9682 if(typeof el == "string"){ // element id
9683 if(!(elm = document.getElementById(el))){
9686 if(ex = El.cache[el]){
9689 ex = El.cache[el] = new El(elm);
9692 }else if(el.tagName){ // dom element
9696 if(ex = El.cache[id]){
9699 ex = El.cache[id] = new El(el);
9702 }else if(el instanceof El){
9704 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9705 // catch case where it hasn't been appended
9706 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9709 }else if(el.isComposite){
9711 }else if(el instanceof Array){
9712 return El.select(el);
9713 }else if(el == document){
9714 // create a bogus element object representing the document object
9716 var f = function(){};
9717 f.prototype = El.prototype;
9719 docEl.dom = document;
9727 El.uncache = function(el){
9728 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9730 delete El.cache[a[i].id || a[i]];
9736 // Garbage collection - uncache elements/purge listeners on orphaned elements
9737 // so we don't hold a reference and cause the browser to retain them
9738 El.garbageCollect = function(){
9739 if(!Roo.enableGarbageCollector){
9740 clearInterval(El.collectorThread);
9743 for(var eid in El.cache){
9744 var el = El.cache[eid], d = el.dom;
9745 // -------------------------------------------------------
9746 // Determining what is garbage:
9747 // -------------------------------------------------------
9749 // dom node is null, definitely garbage
9750 // -------------------------------------------------------
9752 // no parentNode == direct orphan, definitely garbage
9753 // -------------------------------------------------------
9754 // !d.offsetParent && !document.getElementById(eid)
9755 // display none elements have no offsetParent so we will
9756 // also try to look it up by it's id. However, check
9757 // offsetParent first so we don't do unneeded lookups.
9758 // This enables collection of elements that are not orphans
9759 // directly, but somewhere up the line they have an orphan
9761 // -------------------------------------------------------
9762 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9763 delete El.cache[eid];
9764 if(d && Roo.enableListenerCollection){
9770 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9774 El.Flyweight = function(dom){
9777 El.Flyweight.prototype = El.prototype;
9779 El._flyweights = {};
9781 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9782 * the dom node can be overwritten by other code.
9783 * @param {String/HTMLElement} el The dom node or id
9784 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9785 * prevent conflicts (e.g. internally Roo uses "_internal")
9787 * @return {Element} The shared Element object
9789 El.fly = function(el, named){
9790 named = named || '_global';
9791 el = Roo.getDom(el);
9795 if(!El._flyweights[named]){
9796 El._flyweights[named] = new El.Flyweight();
9798 El._flyweights[named].dom = el;
9799 return El._flyweights[named];
9803 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9804 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9805 * Shorthand of {@link Roo.Element#get}
9806 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9807 * @return {Element} The Element object
9813 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9814 * the dom node can be overwritten by other code.
9815 * Shorthand of {@link Roo.Element#fly}
9816 * @param {String/HTMLElement} el The dom node or id
9817 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9818 * prevent conflicts (e.g. internally Roo uses "_internal")
9820 * @return {Element} The shared Element object
9826 // speedy lookup for elements never to box adjust
9827 var noBoxAdjust = Roo.isStrict ? {
9830 input:1, select:1, textarea:1
9832 if(Roo.isIE || Roo.isGecko){
9833 noBoxAdjust['button'] = 1;
9837 Roo.EventManager.on(window, 'unload', function(){
9839 delete El._flyweights;
9847 Roo.Element.selectorFunction = Roo.DomQuery.select;
9850 Roo.Element.select = function(selector, unique, root){
9852 if(typeof selector == "string"){
9853 els = Roo.Element.selectorFunction(selector, root);
9854 }else if(selector.length !== undefined){
9857 throw "Invalid selector";
9859 if(unique === true){
9860 return new Roo.CompositeElement(els);
9862 return new Roo.CompositeElementLite(els);
9866 * Selects elements based on the passed CSS selector to enable working on them as 1.
9867 * @param {String/Array} selector The CSS selector or an array of elements
9868 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9869 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9870 * @return {CompositeElementLite/CompositeElement}
9874 Roo.select = Roo.Element.select;
9891 * Ext JS Library 1.1.1
9892 * Copyright(c) 2006-2007, Ext JS, LLC.
9894 * Originally Released Under LGPL - original licence link has changed is not relivant.
9897 * <script type="text/javascript">
9902 //Notifies Element that fx methods are available
9903 Roo.enableFx = true;
9907 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9908 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9909 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9910 * Element effects to work.</p><br/>
9912 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9913 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9914 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9915 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9916 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9917 * expected results and should be done with care.</p><br/>
9919 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9920 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9923 ----- -----------------------------
9924 tl The top left corner
9925 t The center of the top edge
9926 tr The top right corner
9927 l The center of the left edge
9928 r The center of the right edge
9929 bl The bottom left corner
9930 b The center of the bottom edge
9931 br The bottom right corner
9933 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9934 * below are common options that can be passed to any Fx method.</b>
9935 * @cfg {Function} callback A function called when the effect is finished
9936 * @cfg {Object} scope The scope of the effect function
9937 * @cfg {String} easing A valid Easing value for the effect
9938 * @cfg {String} afterCls A css class to apply after the effect
9939 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9940 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9941 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9942 * effects that end with the element being visually hidden, ignored otherwise)
9943 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9944 * a function which returns such a specification that will be applied to the Element after the effect finishes
9945 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9946 * @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
9947 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9951 * Slides the element into view. An anchor point can be optionally passed to set the point of
9952 * origin for the slide effect. This function automatically handles wrapping the element with
9953 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9956 // default: slide the element in from the top
9959 // custom: slide the element in from the right with a 2-second duration
9960 el.slideIn('r', { duration: 2 });
9962 // common config options shown with default values
9968 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9969 * @param {Object} options (optional) Object literal with any of the Fx config options
9970 * @return {Roo.Element} The Element
9972 slideIn : function(anchor, o){
9973 var el = this.getFxEl();
9976 el.queueFx(o, function(){
9978 anchor = anchor || "t";
9980 // fix display to visibility
9983 // restore values after effect
9984 var r = this.getFxRestore();
9985 var b = this.getBox();
9986 // fixed size for slide
9990 var wrap = this.fxWrap(r.pos, o, "hidden");
9992 var st = this.dom.style;
9993 st.visibility = "visible";
9994 st.position = "absolute";
9996 // clear out temp styles after slide and unwrap
9997 var after = function(){
9998 el.fxUnwrap(wrap, r.pos, o);
10000 st.height = r.height;
10003 // time to calc the positions
10004 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10006 switch(anchor.toLowerCase()){
10008 wrap.setSize(b.width, 0);
10009 st.left = st.bottom = "0";
10013 wrap.setSize(0, b.height);
10014 st.right = st.top = "0";
10018 wrap.setSize(0, b.height);
10019 wrap.setX(b.right);
10020 st.left = st.top = "0";
10021 a = {width: bw, points: pt};
10024 wrap.setSize(b.width, 0);
10025 wrap.setY(b.bottom);
10026 st.left = st.top = "0";
10027 a = {height: bh, points: pt};
10030 wrap.setSize(0, 0);
10031 st.right = st.bottom = "0";
10032 a = {width: bw, height: bh};
10035 wrap.setSize(0, 0);
10036 wrap.setY(b.y+b.height);
10037 st.right = st.top = "0";
10038 a = {width: bw, height: bh, points: pt};
10041 wrap.setSize(0, 0);
10042 wrap.setXY([b.right, b.bottom]);
10043 st.left = st.top = "0";
10044 a = {width: bw, height: bh, points: pt};
10047 wrap.setSize(0, 0);
10048 wrap.setX(b.x+b.width);
10049 st.left = st.bottom = "0";
10050 a = {width: bw, height: bh, points: pt};
10053 this.dom.style.visibility = "visible";
10056 arguments.callee.anim = wrap.fxanim(a,
10066 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10067 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10068 * 'hidden') but block elements will still take up space in the document. The element must be removed
10069 * from the DOM using the 'remove' config option if desired. This function automatically handles
10070 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10073 // default: slide the element out to the top
10076 // custom: slide the element out to the right with a 2-second duration
10077 el.slideOut('r', { duration: 2 });
10079 // common config options shown with default values
10087 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10088 * @param {Object} options (optional) Object literal with any of the Fx config options
10089 * @return {Roo.Element} The Element
10091 slideOut : function(anchor, o){
10092 var el = this.getFxEl();
10095 el.queueFx(o, function(){
10097 anchor = anchor || "t";
10099 // restore values after effect
10100 var r = this.getFxRestore();
10102 var b = this.getBox();
10103 // fixed size for slide
10107 var wrap = this.fxWrap(r.pos, o, "visible");
10109 var st = this.dom.style;
10110 st.visibility = "visible";
10111 st.position = "absolute";
10115 var after = function(){
10117 el.setDisplayed(false);
10122 el.fxUnwrap(wrap, r.pos, o);
10124 st.width = r.width;
10125 st.height = r.height;
10130 var a, zero = {to: 0};
10131 switch(anchor.toLowerCase()){
10133 st.left = st.bottom = "0";
10134 a = {height: zero};
10137 st.right = st.top = "0";
10141 st.left = st.top = "0";
10142 a = {width: zero, points: {to:[b.right, b.y]}};
10145 st.left = st.top = "0";
10146 a = {height: zero, points: {to:[b.x, b.bottom]}};
10149 st.right = st.bottom = "0";
10150 a = {width: zero, height: zero};
10153 st.right = st.top = "0";
10154 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10157 st.left = st.top = "0";
10158 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10161 st.left = st.bottom = "0";
10162 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10166 arguments.callee.anim = wrap.fxanim(a,
10176 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10177 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10178 * The element must be removed from the DOM using the 'remove' config option if desired.
10184 // common config options shown with default values
10192 * @param {Object} options (optional) Object literal with any of the Fx config options
10193 * @return {Roo.Element} The Element
10195 puff : function(o){
10196 var el = this.getFxEl();
10199 el.queueFx(o, function(){
10200 this.clearOpacity();
10203 // restore values after effect
10204 var r = this.getFxRestore();
10205 var st = this.dom.style;
10207 var after = function(){
10209 el.setDisplayed(false);
10216 el.setPositioning(r.pos);
10217 st.width = r.width;
10218 st.height = r.height;
10223 var width = this.getWidth();
10224 var height = this.getHeight();
10226 arguments.callee.anim = this.fxanim({
10227 width : {to: this.adjustWidth(width * 2)},
10228 height : {to: this.adjustHeight(height * 2)},
10229 points : {by: [-(width * .5), -(height * .5)]},
10231 fontSize: {to:200, unit: "%"}
10242 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10243 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10244 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10250 // all config options shown with default values
10258 * @param {Object} options (optional) Object literal with any of the Fx config options
10259 * @return {Roo.Element} The Element
10261 switchOff : function(o){
10262 var el = this.getFxEl();
10265 el.queueFx(o, function(){
10266 this.clearOpacity();
10269 // restore values after effect
10270 var r = this.getFxRestore();
10271 var st = this.dom.style;
10273 var after = function(){
10275 el.setDisplayed(false);
10281 el.setPositioning(r.pos);
10282 st.width = r.width;
10283 st.height = r.height;
10288 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10289 this.clearOpacity();
10293 points:{by:[0, this.getHeight() * .5]}
10294 }, o, 'motion', 0.3, 'easeIn', after);
10295 }).defer(100, this);
10302 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10303 * changed using the "attr" config option) and then fading back to the original color. If no original
10304 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10307 // default: highlight background to yellow
10310 // custom: highlight foreground text to blue for 2 seconds
10311 el.highlight("0000ff", { attr: 'color', duration: 2 });
10313 // common config options shown with default values
10314 el.highlight("ffff9c", {
10315 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10316 endColor: (current color) or "ffffff",
10321 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10322 * @param {Object} options (optional) Object literal with any of the Fx config options
10323 * @return {Roo.Element} The Element
10325 highlight : function(color, o){
10326 var el = this.getFxEl();
10329 el.queueFx(o, function(){
10330 color = color || "ffff9c";
10331 attr = o.attr || "backgroundColor";
10333 this.clearOpacity();
10336 var origColor = this.getColor(attr);
10337 var restoreColor = this.dom.style[attr];
10338 endColor = (o.endColor || origColor) || "ffffff";
10340 var after = function(){
10341 el.dom.style[attr] = restoreColor;
10346 a[attr] = {from: color, to: endColor};
10347 arguments.callee.anim = this.fxanim(a,
10357 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10360 // default: a single light blue ripple
10363 // custom: 3 red ripples lasting 3 seconds total
10364 el.frame("ff0000", 3, { duration: 3 });
10366 // common config options shown with default values
10367 el.frame("C3DAF9", 1, {
10368 duration: 1 //duration of entire animation (not each individual ripple)
10369 // Note: Easing is not configurable and will be ignored if included
10372 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10373 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10374 * @param {Object} options (optional) Object literal with any of the Fx config options
10375 * @return {Roo.Element} The Element
10377 frame : function(color, count, o){
10378 var el = this.getFxEl();
10381 el.queueFx(o, function(){
10382 color = color || "#C3DAF9";
10383 if(color.length == 6){
10384 color = "#" + color;
10386 count = count || 1;
10387 duration = o.duration || 1;
10390 var b = this.getBox();
10391 var animFn = function(){
10392 var proxy = this.createProxy({
10395 visbility:"hidden",
10396 position:"absolute",
10397 "z-index":"35000", // yee haw
10398 border:"0px solid " + color
10401 var scale = Roo.isBorderBox ? 2 : 1;
10403 top:{from:b.y, to:b.y - 20},
10404 left:{from:b.x, to:b.x - 20},
10405 borderWidth:{from:0, to:10},
10406 opacity:{from:1, to:0},
10407 height:{from:b.height, to:(b.height + (20*scale))},
10408 width:{from:b.width, to:(b.width + (20*scale))}
10409 }, duration, function(){
10413 animFn.defer((duration/2)*1000, this);
10424 * Creates a pause before any subsequent queued effects begin. If there are
10425 * no effects queued after the pause it will have no effect.
10430 * @param {Number} seconds The length of time to pause (in seconds)
10431 * @return {Roo.Element} The Element
10433 pause : function(seconds){
10434 var el = this.getFxEl();
10437 el.queueFx(o, function(){
10438 setTimeout(function(){
10440 }, seconds * 1000);
10446 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10447 * using the "endOpacity" config option.
10450 // default: fade in from opacity 0 to 100%
10453 // custom: fade in from opacity 0 to 75% over 2 seconds
10454 el.fadeIn({ endOpacity: .75, duration: 2});
10456 // common config options shown with default values
10458 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10463 * @param {Object} options (optional) Object literal with any of the Fx config options
10464 * @return {Roo.Element} The Element
10466 fadeIn : function(o){
10467 var el = this.getFxEl();
10469 el.queueFx(o, function(){
10470 this.setOpacity(0);
10472 this.dom.style.visibility = 'visible';
10473 var to = o.endOpacity || 1;
10474 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10475 o, null, .5, "easeOut", function(){
10477 this.clearOpacity();
10486 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10487 * using the "endOpacity" config option.
10490 // default: fade out from the element's current opacity to 0
10493 // custom: fade out from the element's current opacity to 25% over 2 seconds
10494 el.fadeOut({ endOpacity: .25, duration: 2});
10496 // common config options shown with default values
10498 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10505 * @param {Object} options (optional) Object literal with any of the Fx config options
10506 * @return {Roo.Element} The Element
10508 fadeOut : function(o){
10509 var el = this.getFxEl();
10511 el.queueFx(o, function(){
10512 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10513 o, null, .5, "easeOut", function(){
10514 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10515 this.dom.style.display = "none";
10517 this.dom.style.visibility = "hidden";
10519 this.clearOpacity();
10527 * Animates the transition of an element's dimensions from a starting height/width
10528 * to an ending height/width.
10531 // change height and width to 100x100 pixels
10532 el.scale(100, 100);
10534 // common config options shown with default values. The height and width will default to
10535 // the element's existing values if passed as null.
10538 [element's height], {
10543 * @param {Number} width The new width (pass undefined to keep the original width)
10544 * @param {Number} height The new height (pass undefined to keep the original height)
10545 * @param {Object} options (optional) Object literal with any of the Fx config options
10546 * @return {Roo.Element} The Element
10548 scale : function(w, h, o){
10549 this.shift(Roo.apply({}, o, {
10557 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10558 * Any of these properties not specified in the config object will not be changed. This effect
10559 * requires that at least one new dimension, position or opacity setting must be passed in on
10560 * the config object in order for the function to have any effect.
10563 // slide the element horizontally to x position 200 while changing the height and opacity
10564 el.shift({ x: 200, height: 50, opacity: .8 });
10566 // common config options shown with default values.
10568 width: [element's width],
10569 height: [element's height],
10570 x: [element's x position],
10571 y: [element's y position],
10572 opacity: [element's opacity],
10577 * @param {Object} options Object literal with any of the Fx config options
10578 * @return {Roo.Element} The Element
10580 shift : function(o){
10581 var el = this.getFxEl();
10583 el.queueFx(o, function(){
10584 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10585 if(w !== undefined){
10586 a.width = {to: this.adjustWidth(w)};
10588 if(h !== undefined){
10589 a.height = {to: this.adjustHeight(h)};
10591 if(x !== undefined || y !== undefined){
10593 x !== undefined ? x : this.getX(),
10594 y !== undefined ? y : this.getY()
10597 if(op !== undefined){
10598 a.opacity = {to: op};
10600 if(o.xy !== undefined){
10601 a.points = {to: o.xy};
10603 arguments.callee.anim = this.fxanim(a,
10604 o, 'motion', .35, "easeOut", function(){
10612 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10613 * ending point of the effect.
10616 // default: slide the element downward while fading out
10619 // custom: slide the element out to the right with a 2-second duration
10620 el.ghost('r', { duration: 2 });
10622 // common config options shown with default values
10630 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10631 * @param {Object} options (optional) Object literal with any of the Fx config options
10632 * @return {Roo.Element} The Element
10634 ghost : function(anchor, o){
10635 var el = this.getFxEl();
10638 el.queueFx(o, function(){
10639 anchor = anchor || "b";
10641 // restore values after effect
10642 var r = this.getFxRestore();
10643 var w = this.getWidth(),
10644 h = this.getHeight();
10646 var st = this.dom.style;
10648 var after = function(){
10650 el.setDisplayed(false);
10656 el.setPositioning(r.pos);
10657 st.width = r.width;
10658 st.height = r.height;
10663 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10664 switch(anchor.toLowerCase()){
10691 arguments.callee.anim = this.fxanim(a,
10701 * Ensures that all effects queued after syncFx is called on the element are
10702 * run concurrently. This is the opposite of {@link #sequenceFx}.
10703 * @return {Roo.Element} The Element
10705 syncFx : function(){
10706 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10715 * Ensures that all effects queued after sequenceFx is called on the element are
10716 * run in sequence. This is the opposite of {@link #syncFx}.
10717 * @return {Roo.Element} The Element
10719 sequenceFx : function(){
10720 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10722 concurrent : false,
10729 nextFx : function(){
10730 var ef = this.fxQueue[0];
10737 * Returns true if the element has any effects actively running or queued, else returns false.
10738 * @return {Boolean} True if element has active effects, else false
10740 hasActiveFx : function(){
10741 return this.fxQueue && this.fxQueue[0];
10745 * Stops any running effects and clears the element's internal effects queue if it contains
10746 * any additional effects that haven't started yet.
10747 * @return {Roo.Element} The Element
10749 stopFx : function(){
10750 if(this.hasActiveFx()){
10751 var cur = this.fxQueue[0];
10752 if(cur && cur.anim && cur.anim.isAnimated()){
10753 this.fxQueue = [cur]; // clear out others
10754 cur.anim.stop(true);
10761 beforeFx : function(o){
10762 if(this.hasActiveFx() && !o.concurrent){
10773 * Returns true if the element is currently blocking so that no other effect can be queued
10774 * until this effect is finished, else returns false if blocking is not set. This is commonly
10775 * used to ensure that an effect initiated by a user action runs to completion prior to the
10776 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10777 * @return {Boolean} True if blocking, else false
10779 hasFxBlock : function(){
10780 var q = this.fxQueue;
10781 return q && q[0] && q[0].block;
10785 queueFx : function(o, fn){
10789 if(!this.hasFxBlock()){
10790 Roo.applyIf(o, this.fxDefaults);
10792 var run = this.beforeFx(o);
10793 fn.block = o.block;
10794 this.fxQueue.push(fn);
10806 fxWrap : function(pos, o, vis){
10808 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10811 wrapXY = this.getXY();
10813 var div = document.createElement("div");
10814 div.style.visibility = vis;
10815 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10816 wrap.setPositioning(pos);
10817 if(wrap.getStyle("position") == "static"){
10818 wrap.position("relative");
10820 this.clearPositioning('auto');
10822 wrap.dom.appendChild(this.dom);
10824 wrap.setXY(wrapXY);
10831 fxUnwrap : function(wrap, pos, o){
10832 this.clearPositioning();
10833 this.setPositioning(pos);
10835 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10841 getFxRestore : function(){
10842 var st = this.dom.style;
10843 return {pos: this.getPositioning(), width: st.width, height : st.height};
10847 afterFx : function(o){
10849 this.applyStyles(o.afterStyle);
10852 this.addClass(o.afterCls);
10854 if(o.remove === true){
10857 Roo.callback(o.callback, o.scope, [this]);
10859 this.fxQueue.shift();
10865 getFxEl : function(){ // support for composite element fx
10866 return Roo.get(this.dom);
10870 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10871 animType = animType || 'run';
10873 var anim = Roo.lib.Anim[animType](
10875 (opt.duration || defaultDur) || .35,
10876 (opt.easing || defaultEase) || 'easeOut',
10878 Roo.callback(cb, this);
10887 // backwords compat
10888 Roo.Fx.resize = Roo.Fx.scale;
10890 //When included, Roo.Fx is automatically applied to Element so that all basic
10891 //effects are available directly via the Element API
10892 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10894 * Ext JS Library 1.1.1
10895 * Copyright(c) 2006-2007, Ext JS, LLC.
10897 * Originally Released Under LGPL - original licence link has changed is not relivant.
10900 * <script type="text/javascript">
10905 * @class Roo.CompositeElement
10906 * Standard composite class. Creates a Roo.Element for every element in the collection.
10908 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10909 * actions will be performed on all the elements in this collection.</b>
10911 * All methods return <i>this</i> and can be chained.
10913 var els = Roo.select("#some-el div.some-class", true);
10914 // or select directly from an existing element
10915 var el = Roo.get('some-el');
10916 el.select('div.some-class', true);
10918 els.setWidth(100); // all elements become 100 width
10919 els.hide(true); // all elements fade out and hide
10921 els.setWidth(100).hide(true);
10924 Roo.CompositeElement = function(els){
10925 this.elements = [];
10926 this.addElements(els);
10928 Roo.CompositeElement.prototype = {
10930 addElements : function(els){
10931 if(!els) return this;
10932 if(typeof els == "string"){
10933 els = Roo.Element.selectorFunction(els);
10935 var yels = this.elements;
10936 var index = yels.length-1;
10937 for(var i = 0, len = els.length; i < len; i++) {
10938 yels[++index] = Roo.get(els[i]);
10944 * Clears this composite and adds the elements returned by the passed selector.
10945 * @param {String/Array} els A string CSS selector, an array of elements or an element
10946 * @return {CompositeElement} this
10948 fill : function(els){
10949 this.elements = [];
10955 * Filters this composite to only elements that match the passed selector.
10956 * @param {String} selector A string CSS selector
10957 * @return {CompositeElement} this
10959 filter : function(selector){
10961 this.each(function(el){
10962 if(el.is(selector)){
10963 els[els.length] = el.dom;
10970 invoke : function(fn, args){
10971 var els = this.elements;
10972 for(var i = 0, len = els.length; i < len; i++) {
10973 Roo.Element.prototype[fn].apply(els[i], args);
10978 * Adds elements to this composite.
10979 * @param {String/Array} els A string CSS selector, an array of elements or an element
10980 * @return {CompositeElement} this
10982 add : function(els){
10983 if(typeof els == "string"){
10984 this.addElements(Roo.Element.selectorFunction(els));
10985 }else if(els.length !== undefined){
10986 this.addElements(els);
10988 this.addElements([els]);
10993 * Calls the passed function passing (el, this, index) for each element in this composite.
10994 * @param {Function} fn The function to call
10995 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10996 * @return {CompositeElement} this
10998 each : function(fn, scope){
10999 var els = this.elements;
11000 for(var i = 0, len = els.length; i < len; i++){
11001 if(fn.call(scope || els[i], els[i], this, i) === false) {
11009 * Returns the Element object at the specified index
11010 * @param {Number} index
11011 * @return {Roo.Element}
11013 item : function(index){
11014 return this.elements[index] || null;
11018 * Returns the first Element
11019 * @return {Roo.Element}
11021 first : function(){
11022 return this.item(0);
11026 * Returns the last Element
11027 * @return {Roo.Element}
11030 return this.item(this.elements.length-1);
11034 * Returns the number of elements in this composite
11037 getCount : function(){
11038 return this.elements.length;
11042 * Returns true if this composite contains the passed element
11045 contains : function(el){
11046 return this.indexOf(el) !== -1;
11050 * Returns true if this composite contains the passed element
11053 indexOf : function(el){
11054 return this.elements.indexOf(Roo.get(el));
11059 * Removes the specified element(s).
11060 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11061 * or an array of any of those.
11062 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11063 * @return {CompositeElement} this
11065 removeElement : function(el, removeDom){
11066 if(el instanceof Array){
11067 for(var i = 0, len = el.length; i < len; i++){
11068 this.removeElement(el[i]);
11072 var index = typeof el == 'number' ? el : this.indexOf(el);
11075 var d = this.elements[index];
11079 d.parentNode.removeChild(d);
11082 this.elements.splice(index, 1);
11088 * Replaces the specified element with the passed element.
11089 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11091 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11092 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11093 * @return {CompositeElement} this
11095 replaceElement : function(el, replacement, domReplace){
11096 var index = typeof el == 'number' ? el : this.indexOf(el);
11099 this.elements[index].replaceWith(replacement);
11101 this.elements.splice(index, 1, Roo.get(replacement))
11108 * Removes all elements.
11110 clear : function(){
11111 this.elements = [];
11115 Roo.CompositeElement.createCall = function(proto, fnName){
11116 if(!proto[fnName]){
11117 proto[fnName] = function(){
11118 return this.invoke(fnName, arguments);
11122 for(var fnName in Roo.Element.prototype){
11123 if(typeof Roo.Element.prototype[fnName] == "function"){
11124 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11130 * Ext JS Library 1.1.1
11131 * Copyright(c) 2006-2007, Ext JS, LLC.
11133 * Originally Released Under LGPL - original licence link has changed is not relivant.
11136 * <script type="text/javascript">
11140 * @class Roo.CompositeElementLite
11141 * @extends Roo.CompositeElement
11142 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11144 var els = Roo.select("#some-el div.some-class");
11145 // or select directly from an existing element
11146 var el = Roo.get('some-el');
11147 el.select('div.some-class');
11149 els.setWidth(100); // all elements become 100 width
11150 els.hide(true); // all elements fade out and hide
11152 els.setWidth(100).hide(true);
11153 </code></pre><br><br>
11154 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11155 * actions will be performed on all the elements in this collection.</b>
11157 Roo.CompositeElementLite = function(els){
11158 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11159 this.el = new Roo.Element.Flyweight();
11161 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11162 addElements : function(els){
11164 if(els instanceof Array){
11165 this.elements = this.elements.concat(els);
11167 var yels = this.elements;
11168 var index = yels.length-1;
11169 for(var i = 0, len = els.length; i < len; i++) {
11170 yels[++index] = els[i];
11176 invoke : function(fn, args){
11177 var els = this.elements;
11179 for(var i = 0, len = els.length; i < len; i++) {
11181 Roo.Element.prototype[fn].apply(el, args);
11186 * Returns a flyweight Element of the dom element object at the specified index
11187 * @param {Number} index
11188 * @return {Roo.Element}
11190 item : function(index){
11191 if(!this.elements[index]){
11194 this.el.dom = this.elements[index];
11198 // fixes scope with flyweight
11199 addListener : function(eventName, handler, scope, opt){
11200 var els = this.elements;
11201 for(var i = 0, len = els.length; i < len; i++) {
11202 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11208 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11209 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11210 * a reference to the dom node, use el.dom.</b>
11211 * @param {Function} fn The function to call
11212 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11213 * @return {CompositeElement} this
11215 each : function(fn, scope){
11216 var els = this.elements;
11218 for(var i = 0, len = els.length; i < len; i++){
11220 if(fn.call(scope || el, el, this, i) === false){
11227 indexOf : function(el){
11228 return this.elements.indexOf(Roo.getDom(el));
11231 replaceElement : function(el, replacement, domReplace){
11232 var index = typeof el == 'number' ? el : this.indexOf(el);
11234 replacement = Roo.getDom(replacement);
11236 var d = this.elements[index];
11237 d.parentNode.insertBefore(replacement, d);
11238 d.parentNode.removeChild(d);
11240 this.elements.splice(index, 1, replacement);
11245 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11249 * Ext JS Library 1.1.1
11250 * Copyright(c) 2006-2007, Ext JS, LLC.
11252 * Originally Released Under LGPL - original licence link has changed is not relivant.
11255 * <script type="text/javascript">
11261 * @class Roo.data.Connection
11262 * @extends Roo.util.Observable
11263 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11264 * either to a configured URL, or to a URL specified at request time.<br><br>
11266 * Requests made by this class are asynchronous, and will return immediately. No data from
11267 * the server will be available to the statement immediately following the {@link #request} call.
11268 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11270 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11271 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11272 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11273 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11274 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11275 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11276 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11277 * standard DOM methods.
11279 * @param {Object} config a configuration object.
11281 Roo.data.Connection = function(config){
11282 Roo.apply(this, config);
11285 * @event beforerequest
11286 * Fires before a network request is made to retrieve a data object.
11287 * @param {Connection} conn This Connection object.
11288 * @param {Object} options The options config object passed to the {@link #request} method.
11290 "beforerequest" : true,
11292 * @event requestcomplete
11293 * Fires if the request was successfully completed.
11294 * @param {Connection} conn This Connection object.
11295 * @param {Object} response The XHR object containing the response data.
11296 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11297 * @param {Object} options The options config object passed to the {@link #request} method.
11299 "requestcomplete" : true,
11301 * @event requestexception
11302 * Fires if an error HTTP status was returned from the server.
11303 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11304 * @param {Connection} conn This Connection object.
11305 * @param {Object} response The XHR object containing the response data.
11306 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11307 * @param {Object} options The options config object passed to the {@link #request} method.
11309 "requestexception" : true
11311 Roo.data.Connection.superclass.constructor.call(this);
11314 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11316 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11319 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11320 * extra parameters to each request made by this object. (defaults to undefined)
11323 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11324 * to each request made by this object. (defaults to undefined)
11327 * @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)
11330 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11334 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11340 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11343 disableCaching: true,
11346 * Sends an HTTP request to a remote server.
11347 * @param {Object} options An object which may contain the following properties:<ul>
11348 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11349 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11350 * request, a url encoded string or a function to call to get either.</li>
11351 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11352 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11353 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11354 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11355 * <li>options {Object} The parameter to the request call.</li>
11356 * <li>success {Boolean} True if the request succeeded.</li>
11357 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11359 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11360 * The callback is passed the following parameters:<ul>
11361 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11362 * <li>options {Object} The parameter to the request call.</li>
11364 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11365 * The callback is passed the following parameters:<ul>
11366 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11367 * <li>options {Object} The parameter to the request call.</li>
11369 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11370 * for the callback function. Defaults to the browser window.</li>
11371 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11372 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11373 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11374 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11375 * params for the post data. Any params will be appended to the URL.</li>
11376 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11378 * @return {Number} transactionId
11380 request : function(o){
11381 if(this.fireEvent("beforerequest", this, o) !== false){
11384 if(typeof p == "function"){
11385 p = p.call(o.scope||window, o);
11387 if(typeof p == "object"){
11388 p = Roo.urlEncode(o.params);
11390 if(this.extraParams){
11391 var extras = Roo.urlEncode(this.extraParams);
11392 p = p ? (p + '&' + extras) : extras;
11395 var url = o.url || this.url;
11396 if(typeof url == 'function'){
11397 url = url.call(o.scope||window, o);
11401 var form = Roo.getDom(o.form);
11402 url = url || form.action;
11404 var enctype = form.getAttribute("enctype");
11405 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11406 return this.doFormUpload(o, p, url);
11408 var f = Roo.lib.Ajax.serializeForm(form);
11409 p = p ? (p + '&' + f) : f;
11412 var hs = o.headers;
11413 if(this.defaultHeaders){
11414 hs = Roo.apply(hs || {}, this.defaultHeaders);
11421 success: this.handleResponse,
11422 failure: this.handleFailure,
11424 argument: {options: o},
11425 timeout : o.timeout || this.timeout
11428 var method = o.method||this.method||(p ? "POST" : "GET");
11430 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11431 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11434 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11438 }else if(this.autoAbort !== false){
11442 if((method == 'GET' && p) || o.xmlData){
11443 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11446 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11447 return this.transId;
11449 Roo.callback(o.callback, o.scope, [o, null, null]);
11455 * Determine whether this object has a request outstanding.
11456 * @param {Number} transactionId (Optional) defaults to the last transaction
11457 * @return {Boolean} True if there is an outstanding request.
11459 isLoading : function(transId){
11461 return Roo.lib.Ajax.isCallInProgress(transId);
11463 return this.transId ? true : false;
11468 * Aborts any outstanding request.
11469 * @param {Number} transactionId (Optional) defaults to the last transaction
11471 abort : function(transId){
11472 if(transId || this.isLoading()){
11473 Roo.lib.Ajax.abort(transId || this.transId);
11478 handleResponse : function(response){
11479 this.transId = false;
11480 var options = response.argument.options;
11481 response.argument = options ? options.argument : null;
11482 this.fireEvent("requestcomplete", this, response, options);
11483 Roo.callback(options.success, options.scope, [response, options]);
11484 Roo.callback(options.callback, options.scope, [options, true, response]);
11488 handleFailure : function(response, e){
11489 this.transId = false;
11490 var options = response.argument.options;
11491 response.argument = options ? options.argument : null;
11492 this.fireEvent("requestexception", this, response, options, e);
11493 Roo.callback(options.failure, options.scope, [response, options]);
11494 Roo.callback(options.callback, options.scope, [options, false, response]);
11498 doFormUpload : function(o, ps, url){
11500 var frame = document.createElement('iframe');
11503 frame.className = 'x-hidden';
11505 frame.src = Roo.SSL_SECURE_URL;
11507 document.body.appendChild(frame);
11510 document.frames[id].name = id;
11513 var form = Roo.getDom(o.form);
11515 form.method = 'POST';
11516 form.enctype = form.encoding = 'multipart/form-data';
11522 if(ps){ // add dynamic params
11524 ps = Roo.urlDecode(ps, false);
11526 if(ps.hasOwnProperty(k)){
11527 hd = document.createElement('input');
11528 hd.type = 'hidden';
11531 form.appendChild(hd);
11538 var r = { // bogus response object
11543 r.argument = o ? o.argument : null;
11548 doc = frame.contentWindow.document;
11550 doc = (frame.contentDocument || window.frames[id].document);
11552 if(doc && doc.body){
11553 r.responseText = doc.body.innerHTML;
11555 if(doc && doc.XMLDocument){
11556 r.responseXML = doc.XMLDocument;
11558 r.responseXML = doc;
11565 Roo.EventManager.removeListener(frame, 'load', cb, this);
11567 this.fireEvent("requestcomplete", this, r, o);
11568 Roo.callback(o.success, o.scope, [r, o]);
11569 Roo.callback(o.callback, o.scope, [o, true, r]);
11571 setTimeout(function(){document.body.removeChild(frame);}, 100);
11574 Roo.EventManager.on(frame, 'load', cb, this);
11577 if(hiddens){ // remove dynamic params
11578 for(var i = 0, len = hiddens.length; i < len; i++){
11579 form.removeChild(hiddens[i]);
11586 * Ext JS Library 1.1.1
11587 * Copyright(c) 2006-2007, Ext JS, LLC.
11589 * Originally Released Under LGPL - original licence link has changed is not relivant.
11592 * <script type="text/javascript">
11596 * Global Ajax request class.
11599 * @extends Roo.data.Connection
11602 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11603 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11604 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11605 * @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)
11606 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11607 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11608 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11610 Roo.Ajax = new Roo.data.Connection({
11619 * Serialize the passed form into a url encoded string
11621 * @param {String/HTMLElement} form
11624 serializeForm : function(form){
11625 return Roo.lib.Ajax.serializeForm(form);
11629 * Ext JS Library 1.1.1
11630 * Copyright(c) 2006-2007, Ext JS, LLC.
11632 * Originally Released Under LGPL - original licence link has changed is not relivant.
11635 * <script type="text/javascript">
11640 * @class Roo.UpdateManager
11641 * @extends Roo.util.Observable
11642 * Provides AJAX-style update for Element object.<br><br>
11645 * // Get it from a Roo.Element object
11646 * var el = Roo.get("foo");
11647 * var mgr = el.getUpdateManager();
11648 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11650 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11652 * // or directly (returns the same UpdateManager instance)
11653 * var mgr = new Roo.UpdateManager("myElementId");
11654 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11655 * mgr.on("update", myFcnNeedsToKnow);
11657 // short handed call directly from the element object
11658 Roo.get("foo").load({
11662 text: "Loading Foo..."
11666 * Create new UpdateManager directly.
11667 * @param {String/HTMLElement/Roo.Element} el The element to update
11668 * @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).
11670 Roo.UpdateManager = function(el, forceNew){
11672 if(!forceNew && el.updateManager){
11673 return el.updateManager;
11676 * The Element object
11677 * @type Roo.Element
11681 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11684 this.defaultUrl = null;
11688 * @event beforeupdate
11689 * Fired before an update is made, return false from your handler and the update is cancelled.
11690 * @param {Roo.Element} el
11691 * @param {String/Object/Function} url
11692 * @param {String/Object} params
11694 "beforeupdate": true,
11697 * Fired after successful update is made.
11698 * @param {Roo.Element} el
11699 * @param {Object} oResponseObject The response Object
11704 * Fired on update failure.
11705 * @param {Roo.Element} el
11706 * @param {Object} oResponseObject The response Object
11710 var d = Roo.UpdateManager.defaults;
11712 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11715 this.sslBlankUrl = d.sslBlankUrl;
11717 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11720 this.disableCaching = d.disableCaching;
11722 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11725 this.indicatorText = d.indicatorText;
11727 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11730 this.showLoadIndicator = d.showLoadIndicator;
11732 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11735 this.timeout = d.timeout;
11738 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11741 this.loadScripts = d.loadScripts;
11744 * Transaction object of current executing transaction
11746 this.transaction = null;
11751 this.autoRefreshProcId = null;
11753 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11756 this.refreshDelegate = this.refresh.createDelegate(this);
11758 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11761 this.updateDelegate = this.update.createDelegate(this);
11763 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11766 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11770 this.successDelegate = this.processSuccess.createDelegate(this);
11774 this.failureDelegate = this.processFailure.createDelegate(this);
11776 if(!this.renderer){
11778 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11780 this.renderer = new Roo.UpdateManager.BasicRenderer();
11783 Roo.UpdateManager.superclass.constructor.call(this);
11786 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11788 * Get the Element this UpdateManager is bound to
11789 * @return {Roo.Element} The element
11791 getEl : function(){
11795 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11796 * @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:
11799 url: "your-url.php",<br/>
11800 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11801 callback: yourFunction,<br/>
11802 scope: yourObject, //(optional scope) <br/>
11803 discardUrl: false, <br/>
11804 nocache: false,<br/>
11805 text: "Loading...",<br/>
11807 scripts: false<br/>
11810 * The only required property is url. The optional properties nocache, text and scripts
11811 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11812 * @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}
11813 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11814 * @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.
11816 update : function(url, params, callback, discardUrl){
11817 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11818 var method = this.method,
11820 if(typeof url == "object"){ // must be config object
11823 params = params || cfg.params;
11824 callback = callback || cfg.callback;
11825 discardUrl = discardUrl || cfg.discardUrl;
11826 if(callback && cfg.scope){
11827 callback = callback.createDelegate(cfg.scope);
11829 if(typeof cfg.method != "undefined"){method = cfg.method;};
11830 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11831 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11832 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11833 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11835 this.showLoading();
11837 this.defaultUrl = url;
11839 if(typeof url == "function"){
11840 url = url.call(this);
11843 method = method || (params ? "POST" : "GET");
11844 if(method == "GET"){
11845 url = this.prepareUrl(url);
11848 var o = Roo.apply(cfg ||{}, {
11851 success: this.successDelegate,
11852 failure: this.failureDelegate,
11853 callback: undefined,
11854 timeout: (this.timeout*1000),
11855 argument: {"url": url, "form": null, "callback": callback, "params": params}
11857 Roo.log("updated manager called with timeout of " + o.timeout);
11858 this.transaction = Roo.Ajax.request(o);
11863 * 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.
11864 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11865 * @param {String/HTMLElement} form The form Id or form element
11866 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11867 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11868 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11870 formUpdate : function(form, url, reset, callback){
11871 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11872 if(typeof url == "function"){
11873 url = url.call(this);
11875 form = Roo.getDom(form);
11876 this.transaction = Roo.Ajax.request({
11879 success: this.successDelegate,
11880 failure: this.failureDelegate,
11881 timeout: (this.timeout*1000),
11882 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11884 this.showLoading.defer(1, this);
11889 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11890 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11892 refresh : function(callback){
11893 if(this.defaultUrl == null){
11896 this.update(this.defaultUrl, null, callback, true);
11900 * Set this element to auto refresh.
11901 * @param {Number} interval How often to update (in seconds).
11902 * @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)
11903 * @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}
11904 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11905 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11907 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11909 this.update(url || this.defaultUrl, params, callback, true);
11911 if(this.autoRefreshProcId){
11912 clearInterval(this.autoRefreshProcId);
11914 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11918 * Stop auto refresh on this element.
11920 stopAutoRefresh : function(){
11921 if(this.autoRefreshProcId){
11922 clearInterval(this.autoRefreshProcId);
11923 delete this.autoRefreshProcId;
11927 isAutoRefreshing : function(){
11928 return this.autoRefreshProcId ? true : false;
11931 * Called to update the element to "Loading" state. Override to perform custom action.
11933 showLoading : function(){
11934 if(this.showLoadIndicator){
11935 this.el.update(this.indicatorText);
11940 * Adds unique parameter to query string if disableCaching = true
11943 prepareUrl : function(url){
11944 if(this.disableCaching){
11945 var append = "_dc=" + (new Date().getTime());
11946 if(url.indexOf("?") !== -1){
11947 url += "&" + append;
11949 url += "?" + append;
11958 processSuccess : function(response){
11959 this.transaction = null;
11960 if(response.argument.form && response.argument.reset){
11961 try{ // put in try/catch since some older FF releases had problems with this
11962 response.argument.form.reset();
11965 if(this.loadScripts){
11966 this.renderer.render(this.el, response, this,
11967 this.updateComplete.createDelegate(this, [response]));
11969 this.renderer.render(this.el, response, this);
11970 this.updateComplete(response);
11974 updateComplete : function(response){
11975 this.fireEvent("update", this.el, response);
11976 if(typeof response.argument.callback == "function"){
11977 response.argument.callback(this.el, true, response);
11984 processFailure : function(response){
11985 this.transaction = null;
11986 this.fireEvent("failure", this.el, response);
11987 if(typeof response.argument.callback == "function"){
11988 response.argument.callback(this.el, false, response);
11993 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11994 * @param {Object} renderer The object implementing the render() method
11996 setRenderer : function(renderer){
11997 this.renderer = renderer;
12000 getRenderer : function(){
12001 return this.renderer;
12005 * Set the defaultUrl used for updates
12006 * @param {String/Function} defaultUrl The url or a function to call to get the url
12008 setDefaultUrl : function(defaultUrl){
12009 this.defaultUrl = defaultUrl;
12013 * Aborts the executing transaction
12015 abort : function(){
12016 if(this.transaction){
12017 Roo.Ajax.abort(this.transaction);
12022 * Returns true if an update is in progress
12023 * @return {Boolean}
12025 isUpdating : function(){
12026 if(this.transaction){
12027 return Roo.Ajax.isLoading(this.transaction);
12034 * @class Roo.UpdateManager.defaults
12035 * @static (not really - but it helps the doc tool)
12036 * The defaults collection enables customizing the default properties of UpdateManager
12038 Roo.UpdateManager.defaults = {
12040 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12046 * True to process scripts by default (Defaults to false).
12049 loadScripts : false,
12052 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12055 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12057 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12060 disableCaching : false,
12062 * Whether to show indicatorText when loading (Defaults to true).
12065 showLoadIndicator : true,
12067 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12070 indicatorText : '<div class="loading-indicator">Loading...</div>'
12074 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12076 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12077 * @param {String/HTMLElement/Roo.Element} el The element to update
12078 * @param {String} url The url
12079 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12080 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12083 * @member Roo.UpdateManager
12085 Roo.UpdateManager.updateElement = function(el, url, params, options){
12086 var um = Roo.get(el, true).getUpdateManager();
12087 Roo.apply(um, options);
12088 um.update(url, params, options ? options.callback : null);
12090 // alias for backwards compat
12091 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12093 * @class Roo.UpdateManager.BasicRenderer
12094 * Default Content renderer. Updates the elements innerHTML with the responseText.
12096 Roo.UpdateManager.BasicRenderer = function(){};
12098 Roo.UpdateManager.BasicRenderer.prototype = {
12100 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12101 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12102 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12103 * @param {Roo.Element} el The element being rendered
12104 * @param {Object} response The YUI Connect response object
12105 * @param {UpdateManager} updateManager The calling update manager
12106 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12108 render : function(el, response, updateManager, callback){
12109 el.update(response.responseText, updateManager.loadScripts, callback);
12115 * (c)) Alan Knowles
12121 * @class Roo.DomTemplate
12122 * @extends Roo.Template
12123 * An effort at a dom based template engine..
12125 * Similar to XTemplate, except it uses dom parsing to create the template..
12127 * Supported features:
12132 {a_variable} - output encoded.
12133 {a_variable.format:("Y-m-d")} - call a method on the variable
12134 {a_variable:raw} - unencoded output
12135 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12136 {a_variable:this.method_on_template(...)} - call a method on the template object.
12141 <div roo-for="a_variable or condition.."></div>
12142 <div roo-if="a_variable or condition"></div>
12143 <div roo-exec="some javascript"></div>
12144 <div roo-name="named_template"></div>
12149 Roo.DomTemplate = function()
12151 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12158 Roo.extend(Roo.DomTemplate, Roo.Template, {
12160 * id counter for sub templates.
12164 * flag to indicate if dom parser is inside a pre,
12165 * it will strip whitespace if not.
12170 * The various sub templates
12178 * basic tag replacing syntax
12181 * // you can fake an object call by doing this
12185 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12186 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12188 iterChild : function (node, method) {
12190 var oldPre = this.inPre;
12191 if (node.tagName == 'PRE') {
12194 for( var i = 0; i < node.childNodes.length; i++) {
12195 method.call(this, node.childNodes[i]);
12197 this.inPre = oldPre;
12203 * compile the template
12205 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12208 compile: function()
12212 // covert the html into DOM...
12216 doc = document.implementation.createHTMLDocument("");
12217 doc.documentElement.innerHTML = this.html ;
12218 div = doc.documentElement;
12220 // old IE... - nasty -- it causes all sorts of issues.. with
12221 // images getting pulled from server..
12222 div = document.createElement('div');
12223 div.innerHTML = this.html;
12225 //doc.documentElement.innerHTML = htmlBody
12231 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12233 var tpls = this.tpls;
12235 // create a top level template from the snippet..
12237 //Roo.log(div.innerHTML);
12244 body : div.innerHTML,
12257 Roo.each(tpls, function(tp){
12258 this.compileTpl(tp);
12259 this.tpls[tp.id] = tp;
12262 this.master = tpls[0];
12268 compileNode : function(node, istop) {
12273 // skip anything not a tag..
12274 if (node.nodeType != 1) {
12275 if (node.nodeType == 3 && !this.inPre) {
12276 // reduce white space..
12277 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12300 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12301 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12302 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12303 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12309 // just itterate children..
12310 this.iterChild(node,this.compileNode);
12313 tpl.uid = this.id++;
12314 tpl.value = node.getAttribute('roo-' + tpl.attr);
12315 node.removeAttribute('roo-'+ tpl.attr);
12316 if (tpl.attr != 'name') {
12317 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12318 node.parentNode.replaceChild(placeholder, node);
12321 var placeholder = document.createElement('span');
12322 placeholder.className = 'roo-tpl-' + tpl.value;
12323 node.parentNode.replaceChild(placeholder, node);
12326 // parent now sees '{domtplXXXX}
12327 this.iterChild(node,this.compileNode);
12329 // we should now have node body...
12330 var div = document.createElement('div');
12331 div.appendChild(node);
12333 // this has the unfortunate side effect of converting tagged attributes
12334 // eg. href="{...}" into %7C...%7D
12335 // this has been fixed by searching for those combo's although it's a bit hacky..
12338 tpl.body = div.innerHTML;
12345 switch (tpl.value) {
12346 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12347 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12348 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12353 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12357 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12361 tpl.id = tpl.value; // replace non characters???
12367 this.tpls.push(tpl);
12377 * Compile a segment of the template into a 'sub-template'
12383 compileTpl : function(tpl)
12385 var fm = Roo.util.Format;
12386 var useF = this.disableFormats !== true;
12388 var sep = Roo.isGecko ? "+\n" : ",\n";
12390 var undef = function(str) {
12391 Roo.debug && Roo.log("Property not found :" + str);
12395 //Roo.log(tpl.body);
12399 var fn = function(m, lbrace, name, format, args)
12402 //Roo.log(arguments);
12403 args = args ? args.replace(/\\'/g,"'") : args;
12404 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12405 if (typeof(format) == 'undefined') {
12406 format = 'htmlEncode';
12408 if (format == 'raw' ) {
12412 if(name.substr(0, 6) == 'domtpl'){
12413 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12416 // build an array of options to determine if value is undefined..
12418 // basically get 'xxxx.yyyy' then do
12419 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12420 // (function () { Roo.log("Property not found"); return ''; })() :
12425 Roo.each(name.split('.'), function(st) {
12426 lookfor += (lookfor.length ? '.': '') + st;
12427 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12430 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12433 if(format && useF){
12435 args = args ? ',' + args : "";
12437 if(format.substr(0, 5) != "this."){
12438 format = "fm." + format + '(';
12440 format = 'this.call("'+ format.substr(5) + '", ';
12444 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12447 if (args && args.length) {
12448 // called with xxyx.yuu:(test,test)
12450 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12452 // raw.. - :raw modifier..
12453 return "'"+ sep + udef_st + name + ")"+sep+"'";
12457 // branched to use + in gecko and [].join() in others
12459 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12460 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12463 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12464 body.push(tpl.body.replace(/(\r\n|\n)/g,
12465 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12466 body.push("'].join('');};};");
12467 body = body.join('');
12470 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12472 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12479 * same as applyTemplate, except it's done to one of the subTemplates
12480 * when using named templates, you can do:
12482 * var str = pl.applySubTemplate('your-name', values);
12485 * @param {Number} id of the template
12486 * @param {Object} values to apply to template
12487 * @param {Object} parent (normaly the instance of this object)
12489 applySubTemplate : function(id, values, parent)
12493 var t = this.tpls[id];
12497 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12498 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12502 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12509 if(t.execCall && t.execCall.call(this, values, parent)){
12513 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12519 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12520 parent = t.target ? values : parent;
12521 if(t.forCall && vs instanceof Array){
12523 for(var i = 0, len = vs.length; i < len; i++){
12525 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12527 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12529 //Roo.log(t.compiled);
12533 return buf.join('');
12536 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12541 return t.compiled.call(this, vs, parent);
12543 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12545 //Roo.log(t.compiled);
12553 applyTemplate : function(values){
12554 return this.master.compiled.call(this, values, {});
12555 //var s = this.subs;
12558 apply : function(){
12559 return this.applyTemplate.apply(this, arguments);
12564 Roo.DomTemplate.from = function(el){
12565 el = Roo.getDom(el);
12566 return new Roo.Domtemplate(el.value || el.innerHTML);
12569 * Ext JS Library 1.1.1
12570 * Copyright(c) 2006-2007, Ext JS, LLC.
12572 * Originally Released Under LGPL - original licence link has changed is not relivant.
12575 * <script type="text/javascript">
12579 * @class Roo.util.DelayedTask
12580 * Provides a convenient method of performing setTimeout where a new
12581 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12582 * You can use this class to buffer
12583 * the keypress events for a certain number of milliseconds, and perform only if they stop
12584 * for that amount of time.
12585 * @constructor The parameters to this constructor serve as defaults and are not required.
12586 * @param {Function} fn (optional) The default function to timeout
12587 * @param {Object} scope (optional) The default scope of that timeout
12588 * @param {Array} args (optional) The default Array of arguments
12590 Roo.util.DelayedTask = function(fn, scope, args){
12591 var id = null, d, t;
12593 var call = function(){
12594 var now = new Date().getTime();
12598 fn.apply(scope, args || []);
12602 * Cancels any pending timeout and queues a new one
12603 * @param {Number} delay The milliseconds to delay
12604 * @param {Function} newFn (optional) Overrides function passed to constructor
12605 * @param {Object} newScope (optional) Overrides scope passed to constructor
12606 * @param {Array} newArgs (optional) Overrides args passed to constructor
12608 this.delay = function(delay, newFn, newScope, newArgs){
12609 if(id && delay != d){
12613 t = new Date().getTime();
12615 scope = newScope || scope;
12616 args = newArgs || args;
12618 id = setInterval(call, d);
12623 * Cancel the last queued timeout
12625 this.cancel = function(){
12633 * Ext JS Library 1.1.1
12634 * Copyright(c) 2006-2007, Ext JS, LLC.
12636 * Originally Released Under LGPL - original licence link has changed is not relivant.
12639 * <script type="text/javascript">
12643 Roo.util.TaskRunner = function(interval){
12644 interval = interval || 10;
12645 var tasks = [], removeQueue = [];
12647 var running = false;
12649 var stopThread = function(){
12655 var startThread = function(){
12658 id = setInterval(runTasks, interval);
12662 var removeTask = function(task){
12663 removeQueue.push(task);
12669 var runTasks = function(){
12670 if(removeQueue.length > 0){
12671 for(var i = 0, len = removeQueue.length; i < len; i++){
12672 tasks.remove(removeQueue[i]);
12675 if(tasks.length < 1){
12680 var now = new Date().getTime();
12681 for(var i = 0, len = tasks.length; i < len; ++i){
12683 var itime = now - t.taskRunTime;
12684 if(t.interval <= itime){
12685 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12686 t.taskRunTime = now;
12687 if(rt === false || t.taskRunCount === t.repeat){
12692 if(t.duration && t.duration <= (now - t.taskStartTime)){
12699 * Queues a new task.
12700 * @param {Object} task
12702 this.start = function(task){
12704 task.taskStartTime = new Date().getTime();
12705 task.taskRunTime = 0;
12706 task.taskRunCount = 0;
12711 this.stop = function(task){
12716 this.stopAll = function(){
12718 for(var i = 0, len = tasks.length; i < len; i++){
12719 if(tasks[i].onStop){
12728 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12730 * Ext JS Library 1.1.1
12731 * Copyright(c) 2006-2007, Ext JS, LLC.
12733 * Originally Released Under LGPL - original licence link has changed is not relivant.
12736 * <script type="text/javascript">
12741 * @class Roo.util.MixedCollection
12742 * @extends Roo.util.Observable
12743 * A Collection class that maintains both numeric indexes and keys and exposes events.
12745 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12746 * collection (defaults to false)
12747 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12748 * and return the key value for that item. This is used when available to look up the key on items that
12749 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12750 * equivalent to providing an implementation for the {@link #getKey} method.
12752 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12760 * Fires when the collection is cleared.
12765 * Fires when an item is added to the collection.
12766 * @param {Number} index The index at which the item was added.
12767 * @param {Object} o The item added.
12768 * @param {String} key The key associated with the added item.
12773 * Fires when an item is replaced in the collection.
12774 * @param {String} key he key associated with the new added.
12775 * @param {Object} old The item being replaced.
12776 * @param {Object} new The new item.
12781 * Fires when an item is removed from the collection.
12782 * @param {Object} o The item being removed.
12783 * @param {String} key (optional) The key associated with the removed item.
12788 this.allowFunctions = allowFunctions === true;
12790 this.getKey = keyFn;
12792 Roo.util.MixedCollection.superclass.constructor.call(this);
12795 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12796 allowFunctions : false,
12799 * Adds an item to the collection.
12800 * @param {String} key The key to associate with the item
12801 * @param {Object} o The item to add.
12802 * @return {Object} The item added.
12804 add : function(key, o){
12805 if(arguments.length == 1){
12807 key = this.getKey(o);
12809 if(typeof key == "undefined" || key === null){
12811 this.items.push(o);
12812 this.keys.push(null);
12814 var old = this.map[key];
12816 return this.replace(key, o);
12819 this.items.push(o);
12821 this.keys.push(key);
12823 this.fireEvent("add", this.length-1, o, key);
12828 * MixedCollection has a generic way to fetch keys if you implement getKey.
12831 var mc = new Roo.util.MixedCollection();
12832 mc.add(someEl.dom.id, someEl);
12833 mc.add(otherEl.dom.id, otherEl);
12837 var mc = new Roo.util.MixedCollection();
12838 mc.getKey = function(el){
12844 // or via the constructor
12845 var mc = new Roo.util.MixedCollection(false, function(el){
12851 * @param o {Object} The item for which to find the key.
12852 * @return {Object} The key for the passed item.
12854 getKey : function(o){
12859 * Replaces an item in the collection.
12860 * @param {String} key The key associated with the item to replace, or the item to replace.
12861 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12862 * @return {Object} The new item.
12864 replace : function(key, o){
12865 if(arguments.length == 1){
12867 key = this.getKey(o);
12869 var old = this.item(key);
12870 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12871 return this.add(key, o);
12873 var index = this.indexOfKey(key);
12874 this.items[index] = o;
12876 this.fireEvent("replace", key, old, o);
12881 * Adds all elements of an Array or an Object to the collection.
12882 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12883 * an Array of values, each of which are added to the collection.
12885 addAll : function(objs){
12886 if(arguments.length > 1 || objs instanceof Array){
12887 var args = arguments.length > 1 ? arguments : objs;
12888 for(var i = 0, len = args.length; i < len; i++){
12892 for(var key in objs){
12893 if(this.allowFunctions || typeof objs[key] != "function"){
12894 this.add(key, objs[key]);
12901 * Executes the specified function once for every item in the collection, passing each
12902 * item as the first and only parameter. returning false from the function will stop the iteration.
12903 * @param {Function} fn The function to execute for each item.
12904 * @param {Object} scope (optional) The scope in which to execute the function.
12906 each : function(fn, scope){
12907 var items = [].concat(this.items); // each safe for removal
12908 for(var i = 0, len = items.length; i < len; i++){
12909 if(fn.call(scope || items[i], items[i], i, len) === false){
12916 * Executes the specified function once for every key in the collection, passing each
12917 * key, and its associated item as the first two parameters.
12918 * @param {Function} fn The function to execute for each item.
12919 * @param {Object} scope (optional) The scope in which to execute the function.
12921 eachKey : function(fn, scope){
12922 for(var i = 0, len = this.keys.length; i < len; i++){
12923 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12928 * Returns the first item in the collection which elicits a true return value from the
12929 * passed selection function.
12930 * @param {Function} fn The selection function to execute for each item.
12931 * @param {Object} scope (optional) The scope in which to execute the function.
12932 * @return {Object} The first item in the collection which returned true from the selection function.
12934 find : function(fn, scope){
12935 for(var i = 0, len = this.items.length; i < len; i++){
12936 if(fn.call(scope || window, this.items[i], this.keys[i])){
12937 return this.items[i];
12944 * Inserts an item at the specified index in the collection.
12945 * @param {Number} index The index to insert the item at.
12946 * @param {String} key The key to associate with the new item, or the item itself.
12947 * @param {Object} o (optional) If the second parameter was a key, the new item.
12948 * @return {Object} The item inserted.
12950 insert : function(index, key, o){
12951 if(arguments.length == 2){
12953 key = this.getKey(o);
12955 if(index >= this.length){
12956 return this.add(key, o);
12959 this.items.splice(index, 0, o);
12960 if(typeof key != "undefined" && key != null){
12963 this.keys.splice(index, 0, key);
12964 this.fireEvent("add", index, o, key);
12969 * Removed an item from the collection.
12970 * @param {Object} o The item to remove.
12971 * @return {Object} The item removed.
12973 remove : function(o){
12974 return this.removeAt(this.indexOf(o));
12978 * Remove an item from a specified index in the collection.
12979 * @param {Number} index The index within the collection of the item to remove.
12981 removeAt : function(index){
12982 if(index < this.length && index >= 0){
12984 var o = this.items[index];
12985 this.items.splice(index, 1);
12986 var key = this.keys[index];
12987 if(typeof key != "undefined"){
12988 delete this.map[key];
12990 this.keys.splice(index, 1);
12991 this.fireEvent("remove", o, key);
12996 * Removed an item associated with the passed key fom the collection.
12997 * @param {String} key The key of the item to remove.
12999 removeKey : function(key){
13000 return this.removeAt(this.indexOfKey(key));
13004 * Returns the number of items in the collection.
13005 * @return {Number} the number of items in the collection.
13007 getCount : function(){
13008 return this.length;
13012 * Returns index within the collection of the passed Object.
13013 * @param {Object} o The item to find the index of.
13014 * @return {Number} index of the item.
13016 indexOf : function(o){
13017 if(!this.items.indexOf){
13018 for(var i = 0, len = this.items.length; i < len; i++){
13019 if(this.items[i] == o) return i;
13023 return this.items.indexOf(o);
13028 * Returns index within the collection of the passed key.
13029 * @param {String} key The key to find the index of.
13030 * @return {Number} index of the key.
13032 indexOfKey : function(key){
13033 if(!this.keys.indexOf){
13034 for(var i = 0, len = this.keys.length; i < len; i++){
13035 if(this.keys[i] == key) return i;
13039 return this.keys.indexOf(key);
13044 * Returns the item associated with the passed key OR index. Key has priority over index.
13045 * @param {String/Number} key The key or index of the item.
13046 * @return {Object} The item associated with the passed key.
13048 item : function(key){
13049 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13050 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13054 * Returns the item at the specified index.
13055 * @param {Number} index The index of the item.
13058 itemAt : function(index){
13059 return this.items[index];
13063 * Returns the item associated with the passed key.
13064 * @param {String/Number} key The key of the item.
13065 * @return {Object} The item associated with the passed key.
13067 key : function(key){
13068 return this.map[key];
13072 * Returns true if the collection contains the passed Object as an item.
13073 * @param {Object} o The Object to look for in the collection.
13074 * @return {Boolean} True if the collection contains the Object as an item.
13076 contains : function(o){
13077 return this.indexOf(o) != -1;
13081 * Returns true if the collection contains the passed Object as a key.
13082 * @param {String} key The key to look for in the collection.
13083 * @return {Boolean} True if the collection contains the Object as a key.
13085 containsKey : function(key){
13086 return typeof this.map[key] != "undefined";
13090 * Removes all items from the collection.
13092 clear : function(){
13097 this.fireEvent("clear");
13101 * Returns the first item in the collection.
13102 * @return {Object} the first item in the collection..
13104 first : function(){
13105 return this.items[0];
13109 * Returns the last item in the collection.
13110 * @return {Object} the last item in the collection..
13113 return this.items[this.length-1];
13116 _sort : function(property, dir, fn){
13117 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13118 fn = fn || function(a, b){
13121 var c = [], k = this.keys, items = this.items;
13122 for(var i = 0, len = items.length; i < len; i++){
13123 c[c.length] = {key: k[i], value: items[i], index: i};
13125 c.sort(function(a, b){
13126 var v = fn(a[property], b[property]) * dsc;
13128 v = (a.index < b.index ? -1 : 1);
13132 for(var i = 0, len = c.length; i < len; i++){
13133 items[i] = c[i].value;
13136 this.fireEvent("sort", this);
13140 * Sorts this collection with the passed comparison function
13141 * @param {String} direction (optional) "ASC" or "DESC"
13142 * @param {Function} fn (optional) comparison function
13144 sort : function(dir, fn){
13145 this._sort("value", dir, fn);
13149 * Sorts this collection by keys
13150 * @param {String} direction (optional) "ASC" or "DESC"
13151 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13153 keySort : function(dir, fn){
13154 this._sort("key", dir, fn || function(a, b){
13155 return String(a).toUpperCase()-String(b).toUpperCase();
13160 * Returns a range of items in this collection
13161 * @param {Number} startIndex (optional) defaults to 0
13162 * @param {Number} endIndex (optional) default to the last item
13163 * @return {Array} An array of items
13165 getRange : function(start, end){
13166 var items = this.items;
13167 if(items.length < 1){
13170 start = start || 0;
13171 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13174 for(var i = start; i <= end; i++) {
13175 r[r.length] = items[i];
13178 for(var i = start; i >= end; i--) {
13179 r[r.length] = items[i];
13186 * Filter the <i>objects</i> in this collection by a specific property.
13187 * Returns a new collection that has been filtered.
13188 * @param {String} property A property on your objects
13189 * @param {String/RegExp} value Either string that the property values
13190 * should start with or a RegExp to test against the property
13191 * @return {MixedCollection} The new filtered collection
13193 filter : function(property, value){
13194 if(!value.exec){ // not a regex
13195 value = String(value);
13196 if(value.length == 0){
13197 return this.clone();
13199 value = new RegExp("^" + Roo.escapeRe(value), "i");
13201 return this.filterBy(function(o){
13202 return o && value.test(o[property]);
13207 * Filter by a function. * Returns a new collection that has been filtered.
13208 * The passed function will be called with each
13209 * object in the collection. If the function returns true, the value is included
13210 * otherwise it is filtered.
13211 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13212 * @param {Object} scope (optional) The scope of the function (defaults to this)
13213 * @return {MixedCollection} The new filtered collection
13215 filterBy : function(fn, scope){
13216 var r = new Roo.util.MixedCollection();
13217 r.getKey = this.getKey;
13218 var k = this.keys, it = this.items;
13219 for(var i = 0, len = it.length; i < len; i++){
13220 if(fn.call(scope||this, it[i], k[i])){
13221 r.add(k[i], it[i]);
13228 * Creates a duplicate of this collection
13229 * @return {MixedCollection}
13231 clone : function(){
13232 var r = new Roo.util.MixedCollection();
13233 var k = this.keys, it = this.items;
13234 for(var i = 0, len = it.length; i < len; i++){
13235 r.add(k[i], it[i]);
13237 r.getKey = this.getKey;
13242 * Returns the item associated with the passed key or index.
13244 * @param {String/Number} key The key or index of the item.
13245 * @return {Object} The item associated with the passed key.
13247 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13249 * Ext JS Library 1.1.1
13250 * Copyright(c) 2006-2007, Ext JS, LLC.
13252 * Originally Released Under LGPL - original licence link has changed is not relivant.
13255 * <script type="text/javascript">
13258 * @class Roo.util.JSON
13259 * Modified version of Douglas Crockford"s json.js that doesn"t
13260 * mess with the Object prototype
13261 * http://www.json.org/js.html
13264 Roo.util.JSON = new (function(){
13265 var useHasOwn = {}.hasOwnProperty ? true : false;
13267 // crashes Safari in some instances
13268 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13270 var pad = function(n) {
13271 return n < 10 ? "0" + n : n;
13284 var encodeString = function(s){
13285 if (/["\\\x00-\x1f]/.test(s)) {
13286 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13291 c = b.charCodeAt();
13293 Math.floor(c / 16).toString(16) +
13294 (c % 16).toString(16);
13297 return '"' + s + '"';
13300 var encodeArray = function(o){
13301 var a = ["["], b, i, l = o.length, v;
13302 for (i = 0; i < l; i += 1) {
13304 switch (typeof v) {
13313 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13321 var encodeDate = function(o){
13322 return '"' + o.getFullYear() + "-" +
13323 pad(o.getMonth() + 1) + "-" +
13324 pad(o.getDate()) + "T" +
13325 pad(o.getHours()) + ":" +
13326 pad(o.getMinutes()) + ":" +
13327 pad(o.getSeconds()) + '"';
13331 * Encodes an Object, Array or other value
13332 * @param {Mixed} o The variable to encode
13333 * @return {String} The JSON string
13335 this.encode = function(o)
13337 // should this be extended to fully wrap stringify..
13339 if(typeof o == "undefined" || o === null){
13341 }else if(o instanceof Array){
13342 return encodeArray(o);
13343 }else if(o instanceof Date){
13344 return encodeDate(o);
13345 }else if(typeof o == "string"){
13346 return encodeString(o);
13347 }else if(typeof o == "number"){
13348 return isFinite(o) ? String(o) : "null";
13349 }else if(typeof o == "boolean"){
13352 var a = ["{"], b, i, v;
13354 if(!useHasOwn || o.hasOwnProperty(i)) {
13356 switch (typeof v) {
13365 a.push(this.encode(i), ":",
13366 v === null ? "null" : this.encode(v));
13377 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13378 * @param {String} json The JSON string
13379 * @return {Object} The resulting object
13381 this.decode = function(json){
13383 return /** eval:var:json */ eval("(" + json + ')');
13387 * Shorthand for {@link Roo.util.JSON#encode}
13388 * @member Roo encode
13390 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13392 * Shorthand for {@link Roo.util.JSON#decode}
13393 * @member Roo decode
13395 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13398 * Ext JS Library 1.1.1
13399 * Copyright(c) 2006-2007, Ext JS, LLC.
13401 * Originally Released Under LGPL - original licence link has changed is not relivant.
13404 * <script type="text/javascript">
13408 * @class Roo.util.Format
13409 * Reusable data formatting functions
13412 Roo.util.Format = function(){
13413 var trimRe = /^\s+|\s+$/g;
13416 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13417 * @param {String} value The string to truncate
13418 * @param {Number} length The maximum length to allow before truncating
13419 * @return {String} The converted text
13421 ellipsis : function(value, len){
13422 if(value && value.length > len){
13423 return value.substr(0, len-3)+"...";
13429 * Checks a reference and converts it to empty string if it is undefined
13430 * @param {Mixed} value Reference to check
13431 * @return {Mixed} Empty string if converted, otherwise the original value
13433 undef : function(value){
13434 return typeof value != "undefined" ? value : "";
13438 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13439 * @param {String} value The string to encode
13440 * @return {String} The encoded text
13442 htmlEncode : function(value){
13443 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13447 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13448 * @param {String} value The string to decode
13449 * @return {String} The decoded text
13451 htmlDecode : function(value){
13452 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13456 * Trims any whitespace from either side of a string
13457 * @param {String} value The text to trim
13458 * @return {String} The trimmed text
13460 trim : function(value){
13461 return String(value).replace(trimRe, "");
13465 * Returns a substring from within an original string
13466 * @param {String} value The original text
13467 * @param {Number} start The start index of the substring
13468 * @param {Number} length The length of the substring
13469 * @return {String} The substring
13471 substr : function(value, start, length){
13472 return String(value).substr(start, length);
13476 * Converts a string to all lower case letters
13477 * @param {String} value The text to convert
13478 * @return {String} The converted text
13480 lowercase : function(value){
13481 return String(value).toLowerCase();
13485 * Converts a string to all upper case letters
13486 * @param {String} value The text to convert
13487 * @return {String} The converted text
13489 uppercase : function(value){
13490 return String(value).toUpperCase();
13494 * Converts the first character only of a string to upper case
13495 * @param {String} value The text to convert
13496 * @return {String} The converted text
13498 capitalize : function(value){
13499 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13503 call : function(value, fn){
13504 if(arguments.length > 2){
13505 var args = Array.prototype.slice.call(arguments, 2);
13506 args.unshift(value);
13508 return /** eval:var:value */ eval(fn).apply(window, args);
13510 /** eval:var:value */
13511 return /** eval:var:value */ eval(fn).call(window, value);
13517 * safer version of Math.toFixed..??/
13518 * @param {Number/String} value The numeric value to format
13519 * @param {Number/String} value Decimal places
13520 * @return {String} The formatted currency string
13522 toFixed : function(v, n)
13524 // why not use to fixed - precision is buggered???
13526 return Math.round(v-0);
13528 var fact = Math.pow(10,n+1);
13529 v = (Math.round((v-0)*fact))/fact;
13530 var z = (''+fact).substring(2);
13531 if (v == Math.floor(v)) {
13532 return Math.floor(v) + '.' + z;
13535 // now just padd decimals..
13536 var ps = String(v).split('.');
13537 var fd = (ps[1] + z);
13538 var r = fd.substring(0,n);
13539 var rm = fd.substring(n);
13541 return ps[0] + '.' + r;
13543 r*=1; // turn it into a number;
13545 if (String(r).length != n) {
13548 r = String(r).substring(1); // chop the end off.
13551 return ps[0] + '.' + r;
13556 * Format a number as US currency
13557 * @param {Number/String} value The numeric value to format
13558 * @return {String} The formatted currency string
13560 usMoney : function(v){
13561 return '$' + Roo.util.Format.number(v);
13566 * eventually this should probably emulate php's number_format
13567 * @param {Number/String} value The numeric value to format
13568 * @param {Number} decimals number of decimal places
13569 * @return {String} The formatted currency string
13571 number : function(v,decimals)
13573 // multiply and round.
13574 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13575 var mul = Math.pow(10, decimals);
13576 var zero = String(mul).substring(1);
13577 v = (Math.round((v-0)*mul))/mul;
13579 // if it's '0' number.. then
13581 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13583 var ps = v.split('.');
13587 var r = /(\d+)(\d{3})/;
13589 while (r.test(whole)) {
13590 whole = whole.replace(r, '$1' + ',' + '$2');
13596 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13597 // does not have decimals
13598 (decimals ? ('.' + zero) : '');
13601 return whole + sub ;
13605 * Parse a value into a formatted date using the specified format pattern.
13606 * @param {Mixed} value The value to format
13607 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13608 * @return {String} The formatted date string
13610 date : function(v, format){
13614 if(!(v instanceof Date)){
13615 v = new Date(Date.parse(v));
13617 return v.dateFormat(format || "m/d/Y");
13621 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13622 * @param {String} format Any valid date format string
13623 * @return {Function} The date formatting function
13625 dateRenderer : function(format){
13626 return function(v){
13627 return Roo.util.Format.date(v, format);
13632 stripTagsRE : /<\/?[^>]+>/gi,
13635 * Strips all HTML tags
13636 * @param {Mixed} value The text from which to strip tags
13637 * @return {String} The stripped text
13639 stripTags : function(v){
13640 return !v ? v : String(v).replace(this.stripTagsRE, "");
13645 * Ext JS Library 1.1.1
13646 * Copyright(c) 2006-2007, Ext JS, LLC.
13648 * Originally Released Under LGPL - original licence link has changed is not relivant.
13651 * <script type="text/javascript">
13658 * @class Roo.MasterTemplate
13659 * @extends Roo.Template
13660 * Provides a template that can have child templates. The syntax is:
13662 var t = new Roo.MasterTemplate(
13663 '<select name="{name}">',
13664 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13667 t.add('options', {value: 'foo', text: 'bar'});
13668 // or you can add multiple child elements in one shot
13669 t.addAll('options', [
13670 {value: 'foo', text: 'bar'},
13671 {value: 'foo2', text: 'bar2'},
13672 {value: 'foo3', text: 'bar3'}
13674 // then append, applying the master template values
13675 t.append('my-form', {name: 'my-select'});
13677 * A name attribute for the child template is not required if you have only one child
13678 * template or you want to refer to them by index.
13680 Roo.MasterTemplate = function(){
13681 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13682 this.originalHtml = this.html;
13684 var m, re = this.subTemplateRe;
13687 while(m = re.exec(this.html)){
13688 var name = m[1], content = m[2];
13693 tpl : new Roo.Template(content)
13696 st[name] = st[subIndex];
13698 st[subIndex].tpl.compile();
13699 st[subIndex].tpl.call = this.call.createDelegate(this);
13702 this.subCount = subIndex;
13705 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13707 * The regular expression used to match sub templates
13711 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13714 * Applies the passed values to a child template.
13715 * @param {String/Number} name (optional) The name or index of the child template
13716 * @param {Array/Object} values The values to be applied to the template
13717 * @return {MasterTemplate} this
13719 add : function(name, values){
13720 if(arguments.length == 1){
13721 values = arguments[0];
13724 var s = this.subs[name];
13725 s.buffer[s.buffer.length] = s.tpl.apply(values);
13730 * Applies all the passed values to a child template.
13731 * @param {String/Number} name (optional) The name or index of the child template
13732 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13733 * @param {Boolean} reset (optional) True to reset the template first
13734 * @return {MasterTemplate} this
13736 fill : function(name, values, reset){
13738 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13746 for(var i = 0, len = values.length; i < len; i++){
13747 this.add(name, values[i]);
13753 * Resets the template for reuse
13754 * @return {MasterTemplate} this
13756 reset : function(){
13758 for(var i = 0; i < this.subCount; i++){
13764 applyTemplate : function(values){
13766 var replaceIndex = -1;
13767 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13768 return s[++replaceIndex].buffer.join("");
13770 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13773 apply : function(){
13774 return this.applyTemplate.apply(this, arguments);
13777 compile : function(){return this;}
13781 * Alias for fill().
13784 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13786 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13787 * var tpl = Roo.MasterTemplate.from('element-id');
13788 * @param {String/HTMLElement} el
13789 * @param {Object} config
13792 Roo.MasterTemplate.from = function(el, config){
13793 el = Roo.getDom(el);
13794 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13797 * Ext JS Library 1.1.1
13798 * Copyright(c) 2006-2007, Ext JS, LLC.
13800 * Originally Released Under LGPL - original licence link has changed is not relivant.
13803 * <script type="text/javascript">
13808 * @class Roo.util.CSS
13809 * Utility class for manipulating CSS rules
13812 Roo.util.CSS = function(){
13814 var doc = document;
13816 var camelRe = /(-[a-z])/gi;
13817 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13821 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13822 * tag and appended to the HEAD of the document.
13823 * @param {String|Object} cssText The text containing the css rules
13824 * @param {String} id An id to add to the stylesheet for later removal
13825 * @return {StyleSheet}
13827 createStyleSheet : function(cssText, id){
13829 var head = doc.getElementsByTagName("head")[0];
13830 var nrules = doc.createElement("style");
13831 nrules.setAttribute("type", "text/css");
13833 nrules.setAttribute("id", id);
13835 if (typeof(cssText) != 'string') {
13836 // support object maps..
13837 // not sure if this a good idea..
13838 // perhaps it should be merged with the general css handling
13839 // and handle js style props.
13840 var cssTextNew = [];
13841 for(var n in cssText) {
13843 for(var k in cssText[n]) {
13844 citems.push( k + ' : ' +cssText[n][k] + ';' );
13846 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13849 cssText = cssTextNew.join("\n");
13855 head.appendChild(nrules);
13856 ss = nrules.styleSheet;
13857 ss.cssText = cssText;
13860 nrules.appendChild(doc.createTextNode(cssText));
13862 nrules.cssText = cssText;
13864 head.appendChild(nrules);
13865 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13867 this.cacheStyleSheet(ss);
13872 * Removes a style or link tag by id
13873 * @param {String} id The id of the tag
13875 removeStyleSheet : function(id){
13876 var existing = doc.getElementById(id);
13878 existing.parentNode.removeChild(existing);
13883 * Dynamically swaps an existing stylesheet reference for a new one
13884 * @param {String} id The id of an existing link tag to remove
13885 * @param {String} url The href of the new stylesheet to include
13887 swapStyleSheet : function(id, url){
13888 this.removeStyleSheet(id);
13889 var ss = doc.createElement("link");
13890 ss.setAttribute("rel", "stylesheet");
13891 ss.setAttribute("type", "text/css");
13892 ss.setAttribute("id", id);
13893 ss.setAttribute("href", url);
13894 doc.getElementsByTagName("head")[0].appendChild(ss);
13898 * Refresh the rule cache if you have dynamically added stylesheets
13899 * @return {Object} An object (hash) of rules indexed by selector
13901 refreshCache : function(){
13902 return this.getRules(true);
13906 cacheStyleSheet : function(stylesheet){
13910 try{// try catch for cross domain access issue
13911 var ssRules = stylesheet.cssRules || stylesheet.rules;
13912 for(var j = ssRules.length-1; j >= 0; --j){
13913 rules[ssRules[j].selectorText] = ssRules[j];
13919 * Gets all css rules for the document
13920 * @param {Boolean} refreshCache true to refresh the internal cache
13921 * @return {Object} An object (hash) of rules indexed by selector
13923 getRules : function(refreshCache){
13924 if(rules == null || refreshCache){
13926 var ds = doc.styleSheets;
13927 for(var i =0, len = ds.length; i < len; i++){
13929 this.cacheStyleSheet(ds[i]);
13937 * Gets an an individual CSS rule by selector(s)
13938 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13939 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13940 * @return {CSSRule} The CSS rule or null if one is not found
13942 getRule : function(selector, refreshCache){
13943 var rs = this.getRules(refreshCache);
13944 if(!(selector instanceof Array)){
13945 return rs[selector];
13947 for(var i = 0; i < selector.length; i++){
13948 if(rs[selector[i]]){
13949 return rs[selector[i]];
13957 * Updates a rule property
13958 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13959 * @param {String} property The css property
13960 * @param {String} value The new value for the property
13961 * @return {Boolean} true If a rule was found and updated
13963 updateRule : function(selector, property, value){
13964 if(!(selector instanceof Array)){
13965 var rule = this.getRule(selector);
13967 rule.style[property.replace(camelRe, camelFn)] = value;
13971 for(var i = 0; i < selector.length; i++){
13972 if(this.updateRule(selector[i], property, value)){
13982 * Ext JS Library 1.1.1
13983 * Copyright(c) 2006-2007, Ext JS, LLC.
13985 * Originally Released Under LGPL - original licence link has changed is not relivant.
13988 * <script type="text/javascript">
13994 * @class Roo.util.ClickRepeater
13995 * @extends Roo.util.Observable
13997 * A wrapper class which can be applied to any element. Fires a "click" event while the
13998 * mouse is pressed. The interval between firings may be specified in the config but
13999 * defaults to 10 milliseconds.
14001 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14003 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14004 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14005 * Similar to an autorepeat key delay.
14006 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14007 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14008 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14009 * "interval" and "delay" are ignored. "immediate" is honored.
14010 * @cfg {Boolean} preventDefault True to prevent the default click event
14011 * @cfg {Boolean} stopDefault True to stop the default click event
14014 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14015 * 2007-02-02 jvs Renamed to ClickRepeater
14016 * 2007-02-03 jvs Modifications for FF Mac and Safari
14019 * @param {String/HTMLElement/Element} el The element to listen on
14020 * @param {Object} config
14022 Roo.util.ClickRepeater = function(el, config)
14024 this.el = Roo.get(el);
14025 this.el.unselectable();
14027 Roo.apply(this, config);
14032 * Fires when the mouse button is depressed.
14033 * @param {Roo.util.ClickRepeater} this
14035 "mousedown" : true,
14038 * Fires on a specified interval during the time the element is pressed.
14039 * @param {Roo.util.ClickRepeater} this
14044 * Fires when the mouse key is released.
14045 * @param {Roo.util.ClickRepeater} this
14050 this.el.on("mousedown", this.handleMouseDown, this);
14051 if(this.preventDefault || this.stopDefault){
14052 this.el.on("click", function(e){
14053 if(this.preventDefault){
14054 e.preventDefault();
14056 if(this.stopDefault){
14062 // allow inline handler
14064 this.on("click", this.handler, this.scope || this);
14067 Roo.util.ClickRepeater.superclass.constructor.call(this);
14070 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14073 preventDefault : true,
14074 stopDefault : false,
14078 handleMouseDown : function(){
14079 clearTimeout(this.timer);
14081 if(this.pressClass){
14082 this.el.addClass(this.pressClass);
14084 this.mousedownTime = new Date();
14086 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14087 this.el.on("mouseout", this.handleMouseOut, this);
14089 this.fireEvent("mousedown", this);
14090 this.fireEvent("click", this);
14092 this.timer = this.click.defer(this.delay || this.interval, this);
14096 click : function(){
14097 this.fireEvent("click", this);
14098 this.timer = this.click.defer(this.getInterval(), this);
14102 getInterval: function(){
14103 if(!this.accelerate){
14104 return this.interval;
14106 var pressTime = this.mousedownTime.getElapsed();
14107 if(pressTime < 500){
14109 }else if(pressTime < 1700){
14111 }else if(pressTime < 2600){
14113 }else if(pressTime < 3500){
14115 }else if(pressTime < 4400){
14117 }else if(pressTime < 5300){
14119 }else if(pressTime < 6200){
14127 handleMouseOut : function(){
14128 clearTimeout(this.timer);
14129 if(this.pressClass){
14130 this.el.removeClass(this.pressClass);
14132 this.el.on("mouseover", this.handleMouseReturn, this);
14136 handleMouseReturn : function(){
14137 this.el.un("mouseover", this.handleMouseReturn);
14138 if(this.pressClass){
14139 this.el.addClass(this.pressClass);
14145 handleMouseUp : function(){
14146 clearTimeout(this.timer);
14147 this.el.un("mouseover", this.handleMouseReturn);
14148 this.el.un("mouseout", this.handleMouseOut);
14149 Roo.get(document).un("mouseup", this.handleMouseUp);
14150 this.el.removeClass(this.pressClass);
14151 this.fireEvent("mouseup", this);
14155 * Ext JS Library 1.1.1
14156 * Copyright(c) 2006-2007, Ext JS, LLC.
14158 * Originally Released Under LGPL - original licence link has changed is not relivant.
14161 * <script type="text/javascript">
14166 * @class Roo.KeyNav
14167 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14168 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14169 * way to implement custom navigation schemes for any UI component.</p>
14170 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14171 * pageUp, pageDown, del, home, end. Usage:</p>
14173 var nav = new Roo.KeyNav("my-element", {
14174 "left" : function(e){
14175 this.moveLeft(e.ctrlKey);
14177 "right" : function(e){
14178 this.moveRight(e.ctrlKey);
14180 "enter" : function(e){
14187 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14188 * @param {Object} config The config
14190 Roo.KeyNav = function(el, config){
14191 this.el = Roo.get(el);
14192 Roo.apply(this, config);
14193 if(!this.disabled){
14194 this.disabled = true;
14199 Roo.KeyNav.prototype = {
14201 * @cfg {Boolean} disabled
14202 * True to disable this KeyNav instance (defaults to false)
14206 * @cfg {String} defaultEventAction
14207 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14208 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14209 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14211 defaultEventAction: "stopEvent",
14213 * @cfg {Boolean} forceKeyDown
14214 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14215 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14216 * handle keydown instead of keypress.
14218 forceKeyDown : false,
14221 prepareEvent : function(e){
14222 var k = e.getKey();
14223 var h = this.keyToHandler[k];
14224 //if(h && this[h]){
14225 // e.stopPropagation();
14227 if(Roo.isSafari && h && k >= 37 && k <= 40){
14233 relay : function(e){
14234 var k = e.getKey();
14235 var h = this.keyToHandler[k];
14237 if(this.doRelay(e, this[h], h) !== true){
14238 e[this.defaultEventAction]();
14244 doRelay : function(e, h, hname){
14245 return h.call(this.scope || this, e);
14248 // possible handlers
14262 // quick lookup hash
14279 * Enable this KeyNav
14281 enable: function(){
14283 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14284 // the EventObject will normalize Safari automatically
14285 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14286 this.el.on("keydown", this.relay, this);
14288 this.el.on("keydown", this.prepareEvent, this);
14289 this.el.on("keypress", this.relay, this);
14291 this.disabled = false;
14296 * Disable this KeyNav
14298 disable: function(){
14299 if(!this.disabled){
14300 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14301 this.el.un("keydown", this.relay);
14303 this.el.un("keydown", this.prepareEvent);
14304 this.el.un("keypress", this.relay);
14306 this.disabled = true;
14311 * Ext JS Library 1.1.1
14312 * Copyright(c) 2006-2007, Ext JS, LLC.
14314 * Originally Released Under LGPL - original licence link has changed is not relivant.
14317 * <script type="text/javascript">
14322 * @class Roo.KeyMap
14323 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14324 * The constructor accepts the same config object as defined by {@link #addBinding}.
14325 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14326 * combination it will call the function with this signature (if the match is a multi-key
14327 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14328 * A KeyMap can also handle a string representation of keys.<br />
14331 // map one key by key code
14332 var map = new Roo.KeyMap("my-element", {
14333 key: 13, // or Roo.EventObject.ENTER
14338 // map multiple keys to one action by string
14339 var map = new Roo.KeyMap("my-element", {
14345 // map multiple keys to multiple actions by strings and array of codes
14346 var map = new Roo.KeyMap("my-element", [
14349 fn: function(){ alert("Return was pressed"); }
14352 fn: function(){ alert('a, b or c was pressed'); }
14357 fn: function(){ alert('Control + shift + tab was pressed.'); }
14361 * <b>Note: A KeyMap starts enabled</b>
14363 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14364 * @param {Object} config The config (see {@link #addBinding})
14365 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14367 Roo.KeyMap = function(el, config, eventName){
14368 this.el = Roo.get(el);
14369 this.eventName = eventName || "keydown";
14370 this.bindings = [];
14372 this.addBinding(config);
14377 Roo.KeyMap.prototype = {
14379 * True to stop the event from bubbling and prevent the default browser action if the
14380 * key was handled by the KeyMap (defaults to false)
14386 * Add a new binding to this KeyMap. The following config object properties are supported:
14388 Property Type Description
14389 ---------- --------------- ----------------------------------------------------------------------
14390 key String/Array A single keycode or an array of keycodes to handle
14391 shift Boolean True to handle key only when shift is pressed (defaults to false)
14392 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14393 alt Boolean True to handle key only when alt is pressed (defaults to false)
14394 fn Function The function to call when KeyMap finds the expected key combination
14395 scope Object The scope of the callback function
14401 var map = new Roo.KeyMap(document, {
14402 key: Roo.EventObject.ENTER,
14407 //Add a new binding to the existing KeyMap later
14415 * @param {Object/Array} config A single KeyMap config or an array of configs
14417 addBinding : function(config){
14418 if(config instanceof Array){
14419 for(var i = 0, len = config.length; i < len; i++){
14420 this.addBinding(config[i]);
14424 var keyCode = config.key,
14425 shift = config.shift,
14426 ctrl = config.ctrl,
14429 scope = config.scope;
14430 if(typeof keyCode == "string"){
14432 var keyString = keyCode.toUpperCase();
14433 for(var j = 0, len = keyString.length; j < len; j++){
14434 ks.push(keyString.charCodeAt(j));
14438 var keyArray = keyCode instanceof Array;
14439 var handler = function(e){
14440 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14441 var k = e.getKey();
14443 for(var i = 0, len = keyCode.length; i < len; i++){
14444 if(keyCode[i] == k){
14445 if(this.stopEvent){
14448 fn.call(scope || window, k, e);
14454 if(this.stopEvent){
14457 fn.call(scope || window, k, e);
14462 this.bindings.push(handler);
14466 * Shorthand for adding a single key listener
14467 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14468 * following options:
14469 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14470 * @param {Function} fn The function to call
14471 * @param {Object} scope (optional) The scope of the function
14473 on : function(key, fn, scope){
14474 var keyCode, shift, ctrl, alt;
14475 if(typeof key == "object" && !(key instanceof Array)){
14494 handleKeyDown : function(e){
14495 if(this.enabled){ //just in case
14496 var b = this.bindings;
14497 for(var i = 0, len = b.length; i < len; i++){
14498 b[i].call(this, e);
14504 * Returns true if this KeyMap is enabled
14505 * @return {Boolean}
14507 isEnabled : function(){
14508 return this.enabled;
14512 * Enables this KeyMap
14514 enable: function(){
14516 this.el.on(this.eventName, this.handleKeyDown, this);
14517 this.enabled = true;
14522 * Disable this KeyMap
14524 disable: function(){
14526 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14527 this.enabled = false;
14532 * Ext JS Library 1.1.1
14533 * Copyright(c) 2006-2007, Ext JS, LLC.
14535 * Originally Released Under LGPL - original licence link has changed is not relivant.
14538 * <script type="text/javascript">
14543 * @class Roo.util.TextMetrics
14544 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14545 * wide, in pixels, a given block of text will be.
14548 Roo.util.TextMetrics = function(){
14552 * Measures the size of the specified text
14553 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14554 * that can affect the size of the rendered text
14555 * @param {String} text The text to measure
14556 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14557 * in order to accurately measure the text height
14558 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14560 measure : function(el, text, fixedWidth){
14562 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14565 shared.setFixedWidth(fixedWidth || 'auto');
14566 return shared.getSize(text);
14570 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14571 * the overhead of multiple calls to initialize the style properties on each measurement.
14572 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14573 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14574 * in order to accurately measure the text height
14575 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14577 createInstance : function(el, fixedWidth){
14578 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14585 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14586 var ml = new Roo.Element(document.createElement('div'));
14587 document.body.appendChild(ml.dom);
14588 ml.position('absolute');
14589 ml.setLeftTop(-1000, -1000);
14593 ml.setWidth(fixedWidth);
14598 * Returns the size of the specified text based on the internal element's style and width properties
14599 * @memberOf Roo.util.TextMetrics.Instance#
14600 * @param {String} text The text to measure
14601 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14603 getSize : function(text){
14605 var s = ml.getSize();
14611 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14612 * that can affect the size of the rendered text
14613 * @memberOf Roo.util.TextMetrics.Instance#
14614 * @param {String/HTMLElement} el The element, dom node or id
14616 bind : function(el){
14618 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14623 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14624 * to set a fixed width in order to accurately measure the text height.
14625 * @memberOf Roo.util.TextMetrics.Instance#
14626 * @param {Number} width The width to set on the element
14628 setFixedWidth : function(width){
14629 ml.setWidth(width);
14633 * Returns the measured width of the specified text
14634 * @memberOf Roo.util.TextMetrics.Instance#
14635 * @param {String} text The text to measure
14636 * @return {Number} width The width in pixels
14638 getWidth : function(text){
14639 ml.dom.style.width = 'auto';
14640 return this.getSize(text).width;
14644 * Returns the measured height of the specified text. For multiline text, be sure to call
14645 * {@link #setFixedWidth} if necessary.
14646 * @memberOf Roo.util.TextMetrics.Instance#
14647 * @param {String} text The text to measure
14648 * @return {Number} height The height in pixels
14650 getHeight : function(text){
14651 return this.getSize(text).height;
14655 instance.bind(bindTo);
14660 // backwards compat
14661 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14663 * Ext JS Library 1.1.1
14664 * Copyright(c) 2006-2007, Ext JS, LLC.
14666 * Originally Released Under LGPL - original licence link has changed is not relivant.
14669 * <script type="text/javascript">
14673 * @class Roo.state.Provider
14674 * Abstract base class for state provider implementations. This class provides methods
14675 * for encoding and decoding <b>typed</b> variables including dates and defines the
14676 * Provider interface.
14678 Roo.state.Provider = function(){
14680 * @event statechange
14681 * Fires when a state change occurs.
14682 * @param {Provider} this This state provider
14683 * @param {String} key The state key which was changed
14684 * @param {String} value The encoded value for the state
14687 "statechange": true
14690 Roo.state.Provider.superclass.constructor.call(this);
14692 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14694 * Returns the current value for a key
14695 * @param {String} name The key name
14696 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14697 * @return {Mixed} The state data
14699 get : function(name, defaultValue){
14700 return typeof this.state[name] == "undefined" ?
14701 defaultValue : this.state[name];
14705 * Clears a value from the state
14706 * @param {String} name The key name
14708 clear : function(name){
14709 delete this.state[name];
14710 this.fireEvent("statechange", this, name, null);
14714 * Sets the value for a key
14715 * @param {String} name The key name
14716 * @param {Mixed} value The value to set
14718 set : function(name, value){
14719 this.state[name] = value;
14720 this.fireEvent("statechange", this, name, value);
14724 * Decodes a string previously encoded with {@link #encodeValue}.
14725 * @param {String} value The value to decode
14726 * @return {Mixed} The decoded value
14728 decodeValue : function(cookie){
14729 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14730 var matches = re.exec(unescape(cookie));
14731 if(!matches || !matches[1]) return; // non state cookie
14732 var type = matches[1];
14733 var v = matches[2];
14736 return parseFloat(v);
14738 return new Date(Date.parse(v));
14743 var values = v.split("^");
14744 for(var i = 0, len = values.length; i < len; i++){
14745 all.push(this.decodeValue(values[i]));
14750 var values = v.split("^");
14751 for(var i = 0, len = values.length; i < len; i++){
14752 var kv = values[i].split("=");
14753 all[kv[0]] = this.decodeValue(kv[1]);
14762 * Encodes a value including type information. Decode with {@link #decodeValue}.
14763 * @param {Mixed} value The value to encode
14764 * @return {String} The encoded value
14766 encodeValue : function(v){
14768 if(typeof v == "number"){
14770 }else if(typeof v == "boolean"){
14771 enc = "b:" + (v ? "1" : "0");
14772 }else if(v instanceof Date){
14773 enc = "d:" + v.toGMTString();
14774 }else if(v instanceof Array){
14776 for(var i = 0, len = v.length; i < len; i++){
14777 flat += this.encodeValue(v[i]);
14778 if(i != len-1) flat += "^";
14781 }else if(typeof v == "object"){
14784 if(typeof v[key] != "function"){
14785 flat += key + "=" + this.encodeValue(v[key]) + "^";
14788 enc = "o:" + flat.substring(0, flat.length-1);
14792 return escape(enc);
14798 * Ext JS Library 1.1.1
14799 * Copyright(c) 2006-2007, Ext JS, LLC.
14801 * Originally Released Under LGPL - original licence link has changed is not relivant.
14804 * <script type="text/javascript">
14807 * @class Roo.state.Manager
14808 * This is the global state manager. By default all components that are "state aware" check this class
14809 * for state information if you don't pass them a custom state provider. In order for this class
14810 * to be useful, it must be initialized with a provider when your application initializes.
14812 // in your initialization function
14814 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14816 // supposed you have a {@link Roo.BorderLayout}
14817 var layout = new Roo.BorderLayout(...);
14818 layout.restoreState();
14819 // or a {Roo.BasicDialog}
14820 var dialog = new Roo.BasicDialog(...);
14821 dialog.restoreState();
14825 Roo.state.Manager = function(){
14826 var provider = new Roo.state.Provider();
14830 * Configures the default state provider for your application
14831 * @param {Provider} stateProvider The state provider to set
14833 setProvider : function(stateProvider){
14834 provider = stateProvider;
14838 * Returns the current value for a key
14839 * @param {String} name The key name
14840 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14841 * @return {Mixed} The state data
14843 get : function(key, defaultValue){
14844 return provider.get(key, defaultValue);
14848 * Sets the value for a key
14849 * @param {String} name The key name
14850 * @param {Mixed} value The state data
14852 set : function(key, value){
14853 provider.set(key, value);
14857 * Clears a value from the state
14858 * @param {String} name The key name
14860 clear : function(key){
14861 provider.clear(key);
14865 * Gets the currently configured state provider
14866 * @return {Provider} The state provider
14868 getProvider : function(){
14875 * Ext JS Library 1.1.1
14876 * Copyright(c) 2006-2007, Ext JS, LLC.
14878 * Originally Released Under LGPL - original licence link has changed is not relivant.
14881 * <script type="text/javascript">
14884 * @class Roo.state.CookieProvider
14885 * @extends Roo.state.Provider
14886 * The default Provider implementation which saves state via cookies.
14889 var cp = new Roo.state.CookieProvider({
14891 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14892 domain: "roojs.com"
14894 Roo.state.Manager.setProvider(cp);
14896 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14897 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14898 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14899 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14900 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14901 * domain the page is running on including the 'www' like 'www.roojs.com')
14902 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14904 * Create a new CookieProvider
14905 * @param {Object} config The configuration object
14907 Roo.state.CookieProvider = function(config){
14908 Roo.state.CookieProvider.superclass.constructor.call(this);
14910 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14911 this.domain = null;
14912 this.secure = false;
14913 Roo.apply(this, config);
14914 this.state = this.readCookies();
14917 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14919 set : function(name, value){
14920 if(typeof value == "undefined" || value === null){
14924 this.setCookie(name, value);
14925 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14929 clear : function(name){
14930 this.clearCookie(name);
14931 Roo.state.CookieProvider.superclass.clear.call(this, name);
14935 readCookies : function(){
14937 var c = document.cookie + ";";
14938 var re = /\s?(.*?)=(.*?);/g;
14940 while((matches = re.exec(c)) != null){
14941 var name = matches[1];
14942 var value = matches[2];
14943 if(name && name.substring(0,3) == "ys-"){
14944 cookies[name.substr(3)] = this.decodeValue(value);
14951 setCookie : function(name, value){
14952 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14953 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14954 ((this.path == null) ? "" : ("; path=" + this.path)) +
14955 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14956 ((this.secure == true) ? "; secure" : "");
14960 clearCookie : function(name){
14961 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14962 ((this.path == null) ? "" : ("; path=" + this.path)) +
14963 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14964 ((this.secure == true) ? "; secure" : "");