4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0,
64 isTouch = (function() {
66 document.createEvent("TouchEvent");
73 // remove css image flicker
76 document.execCommand("BackgroundImageCache", false, true);
82 * True if the browser is in strict mode
87 * True if the page is running over SSL
92 * True when the document is fully initialized and ready for action
97 * Turn on debugging output (currently only the factory uses this)
104 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
107 enableGarbageCollector : true,
110 * True to automatically purge event listeners after uncaching an element (defaults to false).
111 * Note: this only happens if enableGarbageCollector is true.
114 enableListenerCollection:false,
117 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
118 * the IE insecure content warning (defaults to javascript:false).
121 SSL_SECURE_URL : "javascript:false",
124 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
125 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
128 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
130 emptyFn : function(){},
133 * Copies all the properties of config to obj if they don't already exist.
134 * @param {Object} obj The receiver of the properties
135 * @param {Object} config The source of the properties
136 * @return {Object} returns obj
138 applyIf : function(o, c){
141 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
148 * Applies event listeners to elements by selectors when the document is ready.
149 * The event name is specified with an @ suffix.
152 // add a listener for click on all anchors in element with id foo
153 '#foo a@click' : function(e, t){
157 // add the same listener to multiple selectors (separated by comma BEFORE the @)
158 '#foo a, #bar span.some-class@mouseover' : function(){
163 * @param {Object} obj The list of behaviors to apply
165 addBehaviors : function(o){
167 Roo.onReady(function(){
172 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
174 var parts = b.split('@');
175 if(parts[1]){ // for Object prototype breakers
178 cache[s] = Roo.select(s);
180 cache[s].on(parts[1], o[b]);
187 * Generates unique ids. If the element already has an id, it is unchanged
188 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
189 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
190 * @return {String} The generated Id.
192 id : function(el, prefix){
193 prefix = prefix || "roo-gen";
195 var id = prefix + (++idSeed);
196 return el ? (el.id ? el.id : (el.id = id)) : id;
201 * Extends one class with another class and optionally overrides members with the passed literal. This class
202 * also adds the function "override()" to the class that can be used to override
203 * members on an instance.
204 * @param {Object} subclass The class inheriting the functionality
205 * @param {Object} superclass The class being extended
206 * @param {Object} overrides (optional) A literal with members
211 var io = function(o){
216 return function(sb, sp, overrides){
217 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
220 sb = function(){sp.apply(this, arguments);};
222 var F = function(){}, sbp, spp = sp.prototype;
224 sbp = sb.prototype = new F();
228 if(spp.constructor == Object.prototype.constructor){
233 sb.override = function(o){
237 Roo.override(sb, overrides);
243 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
245 Roo.override(MyClass, {
246 newMethod1: function(){
249 newMethod2: function(foo){
254 * @param {Object} origclass The class to override
255 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
256 * containing one or more methods.
259 override : function(origclass, overrides){
261 var p = origclass.prototype;
262 for(var method in overrides){
263 p[method] = overrides[method];
268 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
270 Roo.namespace('Company', 'Company.data');
271 Company.Widget = function() { ... }
272 Company.data.CustomStore = function(config) { ... }
274 * @param {String} namespace1
275 * @param {String} namespace2
276 * @param {String} etc
279 namespace : function(){
280 var a=arguments, o=null, i, j, d, rt;
281 for (i=0; i<a.length; ++i) {
285 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
286 for (j=1; j<d.length; ++j) {
287 o[d[j]]=o[d[j]] || {};
293 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
295 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
296 Roo.factory(conf, Roo.data);
298 * @param {String} classname
299 * @param {String} namespace (optional)
303 factory : function(c, ns)
305 // no xtype, no ns or c.xns - or forced off by c.xns
306 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
309 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
310 if (c.constructor == ns[c.xtype]) {// already created...
314 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
315 var ret = new ns[c.xtype](c);
319 c.xns = false; // prevent recursion..
323 * Logs to console if it can.
325 * @param {String|Object} string
330 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
337 * 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.
341 urlEncode : function(o){
347 var ov = o[key], k = Roo.encodeURIComponent(key);
348 var type = typeof ov;
349 if(type == 'undefined'){
351 }else if(type != "function" && type != "object"){
352 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
353 }else if(ov instanceof Array){
355 for(var i = 0, len = ov.length; i < len; i++) {
356 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
367 * Safe version of encodeURIComponent
368 * @param {String} data
372 encodeURIComponent : function (data)
375 return encodeURIComponent(data);
376 } catch(e) {} // should be an uri encode error.
378 if (data == '' || data == null){
381 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
382 function nibble_to_hex(nibble){
383 var chars = '0123456789ABCDEF';
384 return chars.charAt(nibble);
386 data = data.toString();
388 for(var i=0; i<data.length; i++){
389 var c = data.charCodeAt(i);
390 var bs = new Array();
393 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
394 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
395 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
396 bs[3] = 0x80 | (c & 0x3F);
397 }else if (c > 0x800){
399 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
400 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
401 bs[2] = 0x80 | (c & 0x3F);
404 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
405 bs[1] = 0x80 | (c & 0x3F);
410 for(var j=0; j<bs.length; j++){
412 var hex = nibble_to_hex((b & 0xF0) >>> 4)
413 + nibble_to_hex(b &0x0F);
422 * 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]}.
423 * @param {String} string
424 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
425 * @return {Object} A literal with members
427 urlDecode : function(string, overwrite){
428 if(!string || !string.length){
432 var pairs = string.split('&');
433 var pair, name, value;
434 for(var i = 0, len = pairs.length; i < len; i++){
435 pair = pairs[i].split('=');
436 name = decodeURIComponent(pair[0]);
437 value = decodeURIComponent(pair[1]);
438 if(overwrite !== true){
439 if(typeof obj[name] == "undefined"){
441 }else if(typeof obj[name] == "string"){
442 obj[name] = [obj[name]];
443 obj[name].push(value);
445 obj[name].push(value);
455 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
456 * passed array is not really an array, your function is called once with it.
457 * The supplied function is called with (Object item, Number index, Array allItems).
458 * @param {Array/NodeList/Mixed} array
459 * @param {Function} fn
460 * @param {Object} scope
462 each : function(array, fn, scope){
463 if(typeof array.length == "undefined" || typeof array == "string"){
466 for(var i = 0, len = array.length; i < len; i++){
467 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
472 combine : function(){
473 var as = arguments, l = as.length, r = [];
474 for(var i = 0; i < l; i++){
476 if(a instanceof Array){
478 }else if(a.length !== undefined && !a.substr){
479 r = r.concat(Array.prototype.slice.call(a, 0));
488 * Escapes the passed string for use in a regular expression
489 * @param {String} str
492 escapeRe : function(s) {
493 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
497 callback : function(cb, scope, args, delay){
498 if(typeof cb == "function"){
500 cb.defer(delay, scope, args || []);
502 cb.apply(scope, args || []);
508 * Return the dom node for the passed string (id), dom node, or Roo.Element
509 * @param {String/HTMLElement/Roo.Element} el
510 * @return HTMLElement
512 getDom : function(el){
516 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
520 * Shorthand for {@link Roo.ComponentMgr#get}
522 * @return Roo.Component
524 getCmp : function(id){
525 return Roo.ComponentMgr.get(id);
528 num : function(v, defaultValue){
529 if(typeof v != 'number'){
535 destroy : function(){
536 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
540 as.removeAllListeners();
544 if(typeof as.purgeListeners == 'function'){
547 if(typeof as.destroy == 'function'){
554 // inpired by a similar function in mootools library
556 * Returns the type of object that is passed in. If the object passed in is null or undefined it
557 * return false otherwise it returns one of the following values:<ul>
558 * <li><b>string</b>: If the object passed is a string</li>
559 * <li><b>number</b>: If the object passed is a number</li>
560 * <li><b>boolean</b>: If the object passed is a boolean value</li>
561 * <li><b>function</b>: If the object passed is a function reference</li>
562 * <li><b>object</b>: If the object passed is an object</li>
563 * <li><b>array</b>: If the object passed is an array</li>
564 * <li><b>regexp</b>: If the object passed is a regular expression</li>
565 * <li><b>element</b>: If the object passed is a DOM Element</li>
566 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
567 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
568 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
569 * @param {Mixed} object
573 if(o === undefined || o === null){
580 if(t == 'object' && o.nodeName) {
582 case 1: return 'element';
583 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
586 if(t == 'object' || t == 'function') {
587 switch(o.constructor) {
588 case Array: return 'array';
589 case RegExp: return 'regexp';
591 if(typeof o.length == 'number' && typeof o.item == 'function') {
599 * Returns true if the passed value is null, undefined or an empty string (optional).
600 * @param {Mixed} value The value to test
601 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
604 isEmpty : function(v, allowBlank){
605 return v === null || v === undefined || (!allowBlank ? v === '' : false);
619 isBorderBox : isBorderBox,
621 isWindows : isWindows,
630 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
631 * you may want to set this to true.
634 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
639 * Selects a single element as a Roo Element
640 * This is about as close as you can get to jQuery's $('do crazy stuff')
641 * @param {String} selector The selector/xpath query
642 * @param {Node} root (optional) The start of the query (defaults to document).
643 * @return {Roo.Element}
645 selectNode : function(selector, root)
647 var node = Roo.DomQuery.selectNode(selector,root);
648 return node ? Roo.get(node) : new Roo.Element(false);
656 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
657 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout",
660 "Roo.bootstrap.dash");
663 * Ext JS Library 1.1.1
664 * Copyright(c) 2006-2007, Ext JS, LLC.
666 * Originally Released Under LGPL - original licence link has changed is not relivant.
669 * <script type="text/javascript">
673 // wrappedn so fnCleanup is not in global scope...
675 function fnCleanUp() {
676 var p = Function.prototype;
677 delete p.createSequence;
679 delete p.createDelegate;
680 delete p.createCallback;
681 delete p.createInterceptor;
683 window.detachEvent("onunload", fnCleanUp);
685 window.attachEvent("onunload", fnCleanUp);
692 * These functions are available on every Function object (any JavaScript function).
694 Roo.apply(Function.prototype, {
696 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
697 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
698 * Will create a function that is bound to those 2 args.
699 * @return {Function} The new function
701 createCallback : function(/*args...*/){
702 // make args available, in function below
703 var args = arguments;
706 return method.apply(window, args);
711 * Creates a delegate (callback) that sets the scope to obj.
712 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
713 * Will create a function that is automatically scoped to this.
714 * @param {Object} obj (optional) The object for which the scope is set
715 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
716 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
717 * if a number the args are inserted at the specified position
718 * @return {Function} The new function
720 createDelegate : function(obj, args, appendArgs){
723 var callArgs = args || arguments;
724 if(appendArgs === true){
725 callArgs = Array.prototype.slice.call(arguments, 0);
726 callArgs = callArgs.concat(args);
727 }else if(typeof appendArgs == "number"){
728 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
729 var applyArgs = [appendArgs, 0].concat(args); // create method call params
730 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
732 return method.apply(obj || window, callArgs);
737 * Calls this function after the number of millseconds specified.
738 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
739 * @param {Object} obj (optional) The object for which the scope is set
740 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
741 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
742 * if a number the args are inserted at the specified position
743 * @return {Number} The timeout id that can be used with clearTimeout
745 defer : function(millis, obj, args, appendArgs){
746 var fn = this.createDelegate(obj, args, appendArgs);
748 return setTimeout(fn, millis);
754 * Create a combined function call sequence of the original function + the passed function.
755 * The resulting function returns the results of the original function.
756 * The passed fcn is called with the parameters of the original function
757 * @param {Function} fcn The function to sequence
758 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
759 * @return {Function} The new function
761 createSequence : function(fcn, scope){
762 if(typeof fcn != "function"){
767 var retval = method.apply(this || window, arguments);
768 fcn.apply(scope || this || window, arguments);
774 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
775 * The resulting function returns the results of the original function.
776 * The passed fcn is called with the parameters of the original function.
778 * @param {Function} fcn The function to call before the original
779 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
780 * @return {Function} The new function
782 createInterceptor : function(fcn, scope){
783 if(typeof fcn != "function"){
790 if(fcn.apply(scope || this || window, arguments) === false){
793 return method.apply(this || window, arguments);
799 * Ext JS Library 1.1.1
800 * Copyright(c) 2006-2007, Ext JS, LLC.
802 * Originally Released Under LGPL - original licence link has changed is not relivant.
805 * <script type="text/javascript">
808 Roo.applyIf(String, {
813 * Escapes the passed string for ' and \
814 * @param {String} string The string to escape
815 * @return {String} The escaped string
818 escape : function(string) {
819 return string.replace(/('|\\)/g, "\\$1");
823 * Pads the left side of a string with a specified character. This is especially useful
824 * for normalizing number and date strings. Example usage:
826 var s = String.leftPad('123', 5, '0');
827 // s now contains the string: '00123'
829 * @param {String} string The original string
830 * @param {Number} size The total length of the output string
831 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
832 * @return {String} The padded string
835 leftPad : function (val, size, ch) {
836 var result = new String(val);
837 if(ch === null || ch === undefined || ch === '') {
840 while (result.length < size) {
841 result = ch + result;
847 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
848 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
850 var cls = 'my-class', text = 'Some text';
851 var s = String.format('<div class="{0}">{1}</div>', cls, text);
852 // s now contains the string: '<div class="my-class">Some text</div>'
854 * @param {String} string The tokenized string to be formatted
855 * @param {String} value1 The value to replace token {0}
856 * @param {String} value2 Etc...
857 * @return {String} The formatted string
860 format : function(format){
861 var args = Array.prototype.slice.call(arguments, 1);
862 return format.replace(/\{(\d+)\}/g, function(m, i){
863 return Roo.util.Format.htmlEncode(args[i]);
869 * Utility function that allows you to easily switch a string between two alternating values. The passed value
870 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
871 * they are already different, the first value passed in is returned. Note that this method returns the new value
872 * but does not change the current string.
874 // alternate sort directions
875 sort = sort.toggle('ASC', 'DESC');
877 // instead of conditional logic:
878 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
880 * @param {String} value The value to compare to the current string
881 * @param {String} other The new value to use if the string already equals the first value passed in
882 * @return {String} The new value
885 String.prototype.toggle = function(value, other){
886 return this == value ? other : value;
889 * Ext JS Library 1.1.1
890 * Copyright(c) 2006-2007, Ext JS, LLC.
892 * Originally Released Under LGPL - original licence link has changed is not relivant.
895 * <script type="text/javascript">
901 Roo.applyIf(Number.prototype, {
903 * Checks whether or not the current number is within a desired range. If the number is already within the
904 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
905 * exceeded. Note that this method returns the constrained value but does not change the current number.
906 * @param {Number} min The minimum number in the range
907 * @param {Number} max The maximum number in the range
908 * @return {Number} The constrained value if outside the range, otherwise the current value
910 constrain : function(min, max){
911 return Math.min(Math.max(this, min), max);
915 * Ext JS Library 1.1.1
916 * Copyright(c) 2006-2007, Ext JS, LLC.
918 * Originally Released Under LGPL - original licence link has changed is not relivant.
921 * <script type="text/javascript">
926 Roo.applyIf(Array.prototype, {
929 * Checks whether or not the specified object exists in the array.
930 * @param {Object} o The object to check for
931 * @return {Number} The index of o in the array (or -1 if it is not found)
933 indexOf : function(o){
934 for (var i = 0, len = this.length; i < len; i++){
935 if(this[i] == o) return i;
941 * Removes the specified object from the array. If the object is not found nothing happens.
942 * @param {Object} o The object to remove
944 remove : function(o){
945 var index = this.indexOf(o);
947 this.splice(index, 1);
951 * Map (JS 1.6 compatibility)
952 * @param {Function} function to call
956 var len = this.length >>> 0;
957 if (typeof fun != "function")
958 throw new TypeError();
960 var res = new Array(len);
961 var thisp = arguments[1];
962 for (var i = 0; i < len; i++)
965 res[i] = fun.call(thisp, this[i], i, this);
976 * Ext JS Library 1.1.1
977 * Copyright(c) 2006-2007, Ext JS, LLC.
979 * Originally Released Under LGPL - original licence link has changed is not relivant.
982 * <script type="text/javascript">
988 * The date parsing and format syntax is a subset of
989 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
990 * supported will provide results equivalent to their PHP versions.
992 * Following is the list of all currently supported formats:
995 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
997 Format Output Description
998 ------ ---------- --------------------------------------------------------------
999 d 10 Day of the month, 2 digits with leading zeros
1000 D Wed A textual representation of a day, three letters
1001 j 10 Day of the month without leading zeros
1002 l Wednesday A full textual representation of the day of the week
1003 S th English ordinal day of month suffix, 2 chars (use with j)
1004 w 3 Numeric representation of the day of the week
1005 z 9 The julian date, or day of the year (0-365)
1006 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
1007 F January A full textual representation of the month
1008 m 01 Numeric representation of a month, with leading zeros
1009 M Jan Month name abbreviation, three letters
1010 n 1 Numeric representation of a month, without leading zeros
1011 t 31 Number of days in the given month
1012 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1013 Y 2007 A full numeric representation of a year, 4 digits
1014 y 07 A two digit representation of a year
1015 a pm Lowercase Ante meridiem and Post meridiem
1016 A PM Uppercase Ante meridiem and Post meridiem
1017 g 3 12-hour format of an hour without leading zeros
1018 G 15 24-hour format of an hour without leading zeros
1019 h 03 12-hour format of an hour with leading zeros
1020 H 15 24-hour format of an hour with leading zeros
1021 i 05 Minutes with leading zeros
1022 s 01 Seconds, with leading zeros
1023 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1024 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1025 T CST Timezone setting of the machine running the code
1026 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1029 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1031 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1032 document.write(dt.format('Y-m-d')); //2007-01-10
1033 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1034 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
1037 * Here are some standard date/time patterns that you might find helpful. They
1038 * are not part of the source of Date.js, but to use them you can simply copy this
1039 * block of code into any script that is included after Date.js and they will also become
1040 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1043 ISO8601Long:"Y-m-d H:i:s",
1044 ISO8601Short:"Y-m-d",
1046 LongDate: "l, F d, Y",
1047 FullDateTime: "l, F d, Y g:i:s A",
1050 LongTime: "g:i:s A",
1051 SortableDateTime: "Y-m-d\\TH:i:s",
1052 UniversalSortableDateTime: "Y-m-d H:i:sO",
1059 var dt = new Date();
1060 document.write(dt.format(Date.patterns.ShortDate));
1065 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1066 * They generate precompiled functions from date formats instead of parsing and
1067 * processing the pattern every time you format a date. These functions are available
1068 * on every Date object (any javascript function).
1070 * The original article and download are here:
1071 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1078 Returns the number of milliseconds between this date and date
1079 @param {Date} date (optional) Defaults to now
1080 @return {Number} The diff in milliseconds
1081 @member Date getElapsed
1083 Date.prototype.getElapsed = function(date) {
1084 return Math.abs((date || new Date()).getTime()-this.getTime());
1086 // was in date file..
1090 Date.parseFunctions = {count:0};
1092 Date.parseRegexes = [];
1094 Date.formatFunctions = {count:0};
1097 Date.prototype.dateFormat = function(format) {
1098 if (Date.formatFunctions[format] == null) {
1099 Date.createNewFormat(format);
1101 var func = Date.formatFunctions[format];
1102 return this[func]();
1107 * Formats a date given the supplied format string
1108 * @param {String} format The format string
1109 * @return {String} The formatted date
1112 Date.prototype.format = Date.prototype.dateFormat;
1115 Date.createNewFormat = function(format) {
1116 var funcName = "format" + Date.formatFunctions.count++;
1117 Date.formatFunctions[format] = funcName;
1118 var code = "Date.prototype." + funcName + " = function(){return ";
1119 var special = false;
1121 for (var i = 0; i < format.length; ++i) {
1122 ch = format.charAt(i);
1123 if (!special && ch == "\\") {
1128 code += "'" + String.escape(ch) + "' + ";
1131 code += Date.getFormatCode(ch);
1134 /** eval:var:zzzzzzzzzzzzz */
1135 eval(code.substring(0, code.length - 3) + ";}");
1139 Date.getFormatCode = function(character) {
1140 switch (character) {
1142 return "String.leftPad(this.getDate(), 2, '0') + ";
1144 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1146 return "this.getDate() + ";
1148 return "Date.dayNames[this.getDay()] + ";
1150 return "this.getSuffix() + ";
1152 return "this.getDay() + ";
1154 return "this.getDayOfYear() + ";
1156 return "this.getWeekOfYear() + ";
1158 return "Date.monthNames[this.getMonth()] + ";
1160 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1162 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1164 return "(this.getMonth() + 1) + ";
1166 return "this.getDaysInMonth() + ";
1168 return "(this.isLeapYear() ? 1 : 0) + ";
1170 return "this.getFullYear() + ";
1172 return "('' + this.getFullYear()).substring(2, 4) + ";
1174 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1176 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1178 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1180 return "this.getHours() + ";
1182 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1184 return "String.leftPad(this.getHours(), 2, '0') + ";
1186 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1188 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1190 return "this.getGMTOffset() + ";
1192 return "this.getGMTColonOffset() + ";
1194 return "this.getTimezone() + ";
1196 return "(this.getTimezoneOffset() * -60) + ";
1198 return "'" + String.escape(character) + "' + ";
1203 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1204 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1205 * the date format that is not specified will default to the current date value for that part. Time parts can also
1206 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1207 * string or the parse operation will fail.
1210 //dt = Fri May 25 2007 (current date)
1211 var dt = new Date();
1213 //dt = Thu May 25 2006 (today's month/day in 2006)
1214 dt = Date.parseDate("2006", "Y");
1216 //dt = Sun Jan 15 2006 (all date parts specified)
1217 dt = Date.parseDate("2006-1-15", "Y-m-d");
1219 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1220 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1222 * @param {String} input The unparsed date as a string
1223 * @param {String} format The format the date is in
1224 * @return {Date} The parsed date
1227 Date.parseDate = function(input, format) {
1228 if (Date.parseFunctions[format] == null) {
1229 Date.createParser(format);
1231 var func = Date.parseFunctions[format];
1232 return Date[func](input);
1238 Date.createParser = function(format) {
1239 var funcName = "parse" + Date.parseFunctions.count++;
1240 var regexNum = Date.parseRegexes.length;
1241 var currentGroup = 1;
1242 Date.parseFunctions[format] = funcName;
1244 var code = "Date." + funcName + " = function(input){\n"
1245 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1246 + "var d = new Date();\n"
1247 + "y = d.getFullYear();\n"
1248 + "m = d.getMonth();\n"
1249 + "d = d.getDate();\n"
1250 + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
1251 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1252 + "if (results && results.length > 0) {";
1255 var special = false;
1257 for (var i = 0; i < format.length; ++i) {
1258 ch = format.charAt(i);
1259 if (!special && ch == "\\") {
1264 regex += String.escape(ch);
1267 var obj = Date.formatCodeToRegex(ch, currentGroup);
1268 currentGroup += obj.g;
1270 if (obj.g && obj.c) {
1276 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1277 + "{v = new Date(y, m, d, h, i, s);}\n"
1278 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1279 + "{v = new Date(y, m, d, h, i);}\n"
1280 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1281 + "{v = new Date(y, m, d, h);}\n"
1282 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1283 + "{v = new Date(y, m, d);}\n"
1284 + "else if (y >= 0 && m >= 0)\n"
1285 + "{v = new Date(y, m);}\n"
1286 + "else if (y >= 0)\n"
1287 + "{v = new Date(y);}\n"
1288 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1289 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1290 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1293 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1294 /** eval:var:zzzzzzzzzzzzz */
1299 Date.formatCodeToRegex = function(character, currentGroup) {
1300 switch (character) {
1304 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1307 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1308 s:"(\\d{1,2})"}; // day of month without leading zeroes
1311 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1312 s:"(\\d{2})"}; // day of month with leading zeroes
1316 s:"(?:" + Date.dayNames.join("|") + ")"};
1320 s:"(?:st|nd|rd|th)"};
1335 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1336 s:"(" + Date.monthNames.join("|") + ")"};
1339 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1340 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1343 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1344 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1347 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1348 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1359 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1363 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1364 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1368 c:"if (results[" + currentGroup + "] == 'am') {\n"
1369 + "if (h == 12) { h = 0; }\n"
1370 + "} else { if (h < 12) { h += 12; }}",
1374 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1375 + "if (h == 12) { h = 0; }\n"
1376 + "} else { if (h < 12) { h += 12; }}",
1381 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1382 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1386 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1387 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1390 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1394 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1399 "o = results[", currentGroup, "];\n",
1400 "var sn = o.substring(0,1);\n", // get + / - sign
1401 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1402 "var mn = o.substring(3,5) % 60;\n", // get minutes
1403 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1404 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1406 s:"([+\-]\\d{2,4})"};
1412 "o = results[", currentGroup, "];\n",
1413 "var sn = o.substring(0,1);\n",
1414 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1415 "var mn = o.substring(4,6) % 60;\n",
1416 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1417 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1423 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1426 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1427 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1428 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1432 s:String.escape(character)};
1437 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1438 * @return {String} The abbreviated timezone name (e.g. 'CST')
1440 Date.prototype.getTimezone = function() {
1441 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1445 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1446 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1448 Date.prototype.getGMTOffset = function() {
1449 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1450 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1451 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1455 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1456 * @return {String} 2-characters representing hours and 2-characters representing minutes
1457 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1459 Date.prototype.getGMTColonOffset = function() {
1460 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1461 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1463 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1467 * Get the numeric day number of the year, adjusted for leap year.
1468 * @return {Number} 0 through 364 (365 in leap years)
1470 Date.prototype.getDayOfYear = function() {
1472 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1473 for (var i = 0; i < this.getMonth(); ++i) {
1474 num += Date.daysInMonth[i];
1476 return num + this.getDate() - 1;
1480 * Get the string representation of the numeric week number of the year
1481 * (equivalent to the format specifier 'W').
1482 * @return {String} '00' through '52'
1484 Date.prototype.getWeekOfYear = function() {
1485 // Skip to Thursday of this week
1486 var now = this.getDayOfYear() + (4 - this.getDay());
1487 // Find the first Thursday of the year
1488 var jan1 = new Date(this.getFullYear(), 0, 1);
1489 var then = (7 - jan1.getDay() + 4);
1490 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1494 * Whether or not the current date is in a leap year.
1495 * @return {Boolean} True if the current date is in a leap year, else false
1497 Date.prototype.isLeapYear = function() {
1498 var year = this.getFullYear();
1499 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1503 * Get the first day of the current month, adjusted for leap year. The returned value
1504 * is the numeric day index within the week (0-6) which can be used in conjunction with
1505 * the {@link #monthNames} array to retrieve the textual day name.
1508 var dt = new Date('1/10/2007');
1509 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1511 * @return {Number} The day number (0-6)
1513 Date.prototype.getFirstDayOfMonth = function() {
1514 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1515 return (day < 0) ? (day + 7) : day;
1519 * Get the last day of the current month, adjusted for leap year. The returned value
1520 * is the numeric day index within the week (0-6) which can be used in conjunction with
1521 * the {@link #monthNames} array to retrieve the textual day name.
1524 var dt = new Date('1/10/2007');
1525 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1527 * @return {Number} The day number (0-6)
1529 Date.prototype.getLastDayOfMonth = function() {
1530 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1531 return (day < 0) ? (day + 7) : day;
1536 * Get the first date of this date's month
1539 Date.prototype.getFirstDateOfMonth = function() {
1540 return new Date(this.getFullYear(), this.getMonth(), 1);
1544 * Get the last date of this date's month
1547 Date.prototype.getLastDateOfMonth = function() {
1548 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1551 * Get the number of days in the current month, adjusted for leap year.
1552 * @return {Number} The number of days in the month
1554 Date.prototype.getDaysInMonth = function() {
1555 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1556 return Date.daysInMonth[this.getMonth()];
1560 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1561 * @return {String} 'st, 'nd', 'rd' or 'th'
1563 Date.prototype.getSuffix = function() {
1564 switch (this.getDate()) {
1581 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1584 * An array of textual month names.
1585 * Override these values for international dates, for example...
1586 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1605 * An array of textual day names.
1606 * Override these values for international dates, for example...
1607 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1623 Date.monthNumbers = {
1638 * Creates and returns a new Date instance with the exact same date value as the called instance.
1639 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1640 * variable will also be changed. When the intention is to create a new variable that will not
1641 * modify the original instance, you should create a clone.
1643 * Example of correctly cloning a date:
1646 var orig = new Date('10/1/2006');
1649 document.write(orig); //returns 'Thu Oct 05 2006'!
1652 var orig = new Date('10/1/2006');
1653 var copy = orig.clone();
1655 document.write(orig); //returns 'Thu Oct 01 2006'
1657 * @return {Date} The new Date instance
1659 Date.prototype.clone = function() {
1660 return new Date(this.getTime());
1664 * Clears any time information from this date
1665 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1666 @return {Date} this or the clone
1668 Date.prototype.clearTime = function(clone){
1670 return this.clone().clearTime();
1675 this.setMilliseconds(0);
1680 // safari setMonth is broken
1682 Date.brokenSetMonth = Date.prototype.setMonth;
1683 Date.prototype.setMonth = function(num){
1685 var n = Math.ceil(-num);
1686 var back_year = Math.ceil(n/12);
1687 var month = (n % 12) ? 12 - n % 12 : 0 ;
1688 this.setFullYear(this.getFullYear() - back_year);
1689 return Date.brokenSetMonth.call(this, month);
1691 return Date.brokenSetMonth.apply(this, arguments);
1696 /** Date interval constant
1700 /** Date interval constant
1704 /** Date interval constant
1708 /** Date interval constant
1712 /** Date interval constant
1716 /** Date interval constant
1720 /** Date interval constant
1726 * Provides a convenient method of performing basic date arithmetic. This method
1727 * does not modify the Date instance being called - it creates and returns
1728 * a new Date instance containing the resulting date value.
1733 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1734 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1736 //Negative values will subtract correctly:
1737 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1738 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1740 //You can even chain several calls together in one line!
1741 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1742 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1745 * @param {String} interval A valid date interval enum value
1746 * @param {Number} value The amount to add to the current date
1747 * @return {Date} The new Date instance
1749 Date.prototype.add = function(interval, value){
1750 var d = this.clone();
1751 if (!interval || value === 0) return d;
1752 switch(interval.toLowerCase()){
1754 d.setMilliseconds(this.getMilliseconds() + value);
1757 d.setSeconds(this.getSeconds() + value);
1760 d.setMinutes(this.getMinutes() + value);
1763 d.setHours(this.getHours() + value);
1766 d.setDate(this.getDate() + value);
1769 var day = this.getDate();
1771 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1774 d.setMonth(this.getMonth() + value);
1777 d.setFullYear(this.getFullYear() + value);
1784 * Ext JS Library 1.1.1
1785 * Copyright(c) 2006-2007, Ext JS, LLC.
1787 * Originally Released Under LGPL - original licence link has changed is not relivant.
1790 * <script type="text/javascript">
1794 * @class Roo.lib.Dom
1797 * Dom utils (from YIU afaik)
1802 * Get the view width
1803 * @param {Boolean} full True will get the full document, otherwise it's the view width
1804 * @return {Number} The width
1807 getViewWidth : function(full) {
1808 return full ? this.getDocumentWidth() : this.getViewportWidth();
1811 * Get the view height
1812 * @param {Boolean} full True will get the full document, otherwise it's the view height
1813 * @return {Number} The height
1815 getViewHeight : function(full) {
1816 return full ? this.getDocumentHeight() : this.getViewportHeight();
1819 getDocumentHeight: function() {
1820 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1821 return Math.max(scrollHeight, this.getViewportHeight());
1824 getDocumentWidth: function() {
1825 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1826 return Math.max(scrollWidth, this.getViewportWidth());
1829 getViewportHeight: function() {
1830 var height = self.innerHeight;
1831 var mode = document.compatMode;
1833 if ((mode || Roo.isIE) && !Roo.isOpera) {
1834 height = (mode == "CSS1Compat") ?
1835 document.documentElement.clientHeight :
1836 document.body.clientHeight;
1842 getViewportWidth: function() {
1843 var width = self.innerWidth;
1844 var mode = document.compatMode;
1846 if (mode || Roo.isIE) {
1847 width = (mode == "CSS1Compat") ?
1848 document.documentElement.clientWidth :
1849 document.body.clientWidth;
1854 isAncestor : function(p, c) {
1861 if (p.contains && !Roo.isSafari) {
1862 return p.contains(c);
1863 } else if (p.compareDocumentPosition) {
1864 return !!(p.compareDocumentPosition(c) & 16);
1866 var parent = c.parentNode;
1871 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1874 parent = parent.parentNode;
1880 getRegion : function(el) {
1881 return Roo.lib.Region.getRegion(el);
1884 getY : function(el) {
1885 return this.getXY(el)[1];
1888 getX : function(el) {
1889 return this.getXY(el)[0];
1892 getXY : function(el) {
1893 var p, pe, b, scroll, bd = document.body;
1894 el = Roo.getDom(el);
1895 var fly = Roo.lib.AnimBase.fly;
1896 if (el.getBoundingClientRect) {
1897 b = el.getBoundingClientRect();
1898 scroll = fly(document).getScroll();
1899 return [b.left + scroll.left, b.top + scroll.top];
1905 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1912 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1919 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1920 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1927 if (p != el && pe.getStyle('overflow') != 'visible') {
1935 if (Roo.isSafari && hasAbsolute) {
1940 if (Roo.isGecko && !hasAbsolute) {
1942 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1943 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1947 while (p && p != bd) {
1948 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1960 setXY : function(el, xy) {
1961 el = Roo.fly(el, '_setXY');
1963 var pts = el.translatePoints(xy);
1964 if (xy[0] !== false) {
1965 el.dom.style.left = pts.left + "px";
1967 if (xy[1] !== false) {
1968 el.dom.style.top = pts.top + "px";
1972 setX : function(el, x) {
1973 this.setXY(el, [x, false]);
1976 setY : function(el, y) {
1977 this.setXY(el, [false, y]);
1981 * Portions of this file are based on pieces of Yahoo User Interface Library
1982 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1983 * YUI licensed under the BSD License:
1984 * http://developer.yahoo.net/yui/license.txt
1985 * <script type="text/javascript">
1989 Roo.lib.Event = function() {
1990 var loadComplete = false;
1992 var unloadListeners = [];
1994 var onAvailStack = [];
1996 var lastError = null;
2009 startInterval: function() {
2010 if (!this._interval) {
2012 var callback = function() {
2013 self._tryPreloadAttach();
2015 this._interval = setInterval(callback, this.POLL_INTERVAL);
2020 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2021 onAvailStack.push({ id: p_id,
2024 override: p_override,
2025 checkReady: false });
2027 retryCount = this.POLL_RETRYS;
2028 this.startInterval();
2032 addListener: function(el, eventName, fn) {
2033 el = Roo.getDom(el);
2038 if ("unload" == eventName) {
2039 unloadListeners[unloadListeners.length] =
2040 [el, eventName, fn];
2044 var wrappedFn = function(e) {
2045 return fn(Roo.lib.Event.getEvent(e));
2048 var li = [el, eventName, fn, wrappedFn];
2050 var index = listeners.length;
2051 listeners[index] = li;
2053 this.doAdd(el, eventName, wrappedFn, false);
2059 removeListener: function(el, eventName, fn) {
2062 el = Roo.getDom(el);
2065 return this.purgeElement(el, false, eventName);
2069 if ("unload" == eventName) {
2071 for (i = 0,len = unloadListeners.length; i < len; i++) {
2072 var li = unloadListeners[i];
2075 li[1] == eventName &&
2077 unloadListeners.splice(i, 1);
2085 var cacheItem = null;
2088 var index = arguments[3];
2090 if ("undefined" == typeof index) {
2091 index = this._getCacheIndex(el, eventName, fn);
2095 cacheItem = listeners[index];
2098 if (!el || !cacheItem) {
2102 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2104 delete listeners[index][this.WFN];
2105 delete listeners[index][this.FN];
2106 listeners.splice(index, 1);
2113 getTarget: function(ev, resolveTextNode) {
2114 ev = ev.browserEvent || ev;
2115 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2116 var t = ev.target || ev.srcElement;
2117 return this.resolveTextNode(t);
2121 resolveTextNode: function(node) {
2122 if (Roo.isSafari && node && 3 == node.nodeType) {
2123 return node.parentNode;
2130 getPageX: function(ev) {
2131 ev = ev.browserEvent || ev;
2132 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : 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;
2148 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2150 if (!y && 0 !== y) {
2151 y = ev.clientY || 0;
2154 y += this.getScroll()[0];
2163 getXY: function(ev) {
2164 ev = ev.browserEvent || ev;
2165 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2166 return [this.getPageX(ev), this.getPageY(ev)];
2170 getRelatedTarget: function(ev) {
2171 ev = ev.browserEvent || ev;
2172 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2173 var t = ev.relatedTarget;
2175 if (ev.type == "mouseout") {
2177 } else if (ev.type == "mouseover") {
2182 return this.resolveTextNode(t);
2186 getTime: function(ev) {
2187 ev = ev.browserEvent || ev;
2188 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2190 var t = new Date().getTime();
2194 this.lastError = ex;
2203 stopEvent: function(ev) {
2204 this.stopPropagation(ev);
2205 this.preventDefault(ev);
2209 stopPropagation: function(ev) {
2210 ev = ev.browserEvent || ev;
2211 if (ev.stopPropagation) {
2212 ev.stopPropagation();
2214 ev.cancelBubble = true;
2219 preventDefault: function(ev) {
2220 ev = ev.browserEvent || ev;
2221 if(ev.preventDefault) {
2222 ev.preventDefault();
2224 ev.returnValue = false;
2229 getEvent: function(e) {
2230 var ev = e || window.event;
2232 var c = this.getEvent.caller;
2234 ev = c.arguments[0];
2235 if (ev && Event == ev.constructor) {
2245 getCharCode: function(ev) {
2246 ev = ev.browserEvent || ev;
2247 return ev.charCode || ev.keyCode || 0;
2251 _getCacheIndex: function(el, eventName, fn) {
2252 for (var i = 0,len = listeners.length; i < len; ++i) {
2253 var li = listeners[i];
2255 li[this.FN] == fn &&
2256 li[this.EL] == el &&
2257 li[this.TYPE] == eventName) {
2269 getEl: function(id) {
2270 return document.getElementById(id);
2274 clearCache: function() {
2278 _load: function(e) {
2279 loadComplete = true;
2280 var EU = Roo.lib.Event;
2284 EU.doRemove(window, "load", EU._load);
2289 _tryPreloadAttach: function() {
2298 var tryAgain = !loadComplete;
2300 tryAgain = (retryCount > 0);
2305 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2306 var item = onAvailStack[i];
2308 var el = this.getEl(item.id);
2311 if (!item.checkReady ||
2314 (document && document.body)) {
2317 if (item.override) {
2318 if (item.override === true) {
2321 scope = item.override;
2324 item.fn.call(scope, item.obj);
2325 onAvailStack[i] = null;
2328 notAvail.push(item);
2333 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2337 this.startInterval();
2339 clearInterval(this._interval);
2340 this._interval = null;
2343 this.locked = false;
2350 purgeElement: function(el, recurse, eventName) {
2351 var elListeners = this.getListeners(el, eventName);
2353 for (var i = 0,len = elListeners.length; i < len; ++i) {
2354 var l = elListeners[i];
2355 this.removeListener(el, l.type, l.fn);
2359 if (recurse && el && el.childNodes) {
2360 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2361 this.purgeElement(el.childNodes[i], recurse, eventName);
2367 getListeners: function(el, eventName) {
2368 var results = [], searchLists;
2370 searchLists = [listeners, unloadListeners];
2371 } else if (eventName == "unload") {
2372 searchLists = [unloadListeners];
2374 searchLists = [listeners];
2377 for (var j = 0; j < searchLists.length; ++j) {
2378 var searchList = searchLists[j];
2379 if (searchList && searchList.length > 0) {
2380 for (var i = 0,len = searchList.length; i < len; ++i) {
2381 var l = searchList[i];
2382 if (l && l[this.EL] === el &&
2383 (!eventName || eventName === l[this.TYPE])) {
2388 adjust: l[this.ADJ_SCOPE],
2396 return (results.length) ? results : null;
2400 _unload: function(e) {
2402 var EU = Roo.lib.Event, i, j, l, len, index;
2404 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2405 l = unloadListeners[i];
2408 if (l[EU.ADJ_SCOPE]) {
2409 if (l[EU.ADJ_SCOPE] === true) {
2412 scope = l[EU.ADJ_SCOPE];
2415 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2416 unloadListeners[i] = null;
2422 unloadListeners = null;
2424 if (listeners && listeners.length > 0) {
2425 j = listeners.length;
2428 l = listeners[index];
2430 EU.removeListener(l[EU.EL], l[EU.TYPE],
2440 EU.doRemove(window, "unload", EU._unload);
2445 getScroll: function() {
2446 var dd = document.documentElement, db = document.body;
2447 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2448 return [dd.scrollTop, dd.scrollLeft];
2450 return [db.scrollTop, db.scrollLeft];
2457 doAdd: function () {
2458 if (window.addEventListener) {
2459 return function(el, eventName, fn, capture) {
2460 el.addEventListener(eventName, fn, (capture));
2462 } else if (window.attachEvent) {
2463 return function(el, eventName, fn, capture) {
2464 el.attachEvent("on" + eventName, fn);
2473 doRemove: function() {
2474 if (window.removeEventListener) {
2475 return function (el, eventName, fn, capture) {
2476 el.removeEventListener(eventName, fn, (capture));
2478 } else if (window.detachEvent) {
2479 return function (el, eventName, fn) {
2480 el.detachEvent("on" + eventName, fn);
2492 var E = Roo.lib.Event;
2493 E.on = E.addListener;
2494 E.un = E.removeListener;
2496 if (document && document.body) {
2499 E.doAdd(window, "load", E._load);
2501 E.doAdd(window, "unload", E._unload);
2502 E._tryPreloadAttach();
2506 * Portions of this file are based on pieces of Yahoo User Interface Library
2507 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2508 * YUI licensed under the BSD License:
2509 * http://developer.yahoo.net/yui/license.txt
2510 * <script type="text/javascript">
2516 * @class Roo.lib.Ajax
2523 request : function(method, uri, cb, data, options) {
2525 var hs = options.headers;
2528 if(hs.hasOwnProperty(h)){
2529 this.initHeader(h, hs[h], false);
2533 if(options.xmlData){
2534 this.initHeader('Content-Type', 'text/xml', false);
2536 data = options.xmlData;
2540 return this.asyncRequest(method, uri, cb, data);
2543 serializeForm : function(form) {
2544 if(typeof form == 'string') {
2545 form = (document.getElementById(form) || document.forms[form]);
2548 var el, name, val, disabled, data = '', hasSubmit = false;
2549 for (var i = 0; i < form.elements.length; i++) {
2550 el = form.elements[i];
2551 disabled = form.elements[i].disabled;
2552 name = form.elements[i].name;
2553 val = form.elements[i].value;
2555 if (!disabled && name){
2559 case 'select-multiple':
2560 for (var j = 0; j < el.options.length; j++) {
2561 if (el.options[j].selected) {
2563 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2566 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2574 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2587 if(hasSubmit == false) {
2588 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2593 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2598 data = data.substr(0, data.length - 1);
2606 useDefaultHeader:true,
2608 defaultPostHeader:'application/x-www-form-urlencoded',
2610 useDefaultXhrHeader:true,
2612 defaultXhrHeader:'XMLHttpRequest',
2614 hasDefaultHeaders:true,
2626 setProgId:function(id)
2628 this.activeX.unshift(id);
2631 setDefaultPostHeader:function(b)
2633 this.useDefaultHeader = b;
2636 setDefaultXhrHeader:function(b)
2638 this.useDefaultXhrHeader = b;
2641 setPollingInterval:function(i)
2643 if (typeof i == 'number' && isFinite(i)) {
2644 this.pollInterval = i;
2648 createXhrObject:function(transactionId)
2654 http = new XMLHttpRequest();
2656 obj = { conn:http, tId:transactionId };
2660 for (var i = 0; i < this.activeX.length; ++i) {
2664 http = new ActiveXObject(this.activeX[i]);
2666 obj = { conn:http, tId:transactionId };
2679 getConnectionObject:function()
2682 var tId = this.transactionId;
2686 o = this.createXhrObject(tId);
2688 this.transactionId++;
2699 asyncRequest:function(method, uri, callback, postData)
2701 var o = this.getConnectionObject();
2707 o.conn.open(method, uri, true);
2709 if (this.useDefaultXhrHeader) {
2710 if (!this.defaultHeaders['X-Requested-With']) {
2711 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2715 if(postData && this.useDefaultHeader){
2716 this.initHeader('Content-Type', this.defaultPostHeader);
2719 if (this.hasDefaultHeaders || this.hasHeaders) {
2723 this.handleReadyState(o, callback);
2724 o.conn.send(postData || null);
2730 handleReadyState:function(o, callback)
2734 if (callback && callback.timeout) {
2736 this.timeout[o.tId] = window.setTimeout(function() {
2737 oConn.abort(o, callback, true);
2738 }, callback.timeout);
2741 this.poll[o.tId] = window.setInterval(
2743 if (o.conn && o.conn.readyState == 4) {
2744 window.clearInterval(oConn.poll[o.tId]);
2745 delete oConn.poll[o.tId];
2747 if(callback && callback.timeout) {
2748 window.clearTimeout(oConn.timeout[o.tId]);
2749 delete oConn.timeout[o.tId];
2752 oConn.handleTransactionResponse(o, callback);
2755 , this.pollInterval);
2758 handleTransactionResponse:function(o, callback, isAbort)
2762 this.releaseObject(o);
2766 var httpStatus, responseObject;
2770 if (o.conn.status !== undefined && o.conn.status != 0) {
2771 httpStatus = o.conn.status;
2783 if (httpStatus >= 200 && httpStatus < 300) {
2784 responseObject = this.createResponseObject(o, callback.argument);
2785 if (callback.success) {
2786 if (!callback.scope) {
2787 callback.success(responseObject);
2792 callback.success.apply(callback.scope, [responseObject]);
2797 switch (httpStatus) {
2805 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2806 if (callback.failure) {
2807 if (!callback.scope) {
2808 callback.failure(responseObject);
2811 callback.failure.apply(callback.scope, [responseObject]);
2816 responseObject = this.createResponseObject(o, callback.argument);
2817 if (callback.failure) {
2818 if (!callback.scope) {
2819 callback.failure(responseObject);
2822 callback.failure.apply(callback.scope, [responseObject]);
2828 this.releaseObject(o);
2829 responseObject = null;
2832 createResponseObject:function(o, callbackArg)
2839 var headerStr = o.conn.getAllResponseHeaders();
2840 var header = headerStr.split('\n');
2841 for (var i = 0; i < header.length; i++) {
2842 var delimitPos = header[i].indexOf(':');
2843 if (delimitPos != -1) {
2844 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2852 obj.status = o.conn.status;
2853 obj.statusText = o.conn.statusText;
2854 obj.getResponseHeader = headerObj;
2855 obj.getAllResponseHeaders = headerStr;
2856 obj.responseText = o.conn.responseText;
2857 obj.responseXML = o.conn.responseXML;
2859 if (typeof callbackArg !== undefined) {
2860 obj.argument = callbackArg;
2866 createExceptionObject:function(tId, callbackArg, isAbort)
2869 var COMM_ERROR = 'communication failure';
2870 var ABORT_CODE = -1;
2871 var ABORT_ERROR = 'transaction aborted';
2877 obj.status = ABORT_CODE;
2878 obj.statusText = ABORT_ERROR;
2881 obj.status = COMM_CODE;
2882 obj.statusText = COMM_ERROR;
2886 obj.argument = callbackArg;
2892 initHeader:function(label, value, isDefault)
2894 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2896 if (headerObj[label] === undefined) {
2897 headerObj[label] = value;
2902 headerObj[label] = value + "," + headerObj[label];
2906 this.hasDefaultHeaders = true;
2909 this.hasHeaders = true;
2914 setHeader:function(o)
2916 if (this.hasDefaultHeaders) {
2917 for (var prop in this.defaultHeaders) {
2918 if (this.defaultHeaders.hasOwnProperty(prop)) {
2919 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2924 if (this.hasHeaders) {
2925 for (var prop in this.headers) {
2926 if (this.headers.hasOwnProperty(prop)) {
2927 o.conn.setRequestHeader(prop, this.headers[prop]);
2931 this.hasHeaders = false;
2935 resetDefaultHeaders:function() {
2936 delete this.defaultHeaders;
2937 this.defaultHeaders = {};
2938 this.hasDefaultHeaders = false;
2941 abort:function(o, callback, isTimeout)
2943 if(this.isCallInProgress(o)) {
2945 window.clearInterval(this.poll[o.tId]);
2946 delete this.poll[o.tId];
2948 delete this.timeout[o.tId];
2951 this.handleTransactionResponse(o, callback, true);
2961 isCallInProgress:function(o)
2964 return o.conn.readyState != 4 && o.conn.readyState != 0;
2973 releaseObject:function(o)
2982 'MSXML2.XMLHTTP.3.0',
2990 * Portions of this file are based on pieces of Yahoo User Interface Library
2991 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2992 * YUI licensed under the BSD License:
2993 * http://developer.yahoo.net/yui/license.txt
2994 * <script type="text/javascript">
2998 Roo.lib.Region = function(t, r, b, l) {
3008 Roo.lib.Region.prototype = {
3009 contains : function(region) {
3010 return ( region.left >= this.left &&
3011 region.right <= this.right &&
3012 region.top >= this.top &&
3013 region.bottom <= this.bottom );
3017 getArea : function() {
3018 return ( (this.bottom - this.top) * (this.right - this.left) );
3021 intersect : function(region) {
3022 var t = Math.max(this.top, region.top);
3023 var r = Math.min(this.right, region.right);
3024 var b = Math.min(this.bottom, region.bottom);
3025 var l = Math.max(this.left, region.left);
3027 if (b >= t && r >= l) {
3028 return new Roo.lib.Region(t, r, b, l);
3033 union : function(region) {
3034 var t = Math.min(this.top, region.top);
3035 var r = Math.max(this.right, region.right);
3036 var b = Math.max(this.bottom, region.bottom);
3037 var l = Math.min(this.left, region.left);
3039 return new Roo.lib.Region(t, r, b, l);
3042 adjust : function(t, l, b, r) {
3051 Roo.lib.Region.getRegion = function(el) {
3052 var p = Roo.lib.Dom.getXY(el);
3055 var r = p[0] + el.offsetWidth;
3056 var b = p[1] + el.offsetHeight;
3059 return new Roo.lib.Region(t, r, b, l);
3062 * Portions of this file are based on pieces of Yahoo User Interface Library
3063 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3064 * YUI licensed under the BSD License:
3065 * http://developer.yahoo.net/yui/license.txt
3066 * <script type="text/javascript">
3069 //@@dep Roo.lib.Region
3072 Roo.lib.Point = function(x, y) {
3073 if (x instanceof Array) {
3077 this.x = this.right = this.left = this[0] = x;
3078 this.y = this.top = this.bottom = this[1] = y;
3081 Roo.lib.Point.prototype = new Roo.lib.Region();
3083 * Portions of this file are based on pieces of Yahoo User Interface Library
3084 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3085 * YUI licensed under the BSD License:
3086 * http://developer.yahoo.net/yui/license.txt
3087 * <script type="text/javascript">
3094 scroll : function(el, args, duration, easing, cb, scope) {
3095 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3098 motion : function(el, args, duration, easing, cb, scope) {
3099 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3102 color : function(el, args, duration, easing, cb, scope) {
3103 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3106 run : function(el, args, duration, easing, cb, scope, type) {
3107 type = type || Roo.lib.AnimBase;
3108 if (typeof easing == "string") {
3109 easing = Roo.lib.Easing[easing];
3111 var anim = new type(el, args, duration, easing);
3112 anim.animateX(function() {
3113 Roo.callback(cb, scope);
3119 * Portions of this file are based on pieces of Yahoo User Interface Library
3120 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3121 * YUI licensed under the BSD License:
3122 * http://developer.yahoo.net/yui/license.txt
3123 * <script type="text/javascript">
3131 if (!libFlyweight) {
3132 libFlyweight = new Roo.Element.Flyweight();
3134 libFlyweight.dom = el;
3135 return libFlyweight;
3138 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3142 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3144 this.init(el, attributes, duration, method);
3148 Roo.lib.AnimBase.fly = fly;
3152 Roo.lib.AnimBase.prototype = {
3154 toString: function() {
3155 var el = this.getEl();
3156 var id = el.id || el.tagName;
3157 return ("Anim " + id);
3161 noNegatives: /width|height|opacity|padding/i,
3162 offsetAttribute: /^((width|height)|(top|left))$/,
3163 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3164 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3168 doMethod: function(attr, start, end) {
3169 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3173 setAttribute: function(attr, val, unit) {
3174 if (this.patterns.noNegatives.test(attr)) {
3175 val = (val > 0) ? val : 0;
3178 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3182 getAttribute: function(attr) {
3183 var el = this.getEl();
3184 var val = fly(el).getStyle(attr);
3186 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3187 return parseFloat(val);
3190 var a = this.patterns.offsetAttribute.exec(attr) || [];
3191 var pos = !!( a[3] );
3192 var box = !!( a[2] );
3195 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3196 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3205 getDefaultUnit: function(attr) {
3206 if (this.patterns.defaultUnit.test(attr)) {
3213 animateX : function(callback, scope) {
3214 var f = function() {
3215 this.onComplete.removeListener(f);
3216 if (typeof callback == "function") {
3217 callback.call(scope || this, this);
3220 this.onComplete.addListener(f, this);
3225 setRuntimeAttribute: function(attr) {
3228 var attributes = this.attributes;
3230 this.runtimeAttributes[attr] = {};
3232 var isset = function(prop) {
3233 return (typeof prop !== 'undefined');
3236 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3240 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3243 if (isset(attributes[attr]['to'])) {
3244 end = attributes[attr]['to'];
3245 } else if (isset(attributes[attr]['by'])) {
3246 if (start.constructor == Array) {
3248 for (var i = 0, len = start.length; i < len; ++i) {
3249 end[i] = start[i] + attributes[attr]['by'][i];
3252 end = start + attributes[attr]['by'];
3256 this.runtimeAttributes[attr].start = start;
3257 this.runtimeAttributes[attr].end = end;
3260 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3264 init: function(el, attributes, duration, method) {
3266 var isAnimated = false;
3269 var startTime = null;
3272 var actualFrames = 0;
3275 el = Roo.getDom(el);
3278 this.attributes = attributes || {};
3281 this.duration = duration || 1;
3284 this.method = method || Roo.lib.Easing.easeNone;
3287 this.useSeconds = true;
3290 this.currentFrame = 0;
3293 this.totalFrames = Roo.lib.AnimMgr.fps;
3296 this.getEl = function() {
3301 this.isAnimated = function() {
3306 this.getStartTime = function() {
3310 this.runtimeAttributes = {};
3313 this.animate = function() {
3314 if (this.isAnimated()) {
3318 this.currentFrame = 0;
3320 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3322 Roo.lib.AnimMgr.registerElement(this);
3326 this.stop = function(finish) {
3328 this.currentFrame = this.totalFrames;
3329 this._onTween.fire();
3331 Roo.lib.AnimMgr.stop(this);
3334 var onStart = function() {
3335 this.onStart.fire();
3337 this.runtimeAttributes = {};
3338 for (var attr in this.attributes) {
3339 this.setRuntimeAttribute(attr);
3344 startTime = new Date();
3348 var onTween = function() {
3350 duration: new Date() - this.getStartTime(),
3351 currentFrame: this.currentFrame
3354 data.toString = function() {
3356 'duration: ' + data.duration +
3357 ', currentFrame: ' + data.currentFrame
3361 this.onTween.fire(data);
3363 var runtimeAttributes = this.runtimeAttributes;
3365 for (var attr in runtimeAttributes) {
3366 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3372 var onComplete = function() {
3373 var actual_duration = (new Date() - startTime) / 1000 ;
3376 duration: actual_duration,
3377 frames: actualFrames,
3378 fps: actualFrames / actual_duration
3381 data.toString = function() {
3383 'duration: ' + data.duration +
3384 ', frames: ' + data.frames +
3385 ', fps: ' + data.fps
3391 this.onComplete.fire(data);
3395 this._onStart = new Roo.util.Event(this);
3396 this.onStart = new Roo.util.Event(this);
3397 this.onTween = new Roo.util.Event(this);
3398 this._onTween = new Roo.util.Event(this);
3399 this.onComplete = new Roo.util.Event(this);
3400 this._onComplete = new Roo.util.Event(this);
3401 this._onStart.addListener(onStart);
3402 this._onTween.addListener(onTween);
3403 this._onComplete.addListener(onComplete);
3408 * Portions of this file are based on pieces of Yahoo User Interface Library
3409 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3410 * YUI licensed under the BSD License:
3411 * http://developer.yahoo.net/yui/license.txt
3412 * <script type="text/javascript">
3416 Roo.lib.AnimMgr = new function() {
3433 this.registerElement = function(tween) {
3434 queue[queue.length] = tween;
3436 tween._onStart.fire();
3441 this.unRegister = function(tween, index) {
3442 tween._onComplete.fire();
3443 index = index || getIndex(tween);
3445 queue.splice(index, 1);
3449 if (tweenCount <= 0) {
3455 this.start = function() {
3456 if (thread === null) {
3457 thread = setInterval(this.run, this.delay);
3462 this.stop = function(tween) {
3464 clearInterval(thread);
3466 for (var i = 0, len = queue.length; i < len; ++i) {
3467 if (queue[0].isAnimated()) {
3468 this.unRegister(queue[0], 0);
3477 this.unRegister(tween);
3482 this.run = function() {
3483 for (var i = 0, len = queue.length; i < len; ++i) {
3484 var tween = queue[i];
3485 if (!tween || !tween.isAnimated()) {
3489 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3491 tween.currentFrame += 1;
3493 if (tween.useSeconds) {
3494 correctFrame(tween);
3496 tween._onTween.fire();
3499 Roo.lib.AnimMgr.stop(tween, i);
3504 var getIndex = function(anim) {
3505 for (var i = 0, len = queue.length; i < len; ++i) {
3506 if (queue[i] == anim) {
3514 var correctFrame = function(tween) {
3515 var frames = tween.totalFrames;
3516 var frame = tween.currentFrame;
3517 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3518 var elapsed = (new Date() - tween.getStartTime());
3521 if (elapsed < tween.duration * 1000) {
3522 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3524 tweak = frames - (frame + 1);
3526 if (tweak > 0 && isFinite(tweak)) {
3527 if (tween.currentFrame + tweak >= frames) {
3528 tweak = frames - (frame + 1);
3531 tween.currentFrame += tweak;
3537 * Portions of this file are based on pieces of Yahoo User Interface Library
3538 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3539 * YUI licensed under the BSD License:
3540 * http://developer.yahoo.net/yui/license.txt
3541 * <script type="text/javascript">
3544 Roo.lib.Bezier = new function() {
3546 this.getPosition = function(points, t) {
3547 var n = points.length;
3550 for (var i = 0; i < n; ++i) {
3551 tmp[i] = [points[i][0], points[i][1]];
3554 for (var j = 1; j < n; ++j) {
3555 for (i = 0; i < n - j; ++i) {
3556 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3557 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3561 return [ tmp[0][0], tmp[0][1] ];
3565 * Portions of this file are based on pieces of Yahoo User Interface Library
3566 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3567 * YUI licensed under the BSD License:
3568 * http://developer.yahoo.net/yui/license.txt
3569 * <script type="text/javascript">
3574 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3575 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3578 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3580 var fly = Roo.lib.AnimBase.fly;
3582 var superclass = Y.ColorAnim.superclass;
3583 var proto = Y.ColorAnim.prototype;
3585 proto.toString = function() {
3586 var el = this.getEl();
3587 var id = el.id || el.tagName;
3588 return ("ColorAnim " + id);
3591 proto.patterns.color = /color$/i;
3592 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3593 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3594 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3595 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3598 proto.parseColor = function(s) {
3599 if (s.length == 3) {
3603 var c = this.patterns.hex.exec(s);
3604 if (c && c.length == 4) {
3605 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3608 c = this.patterns.rgb.exec(s);
3609 if (c && c.length == 4) {
3610 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3613 c = this.patterns.hex3.exec(s);
3614 if (c && c.length == 4) {
3615 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3620 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3621 proto.getAttribute = function(attr) {
3622 var el = this.getEl();
3623 if (this.patterns.color.test(attr)) {
3624 var val = fly(el).getStyle(attr);
3626 if (this.patterns.transparent.test(val)) {
3627 var parent = el.parentNode;
3628 val = fly(parent).getStyle(attr);
3630 while (parent && this.patterns.transparent.test(val)) {
3631 parent = parent.parentNode;
3632 val = fly(parent).getStyle(attr);
3633 if (parent.tagName.toUpperCase() == 'HTML') {
3639 val = superclass.getAttribute.call(this, attr);
3644 proto.getAttribute = function(attr) {
3645 var el = this.getEl();
3646 if (this.patterns.color.test(attr)) {
3647 var val = fly(el).getStyle(attr);
3649 if (this.patterns.transparent.test(val)) {
3650 var parent = el.parentNode;
3651 val = fly(parent).getStyle(attr);
3653 while (parent && this.patterns.transparent.test(val)) {
3654 parent = parent.parentNode;
3655 val = fly(parent).getStyle(attr);
3656 if (parent.tagName.toUpperCase() == 'HTML') {
3662 val = superclass.getAttribute.call(this, attr);
3668 proto.doMethod = function(attr, start, end) {
3671 if (this.patterns.color.test(attr)) {
3673 for (var i = 0, len = start.length; i < len; ++i) {
3674 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3677 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3680 val = superclass.doMethod.call(this, attr, start, end);
3686 proto.setRuntimeAttribute = function(attr) {
3687 superclass.setRuntimeAttribute.call(this, attr);
3689 if (this.patterns.color.test(attr)) {
3690 var attributes = this.attributes;
3691 var start = this.parseColor(this.runtimeAttributes[attr].start);
3692 var end = this.parseColor(this.runtimeAttributes[attr].end);
3694 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3695 end = this.parseColor(attributes[attr].by);
3697 for (var i = 0, len = start.length; i < len; ++i) {
3698 end[i] = start[i] + end[i];
3702 this.runtimeAttributes[attr].start = start;
3703 this.runtimeAttributes[attr].end = end;
3709 * Portions of this file are based on pieces of Yahoo User Interface Library
3710 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3711 * YUI licensed under the BSD License:
3712 * http://developer.yahoo.net/yui/license.txt
3713 * <script type="text/javascript">
3719 easeNone: function (t, b, c, d) {
3720 return c * t / d + b;
3724 easeIn: function (t, b, c, d) {
3725 return c * (t /= d) * t + b;
3729 easeOut: function (t, b, c, d) {
3730 return -c * (t /= d) * (t - 2) + b;
3734 easeBoth: function (t, b, c, d) {
3735 if ((t /= d / 2) < 1) {
3736 return c / 2 * t * t + b;
3739 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3743 easeInStrong: function (t, b, c, d) {
3744 return c * (t /= d) * t * t * t + b;
3748 easeOutStrong: function (t, b, c, d) {
3749 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3753 easeBothStrong: function (t, b, c, d) {
3754 if ((t /= d / 2) < 1) {
3755 return c / 2 * t * t * t * t + b;
3758 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3763 elasticIn: function (t, b, c, d, a, p) {
3767 if ((t /= d) == 1) {
3774 if (!a || a < Math.abs(c)) {
3779 var s = p / (2 * Math.PI) * Math.asin(c / a);
3782 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3786 elasticOut: function (t, b, c, d, a, p) {
3790 if ((t /= d) == 1) {
3797 if (!a || a < Math.abs(c)) {
3802 var s = p / (2 * Math.PI) * Math.asin(c / a);
3805 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3809 elasticBoth: function (t, b, c, d, a, p) {
3814 if ((t /= d / 2) == 2) {
3822 if (!a || a < Math.abs(c)) {
3827 var s = p / (2 * Math.PI) * Math.asin(c / a);
3831 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3832 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3834 return a * Math.pow(2, -10 * (t -= 1)) *
3835 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3840 backIn: function (t, b, c, d, s) {
3841 if (typeof s == 'undefined') {
3844 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3848 backOut: function (t, b, c, d, s) {
3849 if (typeof s == 'undefined') {
3852 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3856 backBoth: function (t, b, c, d, s) {
3857 if (typeof s == 'undefined') {
3861 if ((t /= d / 2 ) < 1) {
3862 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3864 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3868 bounceIn: function (t, b, c, d) {
3869 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3873 bounceOut: function (t, b, c, d) {
3874 if ((t /= d) < (1 / 2.75)) {
3875 return c * (7.5625 * t * t) + b;
3876 } else if (t < (2 / 2.75)) {
3877 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3878 } else if (t < (2.5 / 2.75)) {
3879 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3881 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3885 bounceBoth: function (t, b, c, d) {
3887 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3889 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3892 * Portions of this file are based on pieces of Yahoo User Interface Library
3893 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3894 * YUI licensed under the BSD License:
3895 * http://developer.yahoo.net/yui/license.txt
3896 * <script type="text/javascript">
3900 Roo.lib.Motion = function(el, attributes, duration, method) {
3902 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3906 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3910 var superclass = Y.Motion.superclass;
3911 var proto = Y.Motion.prototype;
3913 proto.toString = function() {
3914 var el = this.getEl();
3915 var id = el.id || el.tagName;
3916 return ("Motion " + id);
3919 proto.patterns.points = /^points$/i;
3921 proto.setAttribute = function(attr, val, unit) {
3922 if (this.patterns.points.test(attr)) {
3923 unit = unit || 'px';
3924 superclass.setAttribute.call(this, 'left', val[0], unit);
3925 superclass.setAttribute.call(this, 'top', val[1], unit);
3927 superclass.setAttribute.call(this, attr, val, unit);
3931 proto.getAttribute = function(attr) {
3932 if (this.patterns.points.test(attr)) {
3934 superclass.getAttribute.call(this, 'left'),
3935 superclass.getAttribute.call(this, 'top')
3938 val = superclass.getAttribute.call(this, attr);
3944 proto.doMethod = function(attr, start, end) {
3947 if (this.patterns.points.test(attr)) {
3948 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3949 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3951 val = superclass.doMethod.call(this, attr, start, end);
3956 proto.setRuntimeAttribute = function(attr) {
3957 if (this.patterns.points.test(attr)) {
3958 var el = this.getEl();
3959 var attributes = this.attributes;
3961 var control = attributes['points']['control'] || [];
3965 if (control.length > 0 && !(control[0] instanceof Array)) {
3966 control = [control];
3969 for (i = 0,len = control.length; i < len; ++i) {
3970 tmp[i] = control[i];
3975 Roo.fly(el).position();
3977 if (isset(attributes['points']['from'])) {
3978 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3981 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3984 start = this.getAttribute('points');
3987 if (isset(attributes['points']['to'])) {
3988 end = translateValues.call(this, attributes['points']['to'], start);
3990 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3991 for (i = 0,len = control.length; i < len; ++i) {
3992 control[i] = translateValues.call(this, control[i], start);
3996 } else if (isset(attributes['points']['by'])) {
3997 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3999 for (i = 0,len = control.length; i < len; ++i) {
4000 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
4004 this.runtimeAttributes[attr] = [start];
4006 if (control.length > 0) {
4007 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4010 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4013 superclass.setRuntimeAttribute.call(this, attr);
4017 var translateValues = function(val, start) {
4018 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4019 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4024 var isset = function(prop) {
4025 return (typeof prop !== 'undefined');
4029 * Portions of this file are based on pieces of Yahoo User Interface Library
4030 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4031 * YUI licensed under the BSD License:
4032 * http://developer.yahoo.net/yui/license.txt
4033 * <script type="text/javascript">
4037 Roo.lib.Scroll = function(el, attributes, duration, method) {
4039 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4043 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4047 var superclass = Y.Scroll.superclass;
4048 var proto = Y.Scroll.prototype;
4050 proto.toString = function() {
4051 var el = this.getEl();
4052 var id = el.id || el.tagName;
4053 return ("Scroll " + id);
4056 proto.doMethod = function(attr, start, end) {
4059 if (attr == 'scroll') {
4061 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4062 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4066 val = superclass.doMethod.call(this, attr, start, end);
4071 proto.getAttribute = function(attr) {
4073 var el = this.getEl();
4075 if (attr == 'scroll') {
4076 val = [ el.scrollLeft, el.scrollTop ];
4078 val = superclass.getAttribute.call(this, attr);
4084 proto.setAttribute = function(attr, val, unit) {
4085 var el = this.getEl();
4087 if (attr == 'scroll') {
4088 el.scrollLeft = val[0];
4089 el.scrollTop = val[1];
4091 superclass.setAttribute.call(this, attr, val, unit);
4097 * Ext JS Library 1.1.1
4098 * Copyright(c) 2006-2007, Ext JS, LLC.
4100 * Originally Released Under LGPL - original licence link has changed is not relivant.
4103 * <script type="text/javascript">
4107 // nasty IE9 hack - what a pile of crap that is..
4109 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4110 Range.prototype.createContextualFragment = function (html) {
4111 var doc = window.document;
4112 var container = doc.createElement("div");
4113 container.innerHTML = html;
4114 var frag = doc.createDocumentFragment(), n;
4115 while ((n = container.firstChild)) {
4116 frag.appendChild(n);
4123 * @class Roo.DomHelper
4124 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4125 * 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>.
4128 Roo.DomHelper = function(){
4129 var tempTableEl = null;
4130 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4131 var tableRe = /^table|tbody|tr|td$/i;
4133 // build as innerHTML where available
4135 var createHtml = function(o){
4136 if(typeof o == 'string'){
4145 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4146 if(attr == "style"){
4148 if(typeof s == "function"){
4151 if(typeof s == "string"){
4152 b += ' style="' + s + '"';
4153 }else if(typeof s == "object"){
4156 if(typeof s[key] != "function"){
4157 b += key + ":" + s[key] + ";";
4164 b += ' class="' + o["cls"] + '"';
4165 }else if(attr == "htmlFor"){
4166 b += ' for="' + o["htmlFor"] + '"';
4168 b += " " + attr + '="' + o[attr] + '"';
4172 if(emptyTags.test(o.tag)){
4176 var cn = o.children || o.cn;
4178 //http://bugs.kde.org/show_bug.cgi?id=71506
4179 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4180 for(var i = 0, len = cn.length; i < len; i++) {
4181 b += createHtml(cn[i], b);
4184 b += createHtml(cn, b);
4190 b += "</" + o.tag + ">";
4197 var createDom = function(o, parentNode){
4199 // defininition craeted..
4201 if (o.ns && o.ns != 'html') {
4203 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4204 xmlns[o.ns] = o.xmlns;
4207 if (typeof(xmlns[o.ns]) == 'undefined') {
4208 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4214 if (typeof(o) == 'string') {
4215 return parentNode.appendChild(document.createTextNode(o));
4217 o.tag = o.tag || div;
4218 if (o.ns && Roo.isIE) {
4220 o.tag = o.ns + ':' + o.tag;
4223 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4224 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4227 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4228 attr == "style" || typeof o[attr] == "function") continue;
4230 if(attr=="cls" && Roo.isIE){
4231 el.className = o["cls"];
4233 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4234 else el[attr] = o[attr];
4237 Roo.DomHelper.applyStyles(el, o.style);
4238 var cn = o.children || o.cn;
4240 //http://bugs.kde.org/show_bug.cgi?id=71506
4241 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4242 for(var i = 0, len = cn.length; i < len; i++) {
4243 createDom(cn[i], el);
4250 el.innerHTML = o.html;
4253 parentNode.appendChild(el);
4258 var ieTable = function(depth, s, h, e){
4259 tempTableEl.innerHTML = [s, h, e].join('');
4260 var i = -1, el = tempTableEl;
4267 // kill repeat to save bytes
4271 tbe = '</tbody>'+te,
4277 * Nasty code for IE's broken table implementation
4279 var insertIntoTable = function(tag, where, el, html){
4281 tempTableEl = document.createElement('div');
4286 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4289 if(where == 'beforebegin'){
4293 before = el.nextSibling;
4296 node = ieTable(4, trs, html, tre);
4298 else if(tag == 'tr'){
4299 if(where == 'beforebegin'){
4302 node = ieTable(3, tbs, html, tbe);
4303 } else if(where == 'afterend'){
4304 before = el.nextSibling;
4306 node = ieTable(3, tbs, html, tbe);
4307 } else{ // INTO a TR
4308 if(where == 'afterbegin'){
4309 before = el.firstChild;
4311 node = ieTable(4, trs, html, tre);
4313 } else if(tag == 'tbody'){
4314 if(where == 'beforebegin'){
4317 node = ieTable(2, ts, html, te);
4318 } else if(where == 'afterend'){
4319 before = el.nextSibling;
4321 node = ieTable(2, ts, html, te);
4323 if(where == 'afterbegin'){
4324 before = el.firstChild;
4326 node = ieTable(3, tbs, html, tbe);
4329 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4332 if(where == 'afterbegin'){
4333 before = el.firstChild;
4335 node = ieTable(2, ts, html, te);
4337 el.insertBefore(node, before);
4342 /** True to force the use of DOM instead of html fragments @type Boolean */
4346 * Returns the markup for the passed Element(s) config
4347 * @param {Object} o The Dom object spec (and children)
4350 markup : function(o){
4351 return createHtml(o);
4355 * Applies a style specification to an element
4356 * @param {String/HTMLElement} el The element to apply styles to
4357 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4358 * a function which returns such a specification.
4360 applyStyles : function(el, styles){
4363 if(typeof styles == "string"){
4364 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4366 while ((matches = re.exec(styles)) != null){
4367 el.setStyle(matches[1], matches[2]);
4369 }else if (typeof styles == "object"){
4370 for (var style in styles){
4371 el.setStyle(style, styles[style]);
4373 }else if (typeof styles == "function"){
4374 Roo.DomHelper.applyStyles(el, styles.call());
4380 * Inserts an HTML fragment into the Dom
4381 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4382 * @param {HTMLElement} el The context element
4383 * @param {String} html The HTML fragmenet
4384 * @return {HTMLElement} The new node
4386 insertHtml : function(where, el, html){
4387 where = where.toLowerCase();
4388 if(el.insertAdjacentHTML){
4389 if(tableRe.test(el.tagName)){
4391 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4397 el.insertAdjacentHTML('BeforeBegin', html);
4398 return el.previousSibling;
4400 el.insertAdjacentHTML('AfterBegin', html);
4401 return el.firstChild;
4403 el.insertAdjacentHTML('BeforeEnd', html);
4404 return el.lastChild;
4406 el.insertAdjacentHTML('AfterEnd', html);
4407 return el.nextSibling;
4409 throw 'Illegal insertion point -> "' + where + '"';
4411 var range = el.ownerDocument.createRange();
4415 range.setStartBefore(el);
4416 frag = range.createContextualFragment(html);
4417 el.parentNode.insertBefore(frag, el);
4418 return el.previousSibling;
4421 range.setStartBefore(el.firstChild);
4422 frag = range.createContextualFragment(html);
4423 el.insertBefore(frag, el.firstChild);
4424 return el.firstChild;
4426 el.innerHTML = html;
4427 return el.firstChild;
4431 range.setStartAfter(el.lastChild);
4432 frag = range.createContextualFragment(html);
4433 el.appendChild(frag);
4434 return el.lastChild;
4436 el.innerHTML = html;
4437 return el.lastChild;
4440 range.setStartAfter(el);
4441 frag = range.createContextualFragment(html);
4442 el.parentNode.insertBefore(frag, el.nextSibling);
4443 return el.nextSibling;
4445 throw 'Illegal insertion point -> "' + where + '"';
4449 * Creates new Dom element(s) and inserts them before el
4450 * @param {String/HTMLElement/Element} el The context element
4451 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4452 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4453 * @return {HTMLElement/Roo.Element} The new node
4455 insertBefore : function(el, o, returnElement){
4456 return this.doInsert(el, o, returnElement, "beforeBegin");
4460 * Creates new Dom element(s) and inserts them after el
4461 * @param {String/HTMLElement/Element} el The context element
4462 * @param {Object} o The Dom object spec (and children)
4463 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4464 * @return {HTMLElement/Roo.Element} The new node
4466 insertAfter : function(el, o, returnElement){
4467 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4471 * Creates new Dom element(s) and inserts them as the first child of el
4472 * @param {String/HTMLElement/Element} el The context element
4473 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4474 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4475 * @return {HTMLElement/Roo.Element} The new node
4477 insertFirst : function(el, o, returnElement){
4478 return this.doInsert(el, o, returnElement, "afterBegin");
4482 doInsert : function(el, o, returnElement, pos, sibling){
4483 el = Roo.getDom(el);
4485 if(this.useDom || o.ns){
4486 newNode = createDom(o, null);
4487 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4489 var html = createHtml(o);
4490 newNode = this.insertHtml(pos, el, html);
4492 return returnElement ? Roo.get(newNode, true) : newNode;
4496 * Creates new Dom element(s) and appends them to el
4497 * @param {String/HTMLElement/Element} el The context element
4498 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4499 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4500 * @return {HTMLElement/Roo.Element} The new node
4502 append : function(el, o, returnElement){
4503 el = Roo.getDom(el);
4505 if(this.useDom || o.ns){
4506 newNode = createDom(o, null);
4507 el.appendChild(newNode);
4509 var html = createHtml(o);
4510 newNode = this.insertHtml("beforeEnd", el, html);
4512 return returnElement ? Roo.get(newNode, true) : newNode;
4516 * Creates new Dom element(s) and overwrites the contents of el with them
4517 * @param {String/HTMLElement/Element} el The context element
4518 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4519 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4520 * @return {HTMLElement/Roo.Element} The new node
4522 overwrite : function(el, o, returnElement){
4523 el = Roo.getDom(el);
4526 while (el.childNodes.length) {
4527 el.removeChild(el.firstChild);
4531 el.innerHTML = createHtml(o);
4534 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4538 * Creates a new Roo.DomHelper.Template from the Dom object spec
4539 * @param {Object} o The Dom object spec (and children)
4540 * @return {Roo.DomHelper.Template} The new template
4542 createTemplate : function(o){
4543 var html = createHtml(o);
4544 return new Roo.Template(html);
4550 * Ext JS Library 1.1.1
4551 * Copyright(c) 2006-2007, Ext JS, LLC.
4553 * Originally Released Under LGPL - original licence link has changed is not relivant.
4556 * <script type="text/javascript">
4560 * @class Roo.Template
4561 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4562 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4565 var t = new Roo.Template({
4566 html : '<div name="{id}">' +
4567 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4569 myformat: function (value, allValues) {
4570 return 'XX' + value;
4573 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4575 * For more information see this blog post with examples:
4576 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4577 - Create Elements using DOM, HTML fragments and Templates</a>.
4579 * @param {Object} cfg - Configuration object.
4581 Roo.Template = function(cfg){
4583 if(cfg instanceof Array){
4585 }else if(arguments.length > 1){
4586 cfg = Array.prototype.join.call(arguments, "");
4590 if (typeof(cfg) == 'object') {
4601 Roo.Template.prototype = {
4604 * @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..
4605 * it should be fixed so that template is observable...
4609 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4613 * Returns an HTML fragment of this template with the specified values applied.
4614 * @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'})
4615 * @return {String} The HTML fragment
4617 applyTemplate : function(values){
4621 return this.compiled(values);
4623 var useF = this.disableFormats !== true;
4624 var fm = Roo.util.Format, tpl = this;
4625 var fn = function(m, name, format, args){
4627 if(format.substr(0, 5) == "this."){
4628 return tpl.call(format.substr(5), values[name], values);
4631 // quoted values are required for strings in compiled templates,
4632 // but for non compiled we need to strip them
4633 // quoted reversed for jsmin
4634 var re = /^\s*['"](.*)["']\s*$/;
4635 args = args.split(',');
4636 for(var i = 0, len = args.length; i < len; i++){
4637 args[i] = args[i].replace(re, "$1");
4639 args = [values[name]].concat(args);
4641 args = [values[name]];
4643 return fm[format].apply(fm, args);
4646 return values[name] !== undefined ? values[name] : "";
4649 return this.html.replace(this.re, fn);
4667 this.loading = true;
4668 this.compiled = false;
4670 var cx = new Roo.data.Connection();
4674 success : function (response) {
4676 _t.html = response.responseText;
4680 failure : function(response) {
4681 Roo.log("Template failed to load from " + _t.url);
4688 * Sets the HTML used as the template and optionally compiles it.
4689 * @param {String} html
4690 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4691 * @return {Roo.Template} this
4693 set : function(html, compile){
4695 this.compiled = null;
4703 * True to disable format functions (defaults to false)
4706 disableFormats : false,
4709 * The regular expression used to match template variables
4713 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4716 * Compiles the template into an internal function, eliminating the RegEx overhead.
4717 * @return {Roo.Template} this
4719 compile : function(){
4720 var fm = Roo.util.Format;
4721 var useF = this.disableFormats !== true;
4722 var sep = Roo.isGecko ? "+" : ",";
4723 var fn = function(m, name, format, args){
4725 args = args ? ',' + args : "";
4726 if(format.substr(0, 5) != "this."){
4727 format = "fm." + format + '(';
4729 format = 'this.call("'+ format.substr(5) + '", ';
4733 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4735 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4738 // branched to use + in gecko and [].join() in others
4740 body = "this.compiled = function(values){ return '" +
4741 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4744 body = ["this.compiled = function(values){ return ['"];
4745 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4746 body.push("'].join('');};");
4747 body = body.join('');
4757 // private function used to call members
4758 call : function(fnName, value, allValues){
4759 return this[fnName](value, allValues);
4763 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4764 * @param {String/HTMLElement/Roo.Element} el The context element
4765 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4766 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4767 * @return {HTMLElement/Roo.Element} The new node or Element
4769 insertFirst: function(el, values, returnElement){
4770 return this.doInsert('afterBegin', el, values, returnElement);
4774 * Applies the supplied values to the template and inserts the new node(s) before el.
4775 * @param {String/HTMLElement/Roo.Element} el The context element
4776 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4777 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4778 * @return {HTMLElement/Roo.Element} The new node or Element
4780 insertBefore: function(el, values, returnElement){
4781 return this.doInsert('beforeBegin', el, values, returnElement);
4785 * Applies the supplied values to the template and inserts the new node(s) after el.
4786 * @param {String/HTMLElement/Roo.Element} el The context element
4787 * @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'})
4788 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4789 * @return {HTMLElement/Roo.Element} The new node or Element
4791 insertAfter : function(el, values, returnElement){
4792 return this.doInsert('afterEnd', el, values, returnElement);
4796 * Applies the supplied values to the template and appends the new node(s) to el.
4797 * @param {String/HTMLElement/Roo.Element} el The context element
4798 * @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'})
4799 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4800 * @return {HTMLElement/Roo.Element} The new node or Element
4802 append : function(el, values, returnElement){
4803 return this.doInsert('beforeEnd', el, values, returnElement);
4806 doInsert : function(where, el, values, returnEl){
4807 el = Roo.getDom(el);
4808 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4809 return returnEl ? Roo.get(newNode, true) : newNode;
4813 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4814 * @param {String/HTMLElement/Roo.Element} el The context element
4815 * @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'})
4816 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4817 * @return {HTMLElement/Roo.Element} The new node or Element
4819 overwrite : function(el, values, returnElement){
4820 el = Roo.getDom(el);
4821 el.innerHTML = this.applyTemplate(values);
4822 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4826 * Alias for {@link #applyTemplate}
4829 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4832 Roo.DomHelper.Template = Roo.Template;
4835 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4836 * @param {String/HTMLElement} el A DOM element or its id
4837 * @returns {Roo.Template} The created template
4840 Roo.Template.from = function(el){
4841 el = Roo.getDom(el);
4842 return new Roo.Template(el.value || el.innerHTML);
4845 * Ext JS Library 1.1.1
4846 * Copyright(c) 2006-2007, Ext JS, LLC.
4848 * Originally Released Under LGPL - original licence link has changed is not relivant.
4851 * <script type="text/javascript">
4856 * This is code is also distributed under MIT license for use
4857 * with jQuery and prototype JavaScript libraries.
4860 * @class Roo.DomQuery
4861 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).
4863 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>
4866 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.
4868 <h4>Element Selectors:</h4>
4870 <li> <b>*</b> any element</li>
4871 <li> <b>E</b> an element with the tag E</li>
4872 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4873 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4874 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4875 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4877 <h4>Attribute Selectors:</h4>
4878 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4880 <li> <b>E[foo]</b> has an attribute "foo"</li>
4881 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4882 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4883 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4884 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4885 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4886 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4888 <h4>Pseudo Classes:</h4>
4890 <li> <b>E:first-child</b> E is the first child of its parent</li>
4891 <li> <b>E:last-child</b> E is the last child of its parent</li>
4892 <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>
4893 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4894 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4895 <li> <b>E:only-child</b> E is the only child of its parent</li>
4896 <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>
4897 <li> <b>E:first</b> the first E in the resultset</li>
4898 <li> <b>E:last</b> the last E in the resultset</li>
4899 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4900 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4901 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4902 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4903 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4904 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4905 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4906 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4907 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4909 <h4>CSS Value Selectors:</h4>
4911 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4912 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4913 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4914 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4915 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4916 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4920 Roo.DomQuery = function(){
4921 var cache = {}, simpleCache = {}, valueCache = {};
4922 var nonSpace = /\S/;
4923 var trimRe = /^\s+|\s+$/g;
4924 var tplRe = /\{(\d+)\}/g;
4925 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4926 var tagTokenRe = /^(#)?([\w-\*]+)/;
4927 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4929 function child(p, index){
4931 var n = p.firstChild;
4933 if(n.nodeType == 1){
4944 while((n = n.nextSibling) && n.nodeType != 1);
4949 while((n = n.previousSibling) && n.nodeType != 1);
4953 function children(d){
4954 var n = d.firstChild, ni = -1;
4956 var nx = n.nextSibling;
4957 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4967 function byClassName(c, a, v){
4971 var r = [], ri = -1, cn;
4972 for(var i = 0, ci; ci = c[i]; i++){
4973 if((' '+ci.className+' ').indexOf(v) != -1){
4980 function attrValue(n, attr){
4981 if(!n.tagName && typeof n.length != "undefined"){
4990 if(attr == "class" || attr == "className"){
4993 return n.getAttribute(attr) || n[attr];
4997 function getNodes(ns, mode, tagName){
4998 var result = [], ri = -1, cs;
5002 tagName = tagName || "*";
5003 if(typeof ns.getElementsByTagName != "undefined"){
5007 for(var i = 0, ni; ni = ns[i]; i++){
5008 cs = ni.getElementsByTagName(tagName);
5009 for(var j = 0, ci; ci = cs[j]; j++){
5013 }else if(mode == "/" || mode == ">"){
5014 var utag = tagName.toUpperCase();
5015 for(var i = 0, ni, cn; ni = ns[i]; i++){
5016 cn = ni.children || ni.childNodes;
5017 for(var j = 0, cj; cj = cn[j]; j++){
5018 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5023 }else if(mode == "+"){
5024 var utag = tagName.toUpperCase();
5025 for(var i = 0, n; n = ns[i]; i++){
5026 while((n = n.nextSibling) && n.nodeType != 1);
5027 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5031 }else if(mode == "~"){
5032 for(var i = 0, n; n = ns[i]; i++){
5033 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5042 function concat(a, b){
5046 for(var i = 0, l = b.length; i < l; i++){
5052 function byTag(cs, tagName){
5053 if(cs.tagName || cs == document){
5059 var r = [], ri = -1;
5060 tagName = tagName.toLowerCase();
5061 for(var i = 0, ci; ci = cs[i]; i++){
5062 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5069 function byId(cs, attr, id){
5070 if(cs.tagName || cs == document){
5076 var r = [], ri = -1;
5077 for(var i = 0,ci; ci = cs[i]; i++){
5078 if(ci && ci.id == id){
5086 function byAttribute(cs, attr, value, op, custom){
5087 var r = [], ri = -1, st = custom=="{";
5088 var f = Roo.DomQuery.operators[op];
5089 for(var i = 0, ci; ci = cs[i]; i++){
5092 a = Roo.DomQuery.getStyle(ci, attr);
5094 else if(attr == "class" || attr == "className"){
5096 }else if(attr == "for"){
5098 }else if(attr == "href"){
5099 a = ci.getAttribute("href", 2);
5101 a = ci.getAttribute(attr);
5103 if((f && f(a, value)) || (!f && a)){
5110 function byPseudo(cs, name, value){
5111 return Roo.DomQuery.pseudos[name](cs, value);
5114 // This is for IE MSXML which does not support expandos.
5115 // IE runs the same speed using setAttribute, however FF slows way down
5116 // and Safari completely fails so they need to continue to use expandos.
5117 var isIE = window.ActiveXObject ? true : false;
5119 // this eval is stop the compressor from
5120 // renaming the variable to something shorter
5122 /** eval:var:batch */
5127 function nodupIEXml(cs){
5129 cs[0].setAttribute("_nodup", d);
5131 for(var i = 1, len = cs.length; i < len; i++){
5133 if(!c.getAttribute("_nodup") != d){
5134 c.setAttribute("_nodup", d);
5138 for(var i = 0, len = cs.length; i < len; i++){
5139 cs[i].removeAttribute("_nodup");
5148 var len = cs.length, c, i, r = cs, cj, ri = -1;
5149 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5152 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5153 return nodupIEXml(cs);
5157 for(i = 1; c = cs[i]; i++){
5162 for(var j = 0; j < i; j++){
5165 for(j = i+1; cj = cs[j]; j++){
5177 function quickDiffIEXml(c1, c2){
5179 for(var i = 0, len = c1.length; i < len; i++){
5180 c1[i].setAttribute("_qdiff", d);
5183 for(var i = 0, len = c2.length; i < len; i++){
5184 if(c2[i].getAttribute("_qdiff") != d){
5185 r[r.length] = c2[i];
5188 for(var i = 0, len = c1.length; i < len; i++){
5189 c1[i].removeAttribute("_qdiff");
5194 function quickDiff(c1, c2){
5195 var len1 = c1.length;
5199 if(isIE && c1[0].selectSingleNode){
5200 return quickDiffIEXml(c1, c2);
5203 for(var i = 0; i < len1; i++){
5207 for(var i = 0, len = c2.length; i < len; i++){
5208 if(c2[i]._qdiff != d){
5209 r[r.length] = c2[i];
5215 function quickId(ns, mode, root, id){
5217 var d = root.ownerDocument || root;
5218 return d.getElementById(id);
5220 ns = getNodes(ns, mode, "*");
5221 return byId(ns, null, id);
5225 getStyle : function(el, name){
5226 return Roo.fly(el).getStyle(name);
5229 * Compiles a selector/xpath query into a reusable function. The returned function
5230 * takes one parameter "root" (optional), which is the context node from where the query should start.
5231 * @param {String} selector The selector/xpath query
5232 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5233 * @return {Function}
5235 compile : function(path, type){
5236 type = type || "select";
5238 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5239 var q = path, mode, lq;
5240 var tk = Roo.DomQuery.matchers;
5241 var tklen = tk.length;
5244 // accept leading mode switch
5245 var lmode = q.match(modeRe);
5246 if(lmode && lmode[1]){
5247 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5248 q = q.replace(lmode[1], "");
5250 // strip leading slashes
5251 while(path.substr(0, 1)=="/"){
5252 path = path.substr(1);
5255 while(q && lq != q){
5257 var tm = q.match(tagTokenRe);
5258 if(type == "select"){
5261 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5263 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5265 q = q.replace(tm[0], "");
5266 }else if(q.substr(0, 1) != '@'){
5267 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5272 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5274 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5276 q = q.replace(tm[0], "");
5279 while(!(mm = q.match(modeRe))){
5280 var matched = false;
5281 for(var j = 0; j < tklen; j++){
5283 var m = q.match(t.re);
5285 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5288 q = q.replace(m[0], "");
5293 // prevent infinite loop on bad selector
5295 throw 'Error parsing selector, parsing failed at "' + q + '"';
5299 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5300 q = q.replace(mm[1], "");
5303 fn[fn.length] = "return nodup(n);\n}";
5306 * list of variables that need from compression as they are used by eval.
5316 * eval:var:byClassName
5318 * eval:var:byAttribute
5319 * eval:var:attrValue
5327 * Selects a group of elements.
5328 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5329 * @param {Node} root (optional) The start of the query (defaults to document).
5332 select : function(path, root, type){
5333 if(!root || root == document){
5336 if(typeof root == "string"){
5337 root = document.getElementById(root);
5339 var paths = path.split(",");
5341 for(var i = 0, len = paths.length; i < len; i++){
5342 var p = paths[i].replace(trimRe, "");
5344 cache[p] = Roo.DomQuery.compile(p);
5346 throw p + " is not a valid selector";
5349 var result = cache[p](root);
5350 if(result && result != document){
5351 results = results.concat(result);
5354 if(paths.length > 1){
5355 return nodup(results);
5361 * Selects a single element.
5362 * @param {String} selector The selector/xpath query
5363 * @param {Node} root (optional) The start of the query (defaults to document).
5366 selectNode : function(path, root){
5367 return Roo.DomQuery.select(path, root)[0];
5371 * Selects the value of a node, optionally replacing null with the defaultValue.
5372 * @param {String} selector The selector/xpath query
5373 * @param {Node} root (optional) The start of the query (defaults to document).
5374 * @param {String} defaultValue
5376 selectValue : function(path, root, defaultValue){
5377 path = path.replace(trimRe, "");
5378 if(!valueCache[path]){
5379 valueCache[path] = Roo.DomQuery.compile(path, "select");
5381 var n = valueCache[path](root);
5382 n = n[0] ? n[0] : n;
5383 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5384 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5388 * Selects the value of a node, parsing integers and floats.
5389 * @param {String} selector The selector/xpath query
5390 * @param {Node} root (optional) The start of the query (defaults to document).
5391 * @param {Number} defaultValue
5394 selectNumber : function(path, root, defaultValue){
5395 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5396 return parseFloat(v);
5400 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5401 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5402 * @param {String} selector The simple selector to test
5405 is : function(el, ss){
5406 if(typeof el == "string"){
5407 el = document.getElementById(el);
5409 var isArray = (el instanceof Array);
5410 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5411 return isArray ? (result.length == el.length) : (result.length > 0);
5415 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5416 * @param {Array} el An array of elements to filter
5417 * @param {String} selector The simple selector to test
5418 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5419 * the selector instead of the ones that match
5422 filter : function(els, ss, nonMatches){
5423 ss = ss.replace(trimRe, "");
5424 if(!simpleCache[ss]){
5425 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5427 var result = simpleCache[ss](els);
5428 return nonMatches ? quickDiff(result, els) : result;
5432 * Collection of matching regular expressions and code snippets.
5436 select: 'n = byClassName(n, null, " {1} ");'
5438 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5439 select: 'n = byPseudo(n, "{1}", "{2}");'
5441 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5442 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5445 select: 'n = byId(n, null, "{1}");'
5448 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5453 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5454 * 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, > <.
5457 "=" : function(a, v){
5460 "!=" : function(a, v){
5463 "^=" : function(a, v){
5464 return a && a.substr(0, v.length) == v;
5466 "$=" : function(a, v){
5467 return a && a.substr(a.length-v.length) == v;
5469 "*=" : function(a, v){
5470 return a && a.indexOf(v) !== -1;
5472 "%=" : function(a, v){
5473 return (a % v) == 0;
5475 "|=" : function(a, v){
5476 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5478 "~=" : function(a, v){
5479 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5484 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5485 * and the argument (if any) supplied in the selector.
5488 "first-child" : function(c){
5489 var r = [], ri = -1, n;
5490 for(var i = 0, ci; ci = n = c[i]; i++){
5491 while((n = n.previousSibling) && n.nodeType != 1);
5499 "last-child" : function(c){
5500 var r = [], ri = -1, n;
5501 for(var i = 0, ci; ci = n = c[i]; i++){
5502 while((n = n.nextSibling) && n.nodeType != 1);
5510 "nth-child" : function(c, a) {
5511 var r = [], ri = -1;
5512 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5513 var f = (m[1] || 1) - 0, l = m[2] - 0;
5514 for(var i = 0, n; n = c[i]; i++){
5515 var pn = n.parentNode;
5516 if (batch != pn._batch) {
5518 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5519 if(cn.nodeType == 1){
5526 if (l == 0 || n.nodeIndex == l){
5529 } else if ((n.nodeIndex + l) % f == 0){
5537 "only-child" : function(c){
5538 var r = [], ri = -1;;
5539 for(var i = 0, ci; ci = c[i]; i++){
5540 if(!prev(ci) && !next(ci)){
5547 "empty" : function(c){
5548 var r = [], ri = -1;
5549 for(var i = 0, ci; ci = c[i]; i++){
5550 var cns = ci.childNodes, j = 0, cn, empty = true;
5553 if(cn.nodeType == 1 || cn.nodeType == 3){
5565 "contains" : function(c, v){
5566 var r = [], ri = -1;
5567 for(var i = 0, ci; ci = c[i]; i++){
5568 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5575 "nodeValue" : function(c, v){
5576 var r = [], ri = -1;
5577 for(var i = 0, ci; ci = c[i]; i++){
5578 if(ci.firstChild && ci.firstChild.nodeValue == v){
5585 "checked" : function(c){
5586 var r = [], ri = -1;
5587 for(var i = 0, ci; ci = c[i]; i++){
5588 if(ci.checked == true){
5595 "not" : function(c, ss){
5596 return Roo.DomQuery.filter(c, ss, true);
5599 "odd" : function(c){
5600 return this["nth-child"](c, "odd");
5603 "even" : function(c){
5604 return this["nth-child"](c, "even");
5607 "nth" : function(c, a){
5608 return c[a-1] || [];
5611 "first" : function(c){
5615 "last" : function(c){
5616 return c[c.length-1] || [];
5619 "has" : function(c, ss){
5620 var s = Roo.DomQuery.select;
5621 var r = [], ri = -1;
5622 for(var i = 0, ci; ci = c[i]; i++){
5623 if(s(ss, ci).length > 0){
5630 "next" : function(c, ss){
5631 var is = Roo.DomQuery.is;
5632 var r = [], ri = -1;
5633 for(var i = 0, ci; ci = c[i]; i++){
5642 "prev" : function(c, ss){
5643 var is = Roo.DomQuery.is;
5644 var r = [], ri = -1;
5645 for(var i = 0, ci; ci = c[i]; i++){
5658 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5659 * @param {String} path The selector/xpath query
5660 * @param {Node} root (optional) The start of the query (defaults to document).
5665 Roo.query = Roo.DomQuery.select;
5668 * Ext JS Library 1.1.1
5669 * Copyright(c) 2006-2007, Ext JS, LLC.
5671 * Originally Released Under LGPL - original licence link has changed is not relivant.
5674 * <script type="text/javascript">
5678 * @class Roo.util.Observable
5679 * Base class that provides a common interface for publishing events. Subclasses are expected to
5680 * to have a property "events" with all the events defined.<br>
5683 Employee = function(name){
5690 Roo.extend(Employee, Roo.util.Observable);
5692 * @param {Object} config properties to use (incuding events / listeners)
5695 Roo.util.Observable = function(cfg){
5698 this.addEvents(cfg.events || {});
5700 delete cfg.events; // make sure
5703 Roo.apply(this, cfg);
5706 this.on(this.listeners);
5707 delete this.listeners;
5710 Roo.util.Observable.prototype = {
5712 * @cfg {Object} listeners list of events and functions to call for this object,
5716 'click' : function(e) {
5726 * Fires the specified event with the passed parameters (minus the event name).
5727 * @param {String} eventName
5728 * @param {Object...} args Variable number of parameters are passed to handlers
5729 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5731 fireEvent : function(){
5732 var ce = this.events[arguments[0].toLowerCase()];
5733 if(typeof ce == "object"){
5734 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5741 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5744 * Appends an event handler to this component
5745 * @param {String} eventName The type of event to listen for
5746 * @param {Function} handler The method the event invokes
5747 * @param {Object} scope (optional) The scope in which to execute the handler
5748 * function. The handler function's "this" context.
5749 * @param {Object} options (optional) An object containing handler configuration
5750 * properties. This may contain any of the following properties:<ul>
5751 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5752 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5753 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5754 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5755 * by the specified number of milliseconds. If the event fires again within that time, the original
5756 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5759 * <b>Combining Options</b><br>
5760 * Using the options argument, it is possible to combine different types of listeners:<br>
5762 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5764 el.on('click', this.onClick, this, {
5771 * <b>Attaching multiple handlers in 1 call</b><br>
5772 * The method also allows for a single argument to be passed which is a config object containing properties
5773 * which specify multiple handlers.
5782 fn: this.onMouseOver,
5786 fn: this.onMouseOut,
5792 * Or a shorthand syntax which passes the same scope object to all handlers:
5795 'click': this.onClick,
5796 'mouseover': this.onMouseOver,
5797 'mouseout': this.onMouseOut,
5802 addListener : function(eventName, fn, scope, o){
5803 if(typeof eventName == "object"){
5806 if(this.filterOptRe.test(e)){
5809 if(typeof o[e] == "function"){
5811 this.addListener(e, o[e], o.scope, o);
5813 // individual options
5814 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5819 o = (!o || typeof o == "boolean") ? {} : o;
5820 eventName = eventName.toLowerCase();
5821 var ce = this.events[eventName] || true;
5822 if(typeof ce == "boolean"){
5823 ce = new Roo.util.Event(this, eventName);
5824 this.events[eventName] = ce;
5826 ce.addListener(fn, scope, o);
5830 * Removes a listener
5831 * @param {String} eventName The type of event to listen for
5832 * @param {Function} handler The handler to remove
5833 * @param {Object} scope (optional) The scope (this object) for the handler
5835 removeListener : function(eventName, fn, scope){
5836 var ce = this.events[eventName.toLowerCase()];
5837 if(typeof ce == "object"){
5838 ce.removeListener(fn, scope);
5843 * Removes all listeners for this object
5845 purgeListeners : function(){
5846 for(var evt in this.events){
5847 if(typeof this.events[evt] == "object"){
5848 this.events[evt].clearListeners();
5853 relayEvents : function(o, events){
5854 var createHandler = function(ename){
5856 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5859 for(var i = 0, len = events.length; i < len; i++){
5860 var ename = events[i];
5861 if(!this.events[ename]){ this.events[ename] = true; };
5862 o.on(ename, createHandler(ename), this);
5867 * Used to define events on this Observable
5868 * @param {Object} object The object with the events defined
5870 addEvents : function(o){
5874 Roo.applyIf(this.events, o);
5878 * Checks to see if this object has any listeners for a specified event
5879 * @param {String} eventName The name of the event to check for
5880 * @return {Boolean} True if the event is being listened for, else false
5882 hasListener : function(eventName){
5883 var e = this.events[eventName];
5884 return typeof e == "object" && e.listeners.length > 0;
5888 * Appends an event handler to this element (shorthand for addListener)
5889 * @param {String} eventName The type of event to listen for
5890 * @param {Function} handler The method the event invokes
5891 * @param {Object} scope (optional) The scope in which to execute the handler
5892 * function. The handler function's "this" context.
5893 * @param {Object} options (optional)
5896 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5898 * Removes a listener (shorthand for removeListener)
5899 * @param {String} eventName The type of event to listen for
5900 * @param {Function} handler The handler to remove
5901 * @param {Object} scope (optional) The scope (this object) for the handler
5904 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5907 * Starts capture on the specified Observable. All events will be passed
5908 * to the supplied function with the event name + standard signature of the event
5909 * <b>before</b> the event is fired. If the supplied function returns false,
5910 * the event will not fire.
5911 * @param {Observable} o The Observable to capture
5912 * @param {Function} fn The function to call
5913 * @param {Object} scope (optional) The scope (this object) for the fn
5916 Roo.util.Observable.capture = function(o, fn, scope){
5917 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5921 * Removes <b>all</b> added captures from the Observable.
5922 * @param {Observable} o The Observable to release
5925 Roo.util.Observable.releaseCapture = function(o){
5926 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5931 var createBuffered = function(h, o, scope){
5932 var task = new Roo.util.DelayedTask();
5934 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5938 var createSingle = function(h, e, fn, scope){
5940 e.removeListener(fn, scope);
5941 return h.apply(scope, arguments);
5945 var createDelayed = function(h, o, scope){
5947 var args = Array.prototype.slice.call(arguments, 0);
5948 setTimeout(function(){
5949 h.apply(scope, args);
5954 Roo.util.Event = function(obj, name){
5957 this.listeners = [];
5960 Roo.util.Event.prototype = {
5961 addListener : function(fn, scope, options){
5962 var o = options || {};
5963 scope = scope || this.obj;
5964 if(!this.isListening(fn, scope)){
5965 var l = {fn: fn, scope: scope, options: o};
5968 h = createDelayed(h, o, scope);
5971 h = createSingle(h, this, fn, scope);
5974 h = createBuffered(h, o, scope);
5977 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5978 this.listeners.push(l);
5980 this.listeners = this.listeners.slice(0);
5981 this.listeners.push(l);
5986 findListener : function(fn, scope){
5987 scope = scope || this.obj;
5988 var ls = this.listeners;
5989 for(var i = 0, len = ls.length; i < len; i++){
5991 if(l.fn == fn && l.scope == scope){
5998 isListening : function(fn, scope){
5999 return this.findListener(fn, scope) != -1;
6002 removeListener : function(fn, scope){
6004 if((index = this.findListener(fn, scope)) != -1){
6006 this.listeners.splice(index, 1);
6008 this.listeners = this.listeners.slice(0);
6009 this.listeners.splice(index, 1);
6016 clearListeners : function(){
6017 this.listeners = [];
6021 var ls = this.listeners, scope, len = ls.length;
6024 var args = Array.prototype.slice.call(arguments, 0);
6025 for(var i = 0; i < len; i++){
6027 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6028 this.firing = false;
6032 this.firing = false;
6039 * Ext JS Library 1.1.1
6040 * Copyright(c) 2006-2007, Ext JS, LLC.
6042 * Originally Released Under LGPL - original licence link has changed is not relivant.
6045 * <script type="text/javascript">
6049 * @class Roo.EventManager
6050 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6051 * several useful events directly.
6052 * See {@link Roo.EventObject} for more details on normalized event objects.
6055 Roo.EventManager = function(){
6056 var docReadyEvent, docReadyProcId, docReadyState = false;
6057 var resizeEvent, resizeTask, textEvent, textSize;
6058 var E = Roo.lib.Event;
6059 var D = Roo.lib.Dom;
6064 var fireDocReady = function(){
6066 docReadyState = true;
6069 clearInterval(docReadyProcId);
6071 if(Roo.isGecko || Roo.isOpera) {
6072 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6075 var defer = document.getElementById("ie-deferred-loader");
6077 defer.onreadystatechange = null;
6078 defer.parentNode.removeChild(defer);
6082 docReadyEvent.fire();
6083 docReadyEvent.clearListeners();
6088 var initDocReady = function(){
6089 docReadyEvent = new Roo.util.Event();
6090 if(Roo.isGecko || Roo.isOpera) {
6091 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6093 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6094 var defer = document.getElementById("ie-deferred-loader");
6095 defer.onreadystatechange = function(){
6096 if(this.readyState == "complete"){
6100 }else if(Roo.isSafari){
6101 docReadyProcId = setInterval(function(){
6102 var rs = document.readyState;
6103 if(rs == "complete") {
6108 // no matter what, make sure it fires on load
6109 E.on(window, "load", fireDocReady);
6112 var createBuffered = function(h, o){
6113 var task = new Roo.util.DelayedTask(h);
6115 // create new event object impl so new events don't wipe out properties
6116 e = new Roo.EventObjectImpl(e);
6117 task.delay(o.buffer, h, null, [e]);
6121 var createSingle = function(h, el, ename, fn){
6123 Roo.EventManager.removeListener(el, ename, fn);
6128 var createDelayed = function(h, o){
6130 // create new event object impl so new events don't wipe out properties
6131 e = new Roo.EventObjectImpl(e);
6132 setTimeout(function(){
6137 var transitionEndVal = false;
6139 var transitionEnd = function()
6141 if (transitionEndVal) {
6142 return transitionEndVal;
6144 var el = document.createElement('div');
6146 var transEndEventNames = {
6147 WebkitTransition : 'webkitTransitionEnd',
6148 MozTransition : 'transitionend',
6149 OTransition : 'oTransitionEnd otransitionend',
6150 transition : 'transitionend'
6153 for (var name in transEndEventNames) {
6154 if (el.style[name] !== undefined) {
6155 transitionEndVal = transEndEventNames[name];
6156 return transitionEndVal ;
6162 var listen = function(element, ename, opt, fn, scope){
6163 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6164 fn = fn || o.fn; scope = scope || o.scope;
6165 var el = Roo.getDom(element);
6169 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6172 if (ename == 'transitionend') {
6173 ename = transitionEnd();
6175 var h = function(e){
6176 e = Roo.EventObject.setEvent(e);
6179 t = e.getTarget(o.delegate, el);
6186 if(o.stopEvent === true){
6189 if(o.preventDefault === true){
6192 if(o.stopPropagation === true){
6193 e.stopPropagation();
6196 if(o.normalized === false){
6200 fn.call(scope || el, e, t, o);
6203 h = createDelayed(h, o);
6206 h = createSingle(h, el, ename, fn);
6209 h = createBuffered(h, o);
6211 fn._handlers = fn._handlers || [];
6214 fn._handlers.push([Roo.id(el), ename, h]);
6219 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6220 el.addEventListener("DOMMouseScroll", h, false);
6221 E.on(window, 'unload', function(){
6222 el.removeEventListener("DOMMouseScroll", h, false);
6225 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6226 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6231 var stopListening = function(el, ename, fn){
6232 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6234 for(var i = 0, len = hds.length; i < len; i++){
6236 if(h[0] == id && h[1] == ename){
6243 E.un(el, ename, hd);
6244 el = Roo.getDom(el);
6245 if(ename == "mousewheel" && el.addEventListener){
6246 el.removeEventListener("DOMMouseScroll", hd, false);
6248 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6249 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6253 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6260 * @scope Roo.EventManager
6265 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6266 * object with a Roo.EventObject
6267 * @param {Function} fn The method the event invokes
6268 * @param {Object} scope An object that becomes the scope of the handler
6269 * @param {boolean} override If true, the obj passed in becomes
6270 * the execution scope of the listener
6271 * @return {Function} The wrapped function
6274 wrap : function(fn, scope, override){
6276 Roo.EventObject.setEvent(e);
6277 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6282 * Appends an event handler to an element (shorthand for addListener)
6283 * @param {String/HTMLElement} element The html element or id to assign the
6284 * @param {String} eventName The type of event to listen for
6285 * @param {Function} handler The method the event invokes
6286 * @param {Object} scope (optional) The scope in which to execute the handler
6287 * function. The handler function's "this" context.
6288 * @param {Object} options (optional) An object containing handler configuration
6289 * properties. This may contain any of the following properties:<ul>
6290 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6291 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6292 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6293 * <li>preventDefault {Boolean} True to prevent the default action</li>
6294 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6295 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6296 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6297 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6298 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6299 * by the specified number of milliseconds. If the event fires again within that time, the original
6300 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6303 * <b>Combining Options</b><br>
6304 * Using the options argument, it is possible to combine different types of listeners:<br>
6306 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6308 el.on('click', this.onClick, this, {
6315 * <b>Attaching multiple handlers in 1 call</b><br>
6316 * The method also allows for a single argument to be passed which is a config object containing properties
6317 * which specify multiple handlers.
6327 fn: this.onMouseOver
6336 * Or a shorthand syntax:<br>
6339 'click' : this.onClick,
6340 'mouseover' : this.onMouseOver,
6341 'mouseout' : this.onMouseOut
6345 addListener : function(element, eventName, fn, scope, options){
6346 if(typeof eventName == "object"){
6352 if(typeof o[e] == "function"){
6354 listen(element, e, o, o[e], o.scope);
6356 // individual options
6357 listen(element, e, o[e]);
6362 return listen(element, eventName, options, fn, scope);
6366 * Removes an event handler
6368 * @param {String/HTMLElement} element The id or html element to remove the
6370 * @param {String} eventName The type of event
6371 * @param {Function} fn
6372 * @return {Boolean} True if a listener was actually removed
6374 removeListener : function(element, eventName, fn){
6375 return stopListening(element, eventName, fn);
6379 * Fires when the document is ready (before onload and before images are loaded). Can be
6380 * accessed shorthanded Roo.onReady().
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 onDocumentReady : function(fn, scope, options){
6386 if(docReadyState){ // if it already fired
6387 docReadyEvent.addListener(fn, scope, options);
6388 docReadyEvent.fire();
6389 docReadyEvent.clearListeners();
6395 docReadyEvent.addListener(fn, scope, options);
6399 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6400 * @param {Function} fn The method the event invokes
6401 * @param {Object} scope An object that becomes the scope of the handler
6402 * @param {boolean} options
6404 onWindowResize : function(fn, scope, options){
6406 resizeEvent = new Roo.util.Event();
6407 resizeTask = new Roo.util.DelayedTask(function(){
6408 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6410 E.on(window, "resize", function(){
6412 resizeTask.delay(50);
6414 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6418 resizeEvent.addListener(fn, scope, options);
6422 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6423 * @param {Function} fn The method the event invokes
6424 * @param {Object} scope An object that becomes the scope of the handler
6425 * @param {boolean} options
6427 onTextResize : function(fn, scope, options){
6429 textEvent = new Roo.util.Event();
6430 var textEl = new Roo.Element(document.createElement('div'));
6431 textEl.dom.className = 'x-text-resize';
6432 textEl.dom.innerHTML = 'X';
6433 textEl.appendTo(document.body);
6434 textSize = textEl.dom.offsetHeight;
6435 setInterval(function(){
6436 if(textEl.dom.offsetHeight != textSize){
6437 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6439 }, this.textResizeInterval);
6441 textEvent.addListener(fn, scope, options);
6445 * Removes the passed window resize listener.
6446 * @param {Function} fn The method the event invokes
6447 * @param {Object} scope The scope of handler
6449 removeResizeListener : function(fn, scope){
6451 resizeEvent.removeListener(fn, scope);
6456 fireResize : function(){
6458 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6462 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6466 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6468 textResizeInterval : 50
6473 * @scopeAlias pub=Roo.EventManager
6477 * Appends an event handler to an element (shorthand for addListener)
6478 * @param {String/HTMLElement} element The html element or id to assign the
6479 * @param {String} eventName The type of event to listen for
6480 * @param {Function} handler The method the event invokes
6481 * @param {Object} scope (optional) The scope in which to execute the handler
6482 * function. The handler function's "this" context.
6483 * @param {Object} options (optional) An object containing handler configuration
6484 * properties. This may contain any of the following properties:<ul>
6485 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6486 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6487 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6488 * <li>preventDefault {Boolean} True to prevent the default action</li>
6489 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6490 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6491 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6492 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6493 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6494 * by the specified number of milliseconds. If the event fires again within that time, the original
6495 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6498 * <b>Combining Options</b><br>
6499 * Using the options argument, it is possible to combine different types of listeners:<br>
6501 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6503 el.on('click', this.onClick, this, {
6510 * <b>Attaching multiple handlers in 1 call</b><br>
6511 * The method also allows for a single argument to be passed which is a config object containing properties
6512 * which specify multiple handlers.
6522 fn: this.onMouseOver
6531 * Or a shorthand syntax:<br>
6534 'click' : this.onClick,
6535 'mouseover' : this.onMouseOver,
6536 'mouseout' : this.onMouseOut
6540 pub.on = pub.addListener;
6541 pub.un = pub.removeListener;
6543 pub.stoppedMouseDownEvent = new Roo.util.Event();
6547 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6548 * @param {Function} fn The method the event invokes
6549 * @param {Object} scope An object that becomes the scope of the handler
6550 * @param {boolean} override If true, the obj passed in becomes
6551 * the execution scope of the listener
6555 Roo.onReady = Roo.EventManager.onDocumentReady;
6557 Roo.onReady(function(){
6558 var bd = Roo.get(document.body);
6563 : Roo.isGecko ? "roo-gecko"
6564 : Roo.isOpera ? "roo-opera"
6565 : Roo.isSafari ? "roo-safari" : ""];
6568 cls.push("roo-mac");
6571 cls.push("roo-linux");
6573 if(Roo.isBorderBox){
6574 cls.push('roo-border-box');
6576 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6577 var p = bd.dom.parentNode;
6579 p.className += ' roo-strict';
6582 bd.addClass(cls.join(' '));
6586 * @class Roo.EventObject
6587 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6588 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6591 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6593 var target = e.getTarget();
6596 var myDiv = Roo.get("myDiv");
6597 myDiv.on("click", handleClick);
6599 Roo.EventManager.on("myDiv", 'click', handleClick);
6600 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6604 Roo.EventObject = function(){
6606 var E = Roo.lib.Event;
6608 // safari keypress events for special keys return bad keycodes
6611 63235 : 39, // right
6614 63276 : 33, // page up
6615 63277 : 34, // page down
6616 63272 : 46, // delete
6621 // normalize button clicks
6622 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6623 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6625 Roo.EventObjectImpl = function(e){
6627 this.setEvent(e.browserEvent || e);
6630 Roo.EventObjectImpl.prototype = {
6632 * Used to fix doc tools.
6633 * @scope Roo.EventObject.prototype
6639 /** The normal browser event */
6640 browserEvent : null,
6641 /** The button pressed in a mouse event */
6643 /** True if the shift key was down during the event */
6645 /** True if the control key was down during the event */
6647 /** True if the alt key was down during the event */
6706 setEvent : function(e){
6707 if(e == this || (e && e.browserEvent)){ // already wrapped
6710 this.browserEvent = e;
6712 // normalize buttons
6713 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6714 if(e.type == 'click' && this.button == -1){
6718 this.shiftKey = e.shiftKey;
6719 // mac metaKey behaves like ctrlKey
6720 this.ctrlKey = e.ctrlKey || e.metaKey;
6721 this.altKey = e.altKey;
6722 // in getKey these will be normalized for the mac
6723 this.keyCode = e.keyCode;
6724 // keyup warnings on firefox.
6725 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6726 // cache the target for the delayed and or buffered events
6727 this.target = E.getTarget(e);
6729 this.xy = E.getXY(e);
6732 this.shiftKey = false;
6733 this.ctrlKey = false;
6734 this.altKey = false;
6744 * Stop the event (preventDefault and stopPropagation)
6746 stopEvent : function(){
6747 if(this.browserEvent){
6748 if(this.browserEvent.type == 'mousedown'){
6749 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6751 E.stopEvent(this.browserEvent);
6756 * Prevents the browsers default handling of the event.
6758 preventDefault : function(){
6759 if(this.browserEvent){
6760 E.preventDefault(this.browserEvent);
6765 isNavKeyPress : function(){
6766 var k = this.keyCode;
6767 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6768 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6771 isSpecialKey : function(){
6772 var k = this.keyCode;
6773 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6774 (k == 16) || (k == 17) ||
6775 (k >= 18 && k <= 20) ||
6776 (k >= 33 && k <= 35) ||
6777 (k >= 36 && k <= 39) ||
6778 (k >= 44 && k <= 45);
6781 * Cancels bubbling of the event.
6783 stopPropagation : function(){
6784 if(this.browserEvent){
6785 if(this.type == 'mousedown'){
6786 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6788 E.stopPropagation(this.browserEvent);
6793 * Gets the key code for the event.
6796 getCharCode : function(){
6797 return this.charCode || this.keyCode;
6801 * Returns a normalized keyCode for the event.
6802 * @return {Number} The key code
6804 getKey : function(){
6805 var k = this.keyCode || this.charCode;
6806 return Roo.isSafari ? (safariKeys[k] || k) : k;
6810 * Gets the x coordinate of the event.
6813 getPageX : function(){
6818 * Gets the y coordinate of the event.
6821 getPageY : function(){
6826 * Gets the time of the event.
6829 getTime : function(){
6830 if(this.browserEvent){
6831 return E.getTime(this.browserEvent);
6837 * Gets the page coordinates of the event.
6838 * @return {Array} The xy values like [x, y]
6845 * Gets the target for the event.
6846 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6847 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6848 search as a number or element (defaults to 10 || document.body)
6849 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6850 * @return {HTMLelement}
6852 getTarget : function(selector, maxDepth, returnEl){
6853 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6856 * Gets the related target.
6857 * @return {HTMLElement}
6859 getRelatedTarget : function(){
6860 if(this.browserEvent){
6861 return E.getRelatedTarget(this.browserEvent);
6867 * Normalizes mouse wheel delta across browsers
6868 * @return {Number} The delta
6870 getWheelDelta : function(){
6871 var e = this.browserEvent;
6873 if(e.wheelDelta){ /* IE/Opera. */
6874 delta = e.wheelDelta/120;
6875 }else if(e.detail){ /* Mozilla case. */
6876 delta = -e.detail/3;
6882 * Returns true if the control, meta, shift or alt key was pressed during this event.
6885 hasModifier : function(){
6886 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6890 * Returns true if the target of this event equals el or is a child of el
6891 * @param {String/HTMLElement/Element} el
6892 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6895 within : function(el, related){
6896 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6897 return t && Roo.fly(el).contains(t);
6900 getPoint : function(){
6901 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6905 return new Roo.EventObjectImpl();
6910 * Ext JS Library 1.1.1
6911 * Copyright(c) 2006-2007, Ext JS, LLC.
6913 * Originally Released Under LGPL - original licence link has changed is not relivant.
6916 * <script type="text/javascript">
6920 // was in Composite Element!??!?!
6923 var D = Roo.lib.Dom;
6924 var E = Roo.lib.Event;
6925 var A = Roo.lib.Anim;
6927 // local style camelizing for speed
6929 var camelRe = /(-[a-z])/gi;
6930 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6931 var view = document.defaultView;
6934 * @class Roo.Element
6935 * Represents an Element in the DOM.<br><br>
6938 var el = Roo.get("my-div");
6941 var el = getEl("my-div");
6943 // or with a DOM element
6944 var el = Roo.get(myDivElement);
6946 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6947 * each call instead of constructing a new one.<br><br>
6948 * <b>Animations</b><br />
6949 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6950 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6952 Option Default Description
6953 --------- -------- ---------------------------------------------
6954 duration .35 The duration of the animation in seconds
6955 easing easeOut The YUI easing method
6956 callback none A function to execute when the anim completes
6957 scope this The scope (this) of the callback function
6959 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6960 * manipulate the animation. Here's an example:
6962 var el = Roo.get("my-div");
6967 // default animation
6968 el.setWidth(100, true);
6970 // animation with some options set
6977 // using the "anim" property to get the Anim object
6983 el.setWidth(100, opt);
6985 if(opt.anim.isAnimated()){
6989 * <b> Composite (Collections of) Elements</b><br />
6990 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6991 * @constructor Create a new Element directly.
6992 * @param {String/HTMLElement} element
6993 * @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).
6995 Roo.Element = function(element, forceNew){
6996 var dom = typeof element == "string" ?
6997 document.getElementById(element) : element;
6998 if(!dom){ // invalid id/element
7002 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7003 return Roo.Element.cache[id];
7013 * The DOM element ID
7016 this.id = id || Roo.id(dom);
7019 var El = Roo.Element;
7023 * The element's default display mode (defaults to "")
7026 originalDisplay : "",
7030 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7035 * Sets the element's visibility mode. When setVisible() is called it
7036 * will use this to determine whether to set the visibility or the display property.
7037 * @param visMode Element.VISIBILITY or Element.DISPLAY
7038 * @return {Roo.Element} this
7040 setVisibilityMode : function(visMode){
7041 this.visibilityMode = visMode;
7045 * Convenience method for setVisibilityMode(Element.DISPLAY)
7046 * @param {String} display (optional) What to set display to when visible
7047 * @return {Roo.Element} this
7049 enableDisplayMode : function(display){
7050 this.setVisibilityMode(El.DISPLAY);
7051 if(typeof display != "undefined") this.originalDisplay = display;
7056 * 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)
7057 * @param {String} selector The simple selector to test
7058 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7059 search as a number or element (defaults to 10 || document.body)
7060 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7061 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7063 findParent : function(simpleSelector, maxDepth, returnEl){
7064 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7065 maxDepth = maxDepth || 50;
7066 if(typeof maxDepth != "number"){
7067 stopEl = Roo.getDom(maxDepth);
7070 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7071 if(dq.is(p, simpleSelector)){
7072 return returnEl ? Roo.get(p) : p;
7082 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7083 * @param {String} selector The simple selector to test
7084 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7085 search as a number or element (defaults to 10 || document.body)
7086 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7087 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7089 findParentNode : function(simpleSelector, maxDepth, returnEl){
7090 var p = Roo.fly(this.dom.parentNode, '_internal');
7091 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7095 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7096 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7097 * @param {String} selector The simple selector to test
7098 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7099 search as a number or element (defaults to 10 || document.body)
7100 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7102 up : function(simpleSelector, maxDepth){
7103 return this.findParentNode(simpleSelector, maxDepth, true);
7109 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7110 * @param {String} selector The simple selector to test
7111 * @return {Boolean} True if this element matches the selector, else false
7113 is : function(simpleSelector){
7114 return Roo.DomQuery.is(this.dom, simpleSelector);
7118 * Perform animation on this element.
7119 * @param {Object} args The YUI animation control args
7120 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7121 * @param {Function} onComplete (optional) Function to call when animation completes
7122 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7123 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7124 * @return {Roo.Element} this
7126 animate : function(args, duration, onComplete, easing, animType){
7127 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7132 * @private Internal animation call
7134 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7135 animType = animType || 'run';
7137 var anim = Roo.lib.Anim[animType](
7139 (opt.duration || defaultDur) || .35,
7140 (opt.easing || defaultEase) || 'easeOut',
7142 Roo.callback(cb, this);
7143 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7151 // private legacy anim prep
7152 preanim : function(a, i){
7153 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7157 * Removes worthless text nodes
7158 * @param {Boolean} forceReclean (optional) By default the element
7159 * keeps track if it has been cleaned already so
7160 * you can call this over and over. However, if you update the element and
7161 * need to force a reclean, you can pass true.
7163 clean : function(forceReclean){
7164 if(this.isCleaned && forceReclean !== true){
7168 var d = this.dom, n = d.firstChild, ni = -1;
7170 var nx = n.nextSibling;
7171 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7178 this.isCleaned = true;
7183 calcOffsetsTo : function(el){
7186 var restorePos = false;
7187 if(el.getStyle('position') == 'static'){
7188 el.position('relative');
7193 while(op && op != d && op.tagName != 'HTML'){
7196 op = op.offsetParent;
7199 el.position('static');
7205 * Scrolls this element into view within the passed container.
7206 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7207 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7208 * @return {Roo.Element} this
7210 scrollIntoView : function(container, hscroll){
7211 var c = Roo.getDom(container) || document.body;
7214 var o = this.calcOffsetsTo(c),
7217 b = t+el.offsetHeight,
7218 r = l+el.offsetWidth;
7220 var ch = c.clientHeight;
7221 var ct = parseInt(c.scrollTop, 10);
7222 var cl = parseInt(c.scrollLeft, 10);
7224 var cr = cl + c.clientWidth;
7232 if(hscroll !== false){
7236 c.scrollLeft = r-c.clientWidth;
7243 scrollChildIntoView : function(child, hscroll){
7244 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7248 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7249 * the new height may not be available immediately.
7250 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7251 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7252 * @param {Function} onComplete (optional) Function to call when animation completes
7253 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7254 * @return {Roo.Element} this
7256 autoHeight : function(animate, duration, onComplete, easing){
7257 var oldHeight = this.getHeight();
7259 this.setHeight(1); // force clipping
7260 setTimeout(function(){
7261 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7263 this.setHeight(height);
7265 if(typeof onComplete == "function"){
7269 this.setHeight(oldHeight); // restore original height
7270 this.setHeight(height, animate, duration, function(){
7272 if(typeof onComplete == "function") onComplete();
7273 }.createDelegate(this), easing);
7275 }.createDelegate(this), 0);
7280 * Returns true if this element is an ancestor of the passed element
7281 * @param {HTMLElement/String} el The element to check
7282 * @return {Boolean} True if this element is an ancestor of el, else false
7284 contains : function(el){
7285 if(!el){return false;}
7286 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7290 * Checks whether the element is currently visible using both visibility and display properties.
7291 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7292 * @return {Boolean} True if the element is currently visible, else false
7294 isVisible : function(deep) {
7295 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7296 if(deep !== true || !vis){
7299 var p = this.dom.parentNode;
7300 while(p && p.tagName.toLowerCase() != "body"){
7301 if(!Roo.fly(p, '_isVisible').isVisible()){
7310 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7311 * @param {String} selector The CSS selector
7312 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7313 * @return {CompositeElement/CompositeElementLite} The composite element
7315 select : function(selector, unique){
7316 return El.select(selector, unique, this.dom);
7320 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7321 * @param {String} selector The CSS selector
7322 * @return {Array} An array of the matched nodes
7324 query : function(selector, unique){
7325 return Roo.DomQuery.select(selector, this.dom);
7329 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7330 * @param {String} selector The CSS selector
7331 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7332 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7334 child : function(selector, returnDom){
7335 var n = Roo.DomQuery.selectNode(selector, this.dom);
7336 return returnDom ? n : Roo.get(n);
7340 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7341 * @param {String} selector The CSS selector
7342 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7343 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7345 down : function(selector, returnDom){
7346 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7347 return returnDom ? n : Roo.get(n);
7351 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7352 * @param {String} group The group the DD object is member of
7353 * @param {Object} config The DD config object
7354 * @param {Object} overrides An object containing methods to override/implement on the DD object
7355 * @return {Roo.dd.DD} The DD object
7357 initDD : function(group, config, overrides){
7358 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7359 return Roo.apply(dd, overrides);
7363 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7364 * @param {String} group The group the DDProxy object is member of
7365 * @param {Object} config The DDProxy config object
7366 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7367 * @return {Roo.dd.DDProxy} The DDProxy object
7369 initDDProxy : function(group, config, overrides){
7370 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7371 return Roo.apply(dd, overrides);
7375 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7376 * @param {String} group The group the DDTarget object is member of
7377 * @param {Object} config The DDTarget config object
7378 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7379 * @return {Roo.dd.DDTarget} The DDTarget object
7381 initDDTarget : function(group, config, overrides){
7382 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7383 return Roo.apply(dd, overrides);
7387 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7388 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7389 * @param {Boolean} visible Whether the element is visible
7390 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7391 * @return {Roo.Element} this
7393 setVisible : function(visible, animate){
7395 if(this.visibilityMode == El.DISPLAY){
7396 this.setDisplayed(visible);
7399 this.dom.style.visibility = visible ? "visible" : "hidden";
7402 // closure for composites
7404 var visMode = this.visibilityMode;
7406 this.setOpacity(.01);
7407 this.setVisible(true);
7409 this.anim({opacity: { to: (visible?1:0) }},
7410 this.preanim(arguments, 1),
7411 null, .35, 'easeIn', function(){
7413 if(visMode == El.DISPLAY){
7414 dom.style.display = "none";
7416 dom.style.visibility = "hidden";
7418 Roo.get(dom).setOpacity(1);
7426 * Returns true if display is not "none"
7429 isDisplayed : function() {
7430 return this.getStyle("display") != "none";
7434 * Toggles the element's visibility or display, depending on visibility mode.
7435 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7436 * @return {Roo.Element} this
7438 toggle : function(animate){
7439 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7444 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7445 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7446 * @return {Roo.Element} this
7448 setDisplayed : function(value) {
7449 if(typeof value == "boolean"){
7450 value = value ? this.originalDisplay : "none";
7452 this.setStyle("display", value);
7457 * Tries to focus the element. Any exceptions are caught and ignored.
7458 * @return {Roo.Element} this
7460 focus : function() {
7468 * Tries to blur the element. Any exceptions are caught and ignored.
7469 * @return {Roo.Element} this
7479 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7480 * @param {String/Array} className The CSS class to add, or an array of classes
7481 * @return {Roo.Element} this
7483 addClass : function(className){
7484 if(className instanceof Array){
7485 for(var i = 0, len = className.length; i < len; i++) {
7486 this.addClass(className[i]);
7489 if(className && !this.hasClass(className)){
7490 this.dom.className = this.dom.className + " " + className;
7497 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7498 * @param {String/Array} className The CSS class to add, or an array of classes
7499 * @return {Roo.Element} this
7501 radioClass : function(className){
7502 var siblings = this.dom.parentNode.childNodes;
7503 for(var i = 0; i < siblings.length; i++) {
7504 var s = siblings[i];
7505 if(s.nodeType == 1){
7506 Roo.get(s).removeClass(className);
7509 this.addClass(className);
7514 * Removes one or more CSS classes from the element.
7515 * @param {String/Array} className The CSS class to remove, or an array of classes
7516 * @return {Roo.Element} this
7518 removeClass : function(className){
7519 if(!className || !this.dom.className){
7522 if(className instanceof Array){
7523 for(var i = 0, len = className.length; i < len; i++) {
7524 this.removeClass(className[i]);
7527 if(this.hasClass(className)){
7528 var re = this.classReCache[className];
7530 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7531 this.classReCache[className] = re;
7533 this.dom.className =
7534 this.dom.className.replace(re, " ");
7544 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7545 * @param {String} className The CSS class to toggle
7546 * @return {Roo.Element} this
7548 toggleClass : function(className){
7549 if(this.hasClass(className)){
7550 this.removeClass(className);
7552 this.addClass(className);
7558 * Checks if the specified CSS class exists on this element's DOM node.
7559 * @param {String} className The CSS class to check for
7560 * @return {Boolean} True if the class exists, else false
7562 hasClass : function(className){
7563 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7567 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7568 * @param {String} oldClassName The CSS class to replace
7569 * @param {String} newClassName The replacement CSS class
7570 * @return {Roo.Element} this
7572 replaceClass : function(oldClassName, newClassName){
7573 this.removeClass(oldClassName);
7574 this.addClass(newClassName);
7579 * Returns an object with properties matching the styles requested.
7580 * For example, el.getStyles('color', 'font-size', 'width') might return
7581 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7582 * @param {String} style1 A style name
7583 * @param {String} style2 A style name
7584 * @param {String} etc.
7585 * @return {Object} The style object
7587 getStyles : function(){
7588 var a = arguments, len = a.length, r = {};
7589 for(var i = 0; i < len; i++){
7590 r[a[i]] = this.getStyle(a[i]);
7596 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7597 * @param {String} property The style property whose value is returned.
7598 * @return {String} The current value of the style property for this element.
7600 getStyle : function(){
7601 return view && view.getComputedStyle ?
7603 var el = this.dom, v, cs, camel;
7604 if(prop == 'float'){
7607 if(el.style && (v = el.style[prop])){
7610 if(cs = view.getComputedStyle(el, "")){
7611 if(!(camel = propCache[prop])){
7612 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7619 var el = this.dom, v, cs, camel;
7620 if(prop == 'opacity'){
7621 if(typeof el.style.filter == 'string'){
7622 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7624 var fv = parseFloat(m[1]);
7626 return fv ? fv / 100 : 0;
7631 }else if(prop == 'float'){
7632 prop = "styleFloat";
7634 if(!(camel = propCache[prop])){
7635 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7637 if(v = el.style[camel]){
7640 if(cs = el.currentStyle){
7648 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7649 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7650 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7651 * @return {Roo.Element} this
7653 setStyle : function(prop, value){
7654 if(typeof prop == "string"){
7656 if (prop == 'float') {
7657 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7662 if(!(camel = propCache[prop])){
7663 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7666 if(camel == 'opacity') {
7667 this.setOpacity(value);
7669 this.dom.style[camel] = value;
7672 for(var style in prop){
7673 if(typeof prop[style] != "function"){
7674 this.setStyle(style, prop[style]);
7682 * More flexible version of {@link #setStyle} for setting style properties.
7683 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7684 * a function which returns such a specification.
7685 * @return {Roo.Element} this
7687 applyStyles : function(style){
7688 Roo.DomHelper.applyStyles(this.dom, style);
7693 * 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).
7694 * @return {Number} The X position of the element
7697 return D.getX(this.dom);
7701 * 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).
7702 * @return {Number} The Y position of the element
7705 return D.getY(this.dom);
7709 * 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).
7710 * @return {Array} The XY position of the element
7713 return D.getXY(this.dom);
7717 * 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).
7718 * @param {Number} The X position of the element
7719 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7720 * @return {Roo.Element} this
7722 setX : function(x, animate){
7724 D.setX(this.dom, x);
7726 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7732 * 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).
7733 * @param {Number} The Y position of the element
7734 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7735 * @return {Roo.Element} this
7737 setY : function(y, animate){
7739 D.setY(this.dom, y);
7741 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7747 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7748 * @param {String} left The left CSS property value
7749 * @return {Roo.Element} this
7751 setLeft : function(left){
7752 this.setStyle("left", this.addUnits(left));
7757 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7758 * @param {String} top The top CSS property value
7759 * @return {Roo.Element} this
7761 setTop : function(top){
7762 this.setStyle("top", this.addUnits(top));
7767 * Sets the element's CSS right style.
7768 * @param {String} right The right CSS property value
7769 * @return {Roo.Element} this
7771 setRight : function(right){
7772 this.setStyle("right", this.addUnits(right));
7777 * Sets the element's CSS bottom style.
7778 * @param {String} bottom The bottom CSS property value
7779 * @return {Roo.Element} this
7781 setBottom : function(bottom){
7782 this.setStyle("bottom", this.addUnits(bottom));
7787 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7788 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7789 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7790 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7791 * @return {Roo.Element} this
7793 setXY : function(pos, animate){
7795 D.setXY(this.dom, pos);
7797 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7803 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7804 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7805 * @param {Number} x X value for new position (coordinates are page-based)
7806 * @param {Number} y Y value for new position (coordinates are page-based)
7807 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7808 * @return {Roo.Element} this
7810 setLocation : function(x, y, animate){
7811 this.setXY([x, y], this.preanim(arguments, 2));
7816 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7817 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7818 * @param {Number} x X value for new position (coordinates are page-based)
7819 * @param {Number} y Y value for new position (coordinates are page-based)
7820 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7821 * @return {Roo.Element} this
7823 moveTo : function(x, y, animate){
7824 this.setXY([x, y], this.preanim(arguments, 2));
7829 * Returns the region of the given element.
7830 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7831 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7833 getRegion : function(){
7834 return D.getRegion(this.dom);
7838 * Returns the offset height of the element
7839 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7840 * @return {Number} The element's height
7842 getHeight : function(contentHeight){
7843 var h = this.dom.offsetHeight || 0;
7844 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7848 * Returns the offset width of the element
7849 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7850 * @return {Number} The element's width
7852 getWidth : function(contentWidth){
7853 var w = this.dom.offsetWidth || 0;
7854 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7858 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7859 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7860 * if a height has not been set using CSS.
7863 getComputedHeight : function(){
7864 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7866 h = parseInt(this.getStyle('height'), 10) || 0;
7867 if(!this.isBorderBox()){
7868 h += this.getFrameWidth('tb');
7875 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7876 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7877 * if a width has not been set using CSS.
7880 getComputedWidth : function(){
7881 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7883 w = parseInt(this.getStyle('width'), 10) || 0;
7884 if(!this.isBorderBox()){
7885 w += this.getFrameWidth('lr');
7892 * Returns the size of the element.
7893 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7894 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7896 getSize : function(contentSize){
7897 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7901 * Returns the width and height of the viewport.
7902 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7904 getViewSize : function(){
7905 var d = this.dom, doc = document, aw = 0, ah = 0;
7906 if(d == doc || d == doc.body){
7907 return {width : D.getViewWidth(), height: D.getViewHeight()};
7910 width : d.clientWidth,
7911 height: d.clientHeight
7917 * Returns the value of the "value" attribute
7918 * @param {Boolean} asNumber true to parse the value as a number
7919 * @return {String/Number}
7921 getValue : function(asNumber){
7922 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7926 adjustWidth : function(width){
7927 if(typeof width == "number"){
7928 if(this.autoBoxAdjust && !this.isBorderBox()){
7929 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7939 adjustHeight : function(height){
7940 if(typeof height == "number"){
7941 if(this.autoBoxAdjust && !this.isBorderBox()){
7942 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7952 * Set the width of the element
7953 * @param {Number} width The new width
7954 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7955 * @return {Roo.Element} this
7957 setWidth : function(width, animate){
7958 width = this.adjustWidth(width);
7960 this.dom.style.width = this.addUnits(width);
7962 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7968 * Set the height of the element
7969 * @param {Number} height The new height
7970 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7971 * @return {Roo.Element} this
7973 setHeight : function(height, animate){
7974 height = this.adjustHeight(height);
7976 this.dom.style.height = this.addUnits(height);
7978 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7984 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7985 * @param {Number} width The new width
7986 * @param {Number} height The new height
7987 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7988 * @return {Roo.Element} this
7990 setSize : function(width, height, animate){
7991 if(typeof width == "object"){ // in case of object from getSize()
7992 height = width.height; width = width.width;
7994 width = this.adjustWidth(width); height = this.adjustHeight(height);
7996 this.dom.style.width = this.addUnits(width);
7997 this.dom.style.height = this.addUnits(height);
7999 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8005 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8006 * @param {Number} x X value for new position (coordinates are page-based)
8007 * @param {Number} y Y value for new position (coordinates are page-based)
8008 * @param {Number} width The new width
8009 * @param {Number} height The new height
8010 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8011 * @return {Roo.Element} this
8013 setBounds : function(x, y, width, height, animate){
8015 this.setSize(width, height);
8016 this.setLocation(x, y);
8018 width = this.adjustWidth(width); height = this.adjustHeight(height);
8019 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8020 this.preanim(arguments, 4), 'motion');
8026 * 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.
8027 * @param {Roo.lib.Region} region The region to fill
8028 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8029 * @return {Roo.Element} this
8031 setRegion : function(region, animate){
8032 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8037 * Appends an event handler
8039 * @param {String} eventName The type of event to append
8040 * @param {Function} fn The method the event invokes
8041 * @param {Object} scope (optional) The scope (this object) of the fn
8042 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8044 addListener : function(eventName, fn, scope, options){
8046 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8051 * Removes an event handler from this element
8052 * @param {String} eventName the type of event to remove
8053 * @param {Function} fn the method the event invokes
8054 * @return {Roo.Element} this
8056 removeListener : function(eventName, fn){
8057 Roo.EventManager.removeListener(this.dom, eventName, fn);
8062 * Removes all previous added listeners from this element
8063 * @return {Roo.Element} this
8065 removeAllListeners : function(){
8066 E.purgeElement(this.dom);
8070 relayEvent : function(eventName, observable){
8071 this.on(eventName, function(e){
8072 observable.fireEvent(eventName, e);
8077 * Set the opacity of the element
8078 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8079 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8080 * @return {Roo.Element} this
8082 setOpacity : function(opacity, animate){
8084 var s = this.dom.style;
8087 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8088 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8090 s.opacity = opacity;
8093 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8099 * Gets the left X coordinate
8100 * @param {Boolean} local True to get the local css position instead of page coordinate
8103 getLeft : function(local){
8107 return parseInt(this.getStyle("left"), 10) || 0;
8112 * Gets the right X coordinate of the element (element X position + element width)
8113 * @param {Boolean} local True to get the local css position instead of page coordinate
8116 getRight : function(local){
8118 return this.getX() + this.getWidth();
8120 return (this.getLeft(true) + this.getWidth()) || 0;
8125 * Gets the top Y coordinate
8126 * @param {Boolean} local True to get the local css position instead of page coordinate
8129 getTop : function(local) {
8133 return parseInt(this.getStyle("top"), 10) || 0;
8138 * Gets the bottom Y coordinate of the element (element Y position + element height)
8139 * @param {Boolean} local True to get the local css position instead of page coordinate
8142 getBottom : function(local){
8144 return this.getY() + this.getHeight();
8146 return (this.getTop(true) + this.getHeight()) || 0;
8151 * Initializes positioning on this element. If a desired position is not passed, it will make the
8152 * the element positioned relative IF it is not already positioned.
8153 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8154 * @param {Number} zIndex (optional) The zIndex to apply
8155 * @param {Number} x (optional) Set the page X position
8156 * @param {Number} y (optional) Set the page Y position
8158 position : function(pos, zIndex, x, y){
8160 if(this.getStyle('position') == 'static'){
8161 this.setStyle('position', 'relative');
8164 this.setStyle("position", pos);
8167 this.setStyle("z-index", zIndex);
8169 if(x !== undefined && y !== undefined){
8171 }else if(x !== undefined){
8173 }else if(y !== undefined){
8179 * Clear positioning back to the default when the document was loaded
8180 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8181 * @return {Roo.Element} this
8183 clearPositioning : function(value){
8191 "position" : "static"
8197 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8198 * snapshot before performing an update and then restoring the element.
8201 getPositioning : function(){
8202 var l = this.getStyle("left");
8203 var t = this.getStyle("top");
8205 "position" : this.getStyle("position"),
8207 "right" : l ? "" : this.getStyle("right"),
8209 "bottom" : t ? "" : this.getStyle("bottom"),
8210 "z-index" : this.getStyle("z-index")
8215 * Gets the width of the border(s) for the specified side(s)
8216 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8217 * passing lr would get the border (l)eft width + the border (r)ight width.
8218 * @return {Number} The width of the sides passed added together
8220 getBorderWidth : function(side){
8221 return this.addStyles(side, El.borders);
8225 * Gets the width of the padding(s) for the specified side(s)
8226 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8227 * passing lr would get the padding (l)eft + the padding (r)ight.
8228 * @return {Number} The padding of the sides passed added together
8230 getPadding : function(side){
8231 return this.addStyles(side, El.paddings);
8235 * Set positioning with an object returned by getPositioning().
8236 * @param {Object} posCfg
8237 * @return {Roo.Element} this
8239 setPositioning : function(pc){
8240 this.applyStyles(pc);
8241 if(pc.right == "auto"){
8242 this.dom.style.right = "";
8244 if(pc.bottom == "auto"){
8245 this.dom.style.bottom = "";
8251 fixDisplay : function(){
8252 if(this.getStyle("display") == "none"){
8253 this.setStyle("visibility", "hidden");
8254 this.setStyle("display", this.originalDisplay); // first try reverting to default
8255 if(this.getStyle("display") == "none"){ // if that fails, default to block
8256 this.setStyle("display", "block");
8262 * Quick set left and top adding default units
8263 * @param {String} left The left CSS property value
8264 * @param {String} top The top CSS property value
8265 * @return {Roo.Element} this
8267 setLeftTop : function(left, top){
8268 this.dom.style.left = this.addUnits(left);
8269 this.dom.style.top = this.addUnits(top);
8274 * Move this element relative to its current position.
8275 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8276 * @param {Number} distance How far to move the element in pixels
8277 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8278 * @return {Roo.Element} this
8280 move : function(direction, distance, animate){
8281 var xy = this.getXY();
8282 direction = direction.toLowerCase();
8286 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8290 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8295 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8300 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8307 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8308 * @return {Roo.Element} this
8311 if(!this.isClipped){
8312 this.isClipped = true;
8313 this.originalClip = {
8314 "o": this.getStyle("overflow"),
8315 "x": this.getStyle("overflow-x"),
8316 "y": this.getStyle("overflow-y")
8318 this.setStyle("overflow", "hidden");
8319 this.setStyle("overflow-x", "hidden");
8320 this.setStyle("overflow-y", "hidden");
8326 * Return clipping (overflow) to original clipping before clip() was called
8327 * @return {Roo.Element} this
8329 unclip : function(){
8331 this.isClipped = false;
8332 var o = this.originalClip;
8333 if(o.o){this.setStyle("overflow", o.o);}
8334 if(o.x){this.setStyle("overflow-x", o.x);}
8335 if(o.y){this.setStyle("overflow-y", o.y);}
8342 * Gets the x,y coordinates specified by the anchor position on the element.
8343 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8344 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8345 * {width: (target width), height: (target height)} (defaults to the element's current size)
8346 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8347 * @return {Array} [x, y] An array containing the element's x and y coordinates
8349 getAnchorXY : function(anchor, local, s){
8350 //Passing a different size is useful for pre-calculating anchors,
8351 //especially for anchored animations that change the el size.
8353 var w, h, vp = false;
8356 if(d == document.body || d == document){
8358 w = D.getViewWidth(); h = D.getViewHeight();
8360 w = this.getWidth(); h = this.getHeight();
8363 w = s.width; h = s.height;
8365 var x = 0, y = 0, r = Math.round;
8366 switch((anchor || "tl").toLowerCase()){
8408 var sc = this.getScroll();
8409 return [x + sc.left, y + sc.top];
8411 //Add the element's offset xy
8412 var o = this.getXY();
8413 return [x+o[0], y+o[1]];
8417 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8418 * supported position values.
8419 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8420 * @param {String} position The position to align to.
8421 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8422 * @return {Array} [x, y]
8424 getAlignToXY : function(el, p, o){
8428 throw "Element.alignTo with an element that doesn't exist";
8430 var c = false; //constrain to viewport
8431 var p1 = "", p2 = "";
8438 }else if(p.indexOf("-") == -1){
8441 p = p.toLowerCase();
8442 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8444 throw "Element.alignTo with an invalid alignment " + p;
8446 p1 = m[1]; p2 = m[2]; c = !!m[3];
8448 //Subtract the aligned el's internal xy from the target's offset xy
8449 //plus custom offset to get the aligned el's new offset xy
8450 var a1 = this.getAnchorXY(p1, true);
8451 var a2 = el.getAnchorXY(p2, false);
8452 var x = a2[0] - a1[0] + o[0];
8453 var y = a2[1] - a1[1] + o[1];
8455 //constrain the aligned el to viewport if necessary
8456 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8457 // 5px of margin for ie
8458 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8460 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8461 //perpendicular to the vp border, allow the aligned el to slide on that border,
8462 //otherwise swap the aligned el to the opposite border of the target.
8463 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8464 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8465 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8466 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8469 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8470 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8472 if((x+w) > dw + scrollX){
8473 x = swapX ? r.left-w : dw+scrollX-w;
8476 x = swapX ? r.right : scrollX;
8478 if((y+h) > dh + scrollY){
8479 y = swapY ? r.top-h : dh+scrollY-h;
8482 y = swapY ? r.bottom : scrollY;
8489 getConstrainToXY : function(){
8490 var os = {top:0, left:0, bottom:0, right: 0};
8492 return function(el, local, offsets, proposedXY){
8494 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8496 var vw, vh, vx = 0, vy = 0;
8497 if(el.dom == document.body || el.dom == document){
8498 vw = Roo.lib.Dom.getViewWidth();
8499 vh = Roo.lib.Dom.getViewHeight();
8501 vw = el.dom.clientWidth;
8502 vh = el.dom.clientHeight;
8504 var vxy = el.getXY();
8510 var s = el.getScroll();
8512 vx += offsets.left + s.left;
8513 vy += offsets.top + s.top;
8515 vw -= offsets.right;
8516 vh -= offsets.bottom;
8521 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8522 var x = xy[0], y = xy[1];
8523 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8525 // only move it if it needs it
8528 // first validate right/bottom
8537 // then make sure top/left isn't negative
8546 return moved ? [x, y] : false;
8551 adjustForConstraints : function(xy, parent, offsets){
8552 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8556 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8557 * document it aligns it to the viewport.
8558 * The position parameter is optional, and can be specified in any one of the following formats:
8560 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8561 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8562 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8563 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8564 * <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
8565 * element's anchor point, and the second value is used as the target's anchor point.</li>
8567 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8568 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8569 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8570 * that specified in order to enforce the viewport constraints.
8571 * Following are all of the supported anchor positions:
8574 ----- -----------------------------
8575 tl The top left corner (default)
8576 t The center of the top edge
8577 tr The top right corner
8578 l The center of the left edge
8579 c In the center of the element
8580 r The center of the right edge
8581 bl The bottom left corner
8582 b The center of the bottom edge
8583 br The bottom right corner
8587 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8588 el.alignTo("other-el");
8590 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8591 el.alignTo("other-el", "tr?");
8593 // align the bottom right corner of el with the center left edge of other-el
8594 el.alignTo("other-el", "br-l?");
8596 // align the center of el with the bottom left corner of other-el and
8597 // adjust the x position by -6 pixels (and the y position by 0)
8598 el.alignTo("other-el", "c-bl", [-6, 0]);
8600 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8601 * @param {String} position The position to align to.
8602 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8603 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8604 * @return {Roo.Element} this
8606 alignTo : function(element, position, offsets, animate){
8607 var xy = this.getAlignToXY(element, position, offsets);
8608 this.setXY(xy, this.preanim(arguments, 3));
8613 * Anchors an element to another element and realigns it when the window is resized.
8614 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8615 * @param {String} position The position to align to.
8616 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8617 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8618 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8619 * is a number, it is used as the buffer delay (defaults to 50ms).
8620 * @param {Function} callback The function to call after the animation finishes
8621 * @return {Roo.Element} this
8623 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8624 var action = function(){
8625 this.alignTo(el, alignment, offsets, animate);
8626 Roo.callback(callback, this);
8628 Roo.EventManager.onWindowResize(action, this);
8629 var tm = typeof monitorScroll;
8630 if(tm != 'undefined'){
8631 Roo.EventManager.on(window, 'scroll', action, this,
8632 {buffer: tm == 'number' ? monitorScroll : 50});
8634 action.call(this); // align immediately
8638 * Clears any opacity settings from this element. Required in some cases for IE.
8639 * @return {Roo.Element} this
8641 clearOpacity : function(){
8642 if (window.ActiveXObject) {
8643 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8644 this.dom.style.filter = "";
8647 this.dom.style.opacity = "";
8648 this.dom.style["-moz-opacity"] = "";
8649 this.dom.style["-khtml-opacity"] = "";
8655 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8656 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8657 * @return {Roo.Element} this
8659 hide : function(animate){
8660 this.setVisible(false, this.preanim(arguments, 0));
8665 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8666 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8667 * @return {Roo.Element} this
8669 show : function(animate){
8670 this.setVisible(true, this.preanim(arguments, 0));
8675 * @private Test if size has a unit, otherwise appends the default
8677 addUnits : function(size){
8678 return Roo.Element.addUnits(size, this.defaultUnit);
8682 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8683 * @return {Roo.Element} this
8685 beginMeasure : function(){
8687 if(el.offsetWidth || el.offsetHeight){
8688 return this; // offsets work already
8691 var p = this.dom, b = document.body; // start with this element
8692 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8693 var pe = Roo.get(p);
8694 if(pe.getStyle('display') == 'none'){
8695 changed.push({el: p, visibility: pe.getStyle("visibility")});
8696 p.style.visibility = "hidden";
8697 p.style.display = "block";
8701 this._measureChanged = changed;
8707 * Restores displays to before beginMeasure was called
8708 * @return {Roo.Element} this
8710 endMeasure : function(){
8711 var changed = this._measureChanged;
8713 for(var i = 0, len = changed.length; i < len; i++) {
8715 r.el.style.visibility = r.visibility;
8716 r.el.style.display = "none";
8718 this._measureChanged = null;
8724 * Update the innerHTML of this element, optionally searching for and processing scripts
8725 * @param {String} html The new HTML
8726 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8727 * @param {Function} callback For async script loading you can be noticed when the update completes
8728 * @return {Roo.Element} this
8730 update : function(html, loadScripts, callback){
8731 if(typeof html == "undefined"){
8734 if(loadScripts !== true){
8735 this.dom.innerHTML = html;
8736 if(typeof callback == "function"){
8744 html += '<span id="' + id + '"></span>';
8746 E.onAvailable(id, function(){
8747 var hd = document.getElementsByTagName("head")[0];
8748 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8749 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8750 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8753 while(match = re.exec(html)){
8754 var attrs = match[1];
8755 var srcMatch = attrs ? attrs.match(srcRe) : false;
8756 if(srcMatch && srcMatch[2]){
8757 var s = document.createElement("script");
8758 s.src = srcMatch[2];
8759 var typeMatch = attrs.match(typeRe);
8760 if(typeMatch && typeMatch[2]){
8761 s.type = typeMatch[2];
8764 }else if(match[2] && match[2].length > 0){
8765 if(window.execScript) {
8766 window.execScript(match[2]);
8774 window.eval(match[2]);
8778 var el = document.getElementById(id);
8779 if(el){el.parentNode.removeChild(el);}
8780 if(typeof callback == "function"){
8784 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8789 * Direct access to the UpdateManager update() method (takes the same parameters).
8790 * @param {String/Function} url The url for this request or a function to call to get the url
8791 * @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}
8792 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8793 * @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.
8794 * @return {Roo.Element} this
8797 var um = this.getUpdateManager();
8798 um.update.apply(um, arguments);
8803 * Gets this element's UpdateManager
8804 * @return {Roo.UpdateManager} The UpdateManager
8806 getUpdateManager : function(){
8807 if(!this.updateManager){
8808 this.updateManager = new Roo.UpdateManager(this);
8810 return this.updateManager;
8814 * Disables text selection for this element (normalized across browsers)
8815 * @return {Roo.Element} this
8817 unselectable : function(){
8818 this.dom.unselectable = "on";
8819 this.swallowEvent("selectstart", true);
8820 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8821 this.addClass("x-unselectable");
8826 * Calculates the x, y to center this element on the screen
8827 * @return {Array} The x, y values [x, y]
8829 getCenterXY : function(){
8830 return this.getAlignToXY(document, 'c-c');
8834 * Centers the Element in either the viewport, or another Element.
8835 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8837 center : function(centerIn){
8838 this.alignTo(centerIn || document, 'c-c');
8843 * Tests various css rules/browsers to determine if this element uses a border box
8846 isBorderBox : function(){
8847 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8851 * Return a box {x, y, width, height} that can be used to set another elements
8852 * size/location to match this element.
8853 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8854 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8855 * @return {Object} box An object in the format {x, y, width, height}
8857 getBox : function(contentBox, local){
8862 var left = parseInt(this.getStyle("left"), 10) || 0;
8863 var top = parseInt(this.getStyle("top"), 10) || 0;
8866 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8868 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8870 var l = this.getBorderWidth("l")+this.getPadding("l");
8871 var r = this.getBorderWidth("r")+this.getPadding("r");
8872 var t = this.getBorderWidth("t")+this.getPadding("t");
8873 var b = this.getBorderWidth("b")+this.getPadding("b");
8874 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)};
8876 bx.right = bx.x + bx.width;
8877 bx.bottom = bx.y + bx.height;
8882 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8883 for more information about the sides.
8884 * @param {String} sides
8887 getFrameWidth : function(sides, onlyContentBox){
8888 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8892 * 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.
8893 * @param {Object} box The box to fill {x, y, width, height}
8894 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8895 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8896 * @return {Roo.Element} this
8898 setBox : function(box, adjust, animate){
8899 var w = box.width, h = box.height;
8900 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8901 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8902 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8904 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8909 * Forces the browser to repaint this element
8910 * @return {Roo.Element} this
8912 repaint : function(){
8914 this.addClass("x-repaint");
8915 setTimeout(function(){
8916 Roo.get(dom).removeClass("x-repaint");
8922 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8923 * then it returns the calculated width of the sides (see getPadding)
8924 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8925 * @return {Object/Number}
8927 getMargins : function(side){
8930 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8931 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8932 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8933 right: parseInt(this.getStyle("margin-right"), 10) || 0
8936 return this.addStyles(side, El.margins);
8941 addStyles : function(sides, styles){
8943 for(var i = 0, len = sides.length; i < len; i++){
8944 v = this.getStyle(styles[sides.charAt(i)]);
8946 w = parseInt(v, 10);
8954 * Creates a proxy element of this element
8955 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8956 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8957 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8958 * @return {Roo.Element} The new proxy element
8960 createProxy : function(config, renderTo, matchBox){
8962 renderTo = Roo.getDom(renderTo);
8964 renderTo = document.body;
8966 config = typeof config == "object" ?
8967 config : {tag : "div", cls: config};
8968 var proxy = Roo.DomHelper.append(renderTo, config, true);
8970 proxy.setBox(this.getBox());
8976 * Puts a mask over this element to disable user interaction. Requires core.css.
8977 * This method can only be applied to elements which accept child nodes.
8978 * @param {String} msg (optional) A message to display in the mask
8979 * @param {String} msgCls (optional) A css class to apply to the msg element
8980 * @return {Element} The mask element
8982 mask : function(msg, msgCls)
8984 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
8985 this.setStyle("position", "relative");
8988 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8990 this.addClass("x-masked");
8991 this._mask.setDisplayed(true);
8996 while (dom && dom.style) {
8997 if (!isNaN(parseInt(dom.style.zIndex))) {
8998 z = Math.max(z, parseInt(dom.style.zIndex));
9000 dom = dom.parentNode;
9002 // if we are masking the body - then it hides everything..
9003 if (this.dom == document.body) {
9005 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9006 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9009 if(typeof msg == 'string'){
9011 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9013 var mm = this._maskMsg;
9014 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9015 if (mm.dom.firstChild) { // weird IE issue?
9016 mm.dom.firstChild.innerHTML = msg;
9018 mm.setDisplayed(true);
9020 mm.setStyle('z-index', z + 102);
9022 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9023 this._mask.setHeight(this.getHeight());
9025 this._mask.setStyle('z-index', z + 100);
9031 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9032 * it is cached for reuse.
9034 unmask : function(removeEl){
9036 if(removeEl === true){
9037 this._mask.remove();
9040 this._maskMsg.remove();
9041 delete this._maskMsg;
9044 this._mask.setDisplayed(false);
9046 this._maskMsg.setDisplayed(false);
9050 this.removeClass("x-masked");
9054 * Returns true if this element is masked
9057 isMasked : function(){
9058 return this._mask && this._mask.isVisible();
9062 * Creates an iframe shim for this element to keep selects and other windowed objects from
9064 * @return {Roo.Element} The new shim element
9066 createShim : function(){
9067 var el = document.createElement('iframe');
9068 el.frameBorder = 'no';
9069 el.className = 'roo-shim';
9070 if(Roo.isIE && Roo.isSecure){
9071 el.src = Roo.SSL_SECURE_URL;
9073 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9074 shim.autoBoxAdjust = false;
9079 * Removes this element from the DOM and deletes it from the cache
9081 remove : function(){
9082 if(this.dom.parentNode){
9083 this.dom.parentNode.removeChild(this.dom);
9085 delete El.cache[this.dom.id];
9089 * Sets up event handlers to add and remove a css class when the mouse is over this element
9090 * @param {String} className
9091 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9092 * mouseout events for children elements
9093 * @return {Roo.Element} this
9095 addClassOnOver : function(className, preventFlicker){
9096 this.on("mouseover", function(){
9097 Roo.fly(this, '_internal').addClass(className);
9099 var removeFn = function(e){
9100 if(preventFlicker !== true || !e.within(this, true)){
9101 Roo.fly(this, '_internal').removeClass(className);
9104 this.on("mouseout", removeFn, this.dom);
9109 * Sets up event handlers to add and remove a css class when this element has the focus
9110 * @param {String} className
9111 * @return {Roo.Element} this
9113 addClassOnFocus : function(className){
9114 this.on("focus", function(){
9115 Roo.fly(this, '_internal').addClass(className);
9117 this.on("blur", function(){
9118 Roo.fly(this, '_internal').removeClass(className);
9123 * 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)
9124 * @param {String} className
9125 * @return {Roo.Element} this
9127 addClassOnClick : function(className){
9129 this.on("mousedown", function(){
9130 Roo.fly(dom, '_internal').addClass(className);
9131 var d = Roo.get(document);
9132 var fn = function(){
9133 Roo.fly(dom, '_internal').removeClass(className);
9134 d.removeListener("mouseup", fn);
9136 d.on("mouseup", fn);
9142 * Stops the specified event from bubbling and optionally prevents the default action
9143 * @param {String} eventName
9144 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9145 * @return {Roo.Element} this
9147 swallowEvent : function(eventName, preventDefault){
9148 var fn = function(e){
9149 e.stopPropagation();
9154 if(eventName instanceof Array){
9155 for(var i = 0, len = eventName.length; i < len; i++){
9156 this.on(eventName[i], fn);
9160 this.on(eventName, fn);
9167 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9170 * Sizes this element to its parent element's dimensions performing
9171 * neccessary box adjustments.
9172 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9173 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9174 * @return {Roo.Element} this
9176 fitToParent : function(monitorResize, targetParent) {
9177 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9178 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9179 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9182 var p = Roo.get(targetParent || this.dom.parentNode);
9183 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9184 if (monitorResize === true) {
9185 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9186 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9192 * Gets the next sibling, skipping text nodes
9193 * @return {HTMLElement} The next sibling or null
9195 getNextSibling : function(){
9196 var n = this.dom.nextSibling;
9197 while(n && n.nodeType != 1){
9204 * Gets the previous sibling, skipping text nodes
9205 * @return {HTMLElement} The previous sibling or null
9207 getPrevSibling : function(){
9208 var n = this.dom.previousSibling;
9209 while(n && n.nodeType != 1){
9210 n = n.previousSibling;
9217 * Appends the passed element(s) to this element
9218 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9219 * @return {Roo.Element} this
9221 appendChild: function(el){
9228 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9229 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9230 * automatically generated with the specified attributes.
9231 * @param {HTMLElement} insertBefore (optional) a child element of this element
9232 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9233 * @return {Roo.Element} The new child element
9235 createChild: function(config, insertBefore, returnDom){
9236 config = config || {tag:'div'};
9238 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9240 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9244 * Appends this element to the passed element
9245 * @param {String/HTMLElement/Element} el The new parent element
9246 * @return {Roo.Element} this
9248 appendTo: function(el){
9249 el = Roo.getDom(el);
9250 el.appendChild(this.dom);
9255 * Inserts this element before the passed element in the DOM
9256 * @param {String/HTMLElement/Element} el The element to insert before
9257 * @return {Roo.Element} this
9259 insertBefore: function(el){
9260 el = Roo.getDom(el);
9261 el.parentNode.insertBefore(this.dom, el);
9266 * Inserts this element after the passed element in the DOM
9267 * @param {String/HTMLElement/Element} el The element to insert after
9268 * @return {Roo.Element} this
9270 insertAfter: function(el){
9271 el = Roo.getDom(el);
9272 el.parentNode.insertBefore(this.dom, el.nextSibling);
9277 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9278 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9279 * @return {Roo.Element} The new child
9281 insertFirst: function(el, returnDom){
9283 if(typeof el == 'object' && !el.nodeType){ // dh config
9284 return this.createChild(el, this.dom.firstChild, returnDom);
9286 el = Roo.getDom(el);
9287 this.dom.insertBefore(el, this.dom.firstChild);
9288 return !returnDom ? Roo.get(el) : el;
9293 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9294 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9295 * @param {String} where (optional) 'before' or 'after' defaults to before
9296 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9297 * @return {Roo.Element} the inserted Element
9299 insertSibling: function(el, where, returnDom){
9300 where = where ? where.toLowerCase() : 'before';
9302 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9304 if(typeof el == 'object' && !el.nodeType){ // dh config
9305 if(where == 'after' && !this.dom.nextSibling){
9306 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9308 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9312 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9313 where == 'before' ? this.dom : this.dom.nextSibling);
9322 * Creates and wraps this element with another element
9323 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9324 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9325 * @return {HTMLElement/Element} The newly created wrapper element
9327 wrap: function(config, returnDom){
9329 config = {tag: "div"};
9331 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9332 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9337 * Replaces the passed element with this element
9338 * @param {String/HTMLElement/Element} el The element to replace
9339 * @return {Roo.Element} this
9341 replace: function(el){
9343 this.insertBefore(el);
9349 * Inserts an html fragment into this element
9350 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9351 * @param {String} html The HTML fragment
9352 * @param {Boolean} returnEl True to return an Roo.Element
9353 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9355 insertHtml : function(where, html, returnEl){
9356 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9357 return returnEl ? Roo.get(el) : el;
9361 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9362 * @param {Object} o The object with the attributes
9363 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9364 * @return {Roo.Element} this
9366 set : function(o, useSet){
9368 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9370 if(attr == "style" || typeof o[attr] == "function") continue;
9372 el.className = o["cls"];
9374 if(useSet) el.setAttribute(attr, o[attr]);
9375 else el[attr] = o[attr];
9379 Roo.DomHelper.applyStyles(el, o.style);
9385 * Convenience method for constructing a KeyMap
9386 * @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:
9387 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9388 * @param {Function} fn The function to call
9389 * @param {Object} scope (optional) The scope of the function
9390 * @return {Roo.KeyMap} The KeyMap created
9392 addKeyListener : function(key, fn, scope){
9394 if(typeof key != "object" || key instanceof Array){
9410 return new Roo.KeyMap(this, config);
9414 * Creates a KeyMap for this element
9415 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9416 * @return {Roo.KeyMap} The KeyMap created
9418 addKeyMap : function(config){
9419 return new Roo.KeyMap(this, config);
9423 * Returns true if this element is scrollable.
9426 isScrollable : function(){
9428 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9432 * 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().
9433 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9434 * @param {Number} value The new scroll value
9435 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9436 * @return {Element} this
9439 scrollTo : function(side, value, animate){
9440 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9442 this.dom[prop] = value;
9444 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9445 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9451 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9452 * within this element's scrollable range.
9453 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9454 * @param {Number} distance How far to scroll the element in pixels
9455 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9456 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9457 * was scrolled as far as it could go.
9459 scroll : function(direction, distance, animate){
9460 if(!this.isScrollable()){
9464 var l = el.scrollLeft, t = el.scrollTop;
9465 var w = el.scrollWidth, h = el.scrollHeight;
9466 var cw = el.clientWidth, ch = el.clientHeight;
9467 direction = direction.toLowerCase();
9468 var scrolled = false;
9469 var a = this.preanim(arguments, 2);
9474 var v = Math.min(l + distance, w-cw);
9475 this.scrollTo("left", v, a);
9482 var v = Math.max(l - distance, 0);
9483 this.scrollTo("left", v, a);
9491 var v = Math.max(t - distance, 0);
9492 this.scrollTo("top", v, a);
9500 var v = Math.min(t + distance, h-ch);
9501 this.scrollTo("top", v, a);
9510 * Translates the passed page coordinates into left/top css values for this element
9511 * @param {Number/Array} x The page x or an array containing [x, y]
9512 * @param {Number} y The page y
9513 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9515 translatePoints : function(x, y){
9516 if(typeof x == 'object' || x instanceof Array){
9519 var p = this.getStyle('position');
9520 var o = this.getXY();
9522 var l = parseInt(this.getStyle('left'), 10);
9523 var t = parseInt(this.getStyle('top'), 10);
9526 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9529 t = (p == "relative") ? 0 : this.dom.offsetTop;
9532 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9536 * Returns the current scroll position of the element.
9537 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9539 getScroll : function(){
9540 var d = this.dom, doc = document;
9541 if(d == doc || d == doc.body){
9542 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9543 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9544 return {left: l, top: t};
9546 return {left: d.scrollLeft, top: d.scrollTop};
9551 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9552 * are convert to standard 6 digit hex color.
9553 * @param {String} attr The css attribute
9554 * @param {String} defaultValue The default value to use when a valid color isn't found
9555 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9558 getColor : function(attr, defaultValue, prefix){
9559 var v = this.getStyle(attr);
9560 if(!v || v == "transparent" || v == "inherit") {
9561 return defaultValue;
9563 var color = typeof prefix == "undefined" ? "#" : prefix;
9564 if(v.substr(0, 4) == "rgb("){
9565 var rvs = v.slice(4, v.length -1).split(",");
9566 for(var i = 0; i < 3; i++){
9567 var h = parseInt(rvs[i]).toString(16);
9574 if(v.substr(0, 1) == "#"){
9576 for(var i = 1; i < 4; i++){
9577 var c = v.charAt(i);
9580 }else if(v.length == 7){
9581 color += v.substr(1);
9585 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9589 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9590 * gradient background, rounded corners and a 4-way shadow.
9591 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9592 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9593 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9594 * @return {Roo.Element} this
9596 boxWrap : function(cls){
9597 cls = cls || 'x-box';
9598 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9599 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9604 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9605 * @param {String} namespace The namespace in which to look for the attribute
9606 * @param {String} name The attribute name
9607 * @return {String} The attribute value
9609 getAttributeNS : Roo.isIE ? function(ns, name){
9611 var type = typeof d[ns+":"+name];
9612 if(type != 'undefined' && type != 'unknown'){
9613 return d[ns+":"+name];
9616 } : function(ns, name){
9618 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9623 * Sets or Returns the value the dom attribute value
9624 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9625 * @param {String} value (optional) The value to set the attribute to
9626 * @return {String} The attribute value
9628 attr : function(name){
9629 if (arguments.length > 1) {
9630 this.dom.setAttribute(name, arguments[1]);
9631 return arguments[1];
9633 if (typeof(name) == 'object') {
9634 for(var i in name) {
9635 this.attr(i, name[i]);
9641 if (!this.dom.hasAttribute(name)) {
9644 return this.dom.getAttribute(name);
9651 var ep = El.prototype;
9654 * Appends an event handler (Shorthand for addListener)
9655 * @param {String} eventName The type of event to append
9656 * @param {Function} fn The method the event invokes
9657 * @param {Object} scope (optional) The scope (this object) of the fn
9658 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9661 ep.on = ep.addListener;
9663 ep.mon = ep.addListener;
9666 * Removes an event handler from this element (shorthand for removeListener)
9667 * @param {String} eventName the type of event to remove
9668 * @param {Function} fn the method the event invokes
9669 * @return {Roo.Element} this
9672 ep.un = ep.removeListener;
9675 * true to automatically adjust width and height settings for box-model issues (default to true)
9677 ep.autoBoxAdjust = true;
9680 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9683 El.addUnits = function(v, defaultUnit){
9684 if(v === "" || v == "auto"){
9687 if(v === undefined){
9690 if(typeof v == "number" || !El.unitPattern.test(v)){
9691 return v + (defaultUnit || 'px');
9696 // special markup used throughout Roo when box wrapping elements
9697 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>';
9699 * Visibility mode constant - Use visibility to hide element
9705 * Visibility mode constant - Use display to hide element
9711 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9712 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9713 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9725 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9726 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9727 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9728 * @return {Element} The Element object
9731 El.get = function(el){
9733 if(!el){ return null; }
9734 if(typeof el == "string"){ // element id
9735 if(!(elm = document.getElementById(el))){
9738 if(ex = El.cache[el]){
9741 ex = El.cache[el] = new El(elm);
9744 }else if(el.tagName){ // dom element
9748 if(ex = El.cache[id]){
9751 ex = El.cache[id] = new El(el);
9754 }else if(el instanceof El){
9756 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9757 // catch case where it hasn't been appended
9758 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9761 }else if(el.isComposite){
9763 }else if(el instanceof Array){
9764 return El.select(el);
9765 }else if(el == document){
9766 // create a bogus element object representing the document object
9768 var f = function(){};
9769 f.prototype = El.prototype;
9771 docEl.dom = document;
9779 El.uncache = function(el){
9780 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9782 delete El.cache[a[i].id || a[i]];
9788 // Garbage collection - uncache elements/purge listeners on orphaned elements
9789 // so we don't hold a reference and cause the browser to retain them
9790 El.garbageCollect = function(){
9791 if(!Roo.enableGarbageCollector){
9792 clearInterval(El.collectorThread);
9795 for(var eid in El.cache){
9796 var el = El.cache[eid], d = el.dom;
9797 // -------------------------------------------------------
9798 // Determining what is garbage:
9799 // -------------------------------------------------------
9801 // dom node is null, definitely garbage
9802 // -------------------------------------------------------
9804 // no parentNode == direct orphan, definitely garbage
9805 // -------------------------------------------------------
9806 // !d.offsetParent && !document.getElementById(eid)
9807 // display none elements have no offsetParent so we will
9808 // also try to look it up by it's id. However, check
9809 // offsetParent first so we don't do unneeded lookups.
9810 // This enables collection of elements that are not orphans
9811 // directly, but somewhere up the line they have an orphan
9813 // -------------------------------------------------------
9814 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9815 delete El.cache[eid];
9816 if(d && Roo.enableListenerCollection){
9822 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9826 El.Flyweight = function(dom){
9829 El.Flyweight.prototype = El.prototype;
9831 El._flyweights = {};
9833 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9834 * the dom node can be overwritten by other code.
9835 * @param {String/HTMLElement} el The dom node or id
9836 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9837 * prevent conflicts (e.g. internally Roo uses "_internal")
9839 * @return {Element} The shared Element object
9841 El.fly = function(el, named){
9842 named = named || '_global';
9843 el = Roo.getDom(el);
9847 if(!El._flyweights[named]){
9848 El._flyweights[named] = new El.Flyweight();
9850 El._flyweights[named].dom = el;
9851 return El._flyweights[named];
9855 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9856 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9857 * Shorthand of {@link Roo.Element#get}
9858 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9859 * @return {Element} The Element object
9865 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9866 * the dom node can be overwritten by other code.
9867 * Shorthand of {@link Roo.Element#fly}
9868 * @param {String/HTMLElement} el The dom node or id
9869 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9870 * prevent conflicts (e.g. internally Roo uses "_internal")
9872 * @return {Element} The shared Element object
9878 // speedy lookup for elements never to box adjust
9879 var noBoxAdjust = Roo.isStrict ? {
9882 input:1, select:1, textarea:1
9884 if(Roo.isIE || Roo.isGecko){
9885 noBoxAdjust['button'] = 1;
9889 Roo.EventManager.on(window, 'unload', function(){
9891 delete El._flyweights;
9899 Roo.Element.selectorFunction = Roo.DomQuery.select;
9902 Roo.Element.select = function(selector, unique, root){
9904 if(typeof selector == "string"){
9905 els = Roo.Element.selectorFunction(selector, root);
9906 }else if(selector.length !== undefined){
9909 throw "Invalid selector";
9911 if(unique === true){
9912 return new Roo.CompositeElement(els);
9914 return new Roo.CompositeElementLite(els);
9918 * Selects elements based on the passed CSS selector to enable working on them as 1.
9919 * @param {String/Array} selector The CSS selector or an array of elements
9920 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9921 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9922 * @return {CompositeElementLite/CompositeElement}
9926 Roo.select = Roo.Element.select;
9943 * Ext JS Library 1.1.1
9944 * Copyright(c) 2006-2007, Ext JS, LLC.
9946 * Originally Released Under LGPL - original licence link has changed is not relivant.
9949 * <script type="text/javascript">
9954 //Notifies Element that fx methods are available
9955 Roo.enableFx = true;
9959 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9960 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9961 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9962 * Element effects to work.</p><br/>
9964 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9965 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9966 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9967 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9968 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9969 * expected results and should be done with care.</p><br/>
9971 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9972 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9975 ----- -----------------------------
9976 tl The top left corner
9977 t The center of the top edge
9978 tr The top right corner
9979 l The center of the left edge
9980 r The center of the right edge
9981 bl The bottom left corner
9982 b The center of the bottom edge
9983 br The bottom right corner
9985 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9986 * below are common options that can be passed to any Fx method.</b>
9987 * @cfg {Function} callback A function called when the effect is finished
9988 * @cfg {Object} scope The scope of the effect function
9989 * @cfg {String} easing A valid Easing value for the effect
9990 * @cfg {String} afterCls A css class to apply after the effect
9991 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9992 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9993 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9994 * effects that end with the element being visually hidden, ignored otherwise)
9995 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9996 * a function which returns such a specification that will be applied to the Element after the effect finishes
9997 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9998 * @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
9999 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10003 * Slides the element into view. An anchor point can be optionally passed to set the point of
10004 * origin for the slide effect. This function automatically handles wrapping the element with
10005 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10008 // default: slide the element in from the top
10011 // custom: slide the element in from the right with a 2-second duration
10012 el.slideIn('r', { duration: 2 });
10014 // common config options shown with default values
10020 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10021 * @param {Object} options (optional) Object literal with any of the Fx config options
10022 * @return {Roo.Element} The Element
10024 slideIn : function(anchor, o){
10025 var el = this.getFxEl();
10028 el.queueFx(o, function(){
10030 anchor = anchor || "t";
10032 // fix display to visibility
10035 // restore values after effect
10036 var r = this.getFxRestore();
10037 var b = this.getBox();
10038 // fixed size for slide
10042 var wrap = this.fxWrap(r.pos, o, "hidden");
10044 var st = this.dom.style;
10045 st.visibility = "visible";
10046 st.position = "absolute";
10048 // clear out temp styles after slide and unwrap
10049 var after = function(){
10050 el.fxUnwrap(wrap, r.pos, o);
10051 st.width = r.width;
10052 st.height = r.height;
10055 // time to calc the positions
10056 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10058 switch(anchor.toLowerCase()){
10060 wrap.setSize(b.width, 0);
10061 st.left = st.bottom = "0";
10065 wrap.setSize(0, b.height);
10066 st.right = st.top = "0";
10070 wrap.setSize(0, b.height);
10071 wrap.setX(b.right);
10072 st.left = st.top = "0";
10073 a = {width: bw, points: pt};
10076 wrap.setSize(b.width, 0);
10077 wrap.setY(b.bottom);
10078 st.left = st.top = "0";
10079 a = {height: bh, points: pt};
10082 wrap.setSize(0, 0);
10083 st.right = st.bottom = "0";
10084 a = {width: bw, height: bh};
10087 wrap.setSize(0, 0);
10088 wrap.setY(b.y+b.height);
10089 st.right = st.top = "0";
10090 a = {width: bw, height: bh, points: pt};
10093 wrap.setSize(0, 0);
10094 wrap.setXY([b.right, b.bottom]);
10095 st.left = st.top = "0";
10096 a = {width: bw, height: bh, points: pt};
10099 wrap.setSize(0, 0);
10100 wrap.setX(b.x+b.width);
10101 st.left = st.bottom = "0";
10102 a = {width: bw, height: bh, points: pt};
10105 this.dom.style.visibility = "visible";
10108 arguments.callee.anim = wrap.fxanim(a,
10118 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10119 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10120 * 'hidden') but block elements will still take up space in the document. The element must be removed
10121 * from the DOM using the 'remove' config option if desired. This function automatically handles
10122 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10125 // default: slide the element out to the top
10128 // custom: slide the element out to the right with a 2-second duration
10129 el.slideOut('r', { duration: 2 });
10131 // common config options shown with default values
10139 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10140 * @param {Object} options (optional) Object literal with any of the Fx config options
10141 * @return {Roo.Element} The Element
10143 slideOut : function(anchor, o){
10144 var el = this.getFxEl();
10147 el.queueFx(o, function(){
10149 anchor = anchor || "t";
10151 // restore values after effect
10152 var r = this.getFxRestore();
10154 var b = this.getBox();
10155 // fixed size for slide
10159 var wrap = this.fxWrap(r.pos, o, "visible");
10161 var st = this.dom.style;
10162 st.visibility = "visible";
10163 st.position = "absolute";
10167 var after = function(){
10169 el.setDisplayed(false);
10174 el.fxUnwrap(wrap, r.pos, o);
10176 st.width = r.width;
10177 st.height = r.height;
10182 var a, zero = {to: 0};
10183 switch(anchor.toLowerCase()){
10185 st.left = st.bottom = "0";
10186 a = {height: zero};
10189 st.right = st.top = "0";
10193 st.left = st.top = "0";
10194 a = {width: zero, points: {to:[b.right, b.y]}};
10197 st.left = st.top = "0";
10198 a = {height: zero, points: {to:[b.x, b.bottom]}};
10201 st.right = st.bottom = "0";
10202 a = {width: zero, height: zero};
10205 st.right = st.top = "0";
10206 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10209 st.left = st.top = "0";
10210 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10213 st.left = st.bottom = "0";
10214 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10218 arguments.callee.anim = wrap.fxanim(a,
10228 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10229 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10230 * The element must be removed from the DOM using the 'remove' config option if desired.
10236 // common config options shown with default values
10244 * @param {Object} options (optional) Object literal with any of the Fx config options
10245 * @return {Roo.Element} The Element
10247 puff : function(o){
10248 var el = this.getFxEl();
10251 el.queueFx(o, function(){
10252 this.clearOpacity();
10255 // restore values after effect
10256 var r = this.getFxRestore();
10257 var st = this.dom.style;
10259 var after = function(){
10261 el.setDisplayed(false);
10268 el.setPositioning(r.pos);
10269 st.width = r.width;
10270 st.height = r.height;
10275 var width = this.getWidth();
10276 var height = this.getHeight();
10278 arguments.callee.anim = this.fxanim({
10279 width : {to: this.adjustWidth(width * 2)},
10280 height : {to: this.adjustHeight(height * 2)},
10281 points : {by: [-(width * .5), -(height * .5)]},
10283 fontSize: {to:200, unit: "%"}
10294 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10295 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10296 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10302 // all config options shown with default values
10310 * @param {Object} options (optional) Object literal with any of the Fx config options
10311 * @return {Roo.Element} The Element
10313 switchOff : function(o){
10314 var el = this.getFxEl();
10317 el.queueFx(o, function(){
10318 this.clearOpacity();
10321 // restore values after effect
10322 var r = this.getFxRestore();
10323 var st = this.dom.style;
10325 var after = function(){
10327 el.setDisplayed(false);
10333 el.setPositioning(r.pos);
10334 st.width = r.width;
10335 st.height = r.height;
10340 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10341 this.clearOpacity();
10345 points:{by:[0, this.getHeight() * .5]}
10346 }, o, 'motion', 0.3, 'easeIn', after);
10347 }).defer(100, this);
10354 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10355 * changed using the "attr" config option) and then fading back to the original color. If no original
10356 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10359 // default: highlight background to yellow
10362 // custom: highlight foreground text to blue for 2 seconds
10363 el.highlight("0000ff", { attr: 'color', duration: 2 });
10365 // common config options shown with default values
10366 el.highlight("ffff9c", {
10367 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10368 endColor: (current color) or "ffffff",
10373 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10374 * @param {Object} options (optional) Object literal with any of the Fx config options
10375 * @return {Roo.Element} The Element
10377 highlight : function(color, o){
10378 var el = this.getFxEl();
10381 el.queueFx(o, function(){
10382 color = color || "ffff9c";
10383 attr = o.attr || "backgroundColor";
10385 this.clearOpacity();
10388 var origColor = this.getColor(attr);
10389 var restoreColor = this.dom.style[attr];
10390 endColor = (o.endColor || origColor) || "ffffff";
10392 var after = function(){
10393 el.dom.style[attr] = restoreColor;
10398 a[attr] = {from: color, to: endColor};
10399 arguments.callee.anim = this.fxanim(a,
10409 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10412 // default: a single light blue ripple
10415 // custom: 3 red ripples lasting 3 seconds total
10416 el.frame("ff0000", 3, { duration: 3 });
10418 // common config options shown with default values
10419 el.frame("C3DAF9", 1, {
10420 duration: 1 //duration of entire animation (not each individual ripple)
10421 // Note: Easing is not configurable and will be ignored if included
10424 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10425 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10426 * @param {Object} options (optional) Object literal with any of the Fx config options
10427 * @return {Roo.Element} The Element
10429 frame : function(color, count, o){
10430 var el = this.getFxEl();
10433 el.queueFx(o, function(){
10434 color = color || "#C3DAF9";
10435 if(color.length == 6){
10436 color = "#" + color;
10438 count = count || 1;
10439 duration = o.duration || 1;
10442 var b = this.getBox();
10443 var animFn = function(){
10444 var proxy = this.createProxy({
10447 visbility:"hidden",
10448 position:"absolute",
10449 "z-index":"35000", // yee haw
10450 border:"0px solid " + color
10453 var scale = Roo.isBorderBox ? 2 : 1;
10455 top:{from:b.y, to:b.y - 20},
10456 left:{from:b.x, to:b.x - 20},
10457 borderWidth:{from:0, to:10},
10458 opacity:{from:1, to:0},
10459 height:{from:b.height, to:(b.height + (20*scale))},
10460 width:{from:b.width, to:(b.width + (20*scale))}
10461 }, duration, function(){
10465 animFn.defer((duration/2)*1000, this);
10476 * Creates a pause before any subsequent queued effects begin. If there are
10477 * no effects queued after the pause it will have no effect.
10482 * @param {Number} seconds The length of time to pause (in seconds)
10483 * @return {Roo.Element} The Element
10485 pause : function(seconds){
10486 var el = this.getFxEl();
10489 el.queueFx(o, function(){
10490 setTimeout(function(){
10492 }, seconds * 1000);
10498 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10499 * using the "endOpacity" config option.
10502 // default: fade in from opacity 0 to 100%
10505 // custom: fade in from opacity 0 to 75% over 2 seconds
10506 el.fadeIn({ endOpacity: .75, duration: 2});
10508 // common config options shown with default values
10510 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10515 * @param {Object} options (optional) Object literal with any of the Fx config options
10516 * @return {Roo.Element} The Element
10518 fadeIn : function(o){
10519 var el = this.getFxEl();
10521 el.queueFx(o, function(){
10522 this.setOpacity(0);
10524 this.dom.style.visibility = 'visible';
10525 var to = o.endOpacity || 1;
10526 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10527 o, null, .5, "easeOut", function(){
10529 this.clearOpacity();
10538 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10539 * using the "endOpacity" config option.
10542 // default: fade out from the element's current opacity to 0
10545 // custom: fade out from the element's current opacity to 25% over 2 seconds
10546 el.fadeOut({ endOpacity: .25, duration: 2});
10548 // common config options shown with default values
10550 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10557 * @param {Object} options (optional) Object literal with any of the Fx config options
10558 * @return {Roo.Element} The Element
10560 fadeOut : function(o){
10561 var el = this.getFxEl();
10563 el.queueFx(o, function(){
10564 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10565 o, null, .5, "easeOut", function(){
10566 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10567 this.dom.style.display = "none";
10569 this.dom.style.visibility = "hidden";
10571 this.clearOpacity();
10579 * Animates the transition of an element's dimensions from a starting height/width
10580 * to an ending height/width.
10583 // change height and width to 100x100 pixels
10584 el.scale(100, 100);
10586 // common config options shown with default values. The height and width will default to
10587 // the element's existing values if passed as null.
10590 [element's height], {
10595 * @param {Number} width The new width (pass undefined to keep the original width)
10596 * @param {Number} height The new height (pass undefined to keep the original height)
10597 * @param {Object} options (optional) Object literal with any of the Fx config options
10598 * @return {Roo.Element} The Element
10600 scale : function(w, h, o){
10601 this.shift(Roo.apply({}, o, {
10609 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10610 * Any of these properties not specified in the config object will not be changed. This effect
10611 * requires that at least one new dimension, position or opacity setting must be passed in on
10612 * the config object in order for the function to have any effect.
10615 // slide the element horizontally to x position 200 while changing the height and opacity
10616 el.shift({ x: 200, height: 50, opacity: .8 });
10618 // common config options shown with default values.
10620 width: [element's width],
10621 height: [element's height],
10622 x: [element's x position],
10623 y: [element's y position],
10624 opacity: [element's opacity],
10629 * @param {Object} options Object literal with any of the Fx config options
10630 * @return {Roo.Element} The Element
10632 shift : function(o){
10633 var el = this.getFxEl();
10635 el.queueFx(o, function(){
10636 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10637 if(w !== undefined){
10638 a.width = {to: this.adjustWidth(w)};
10640 if(h !== undefined){
10641 a.height = {to: this.adjustHeight(h)};
10643 if(x !== undefined || y !== undefined){
10645 x !== undefined ? x : this.getX(),
10646 y !== undefined ? y : this.getY()
10649 if(op !== undefined){
10650 a.opacity = {to: op};
10652 if(o.xy !== undefined){
10653 a.points = {to: o.xy};
10655 arguments.callee.anim = this.fxanim(a,
10656 o, 'motion', .35, "easeOut", function(){
10664 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10665 * ending point of the effect.
10668 // default: slide the element downward while fading out
10671 // custom: slide the element out to the right with a 2-second duration
10672 el.ghost('r', { duration: 2 });
10674 // common config options shown with default values
10682 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10683 * @param {Object} options (optional) Object literal with any of the Fx config options
10684 * @return {Roo.Element} The Element
10686 ghost : function(anchor, o){
10687 var el = this.getFxEl();
10690 el.queueFx(o, function(){
10691 anchor = anchor || "b";
10693 // restore values after effect
10694 var r = this.getFxRestore();
10695 var w = this.getWidth(),
10696 h = this.getHeight();
10698 var st = this.dom.style;
10700 var after = function(){
10702 el.setDisplayed(false);
10708 el.setPositioning(r.pos);
10709 st.width = r.width;
10710 st.height = r.height;
10715 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10716 switch(anchor.toLowerCase()){
10743 arguments.callee.anim = this.fxanim(a,
10753 * Ensures that all effects queued after syncFx is called on the element are
10754 * run concurrently. This is the opposite of {@link #sequenceFx}.
10755 * @return {Roo.Element} The Element
10757 syncFx : function(){
10758 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10767 * Ensures that all effects queued after sequenceFx is called on the element are
10768 * run in sequence. This is the opposite of {@link #syncFx}.
10769 * @return {Roo.Element} The Element
10771 sequenceFx : function(){
10772 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10774 concurrent : false,
10781 nextFx : function(){
10782 var ef = this.fxQueue[0];
10789 * Returns true if the element has any effects actively running or queued, else returns false.
10790 * @return {Boolean} True if element has active effects, else false
10792 hasActiveFx : function(){
10793 return this.fxQueue && this.fxQueue[0];
10797 * Stops any running effects and clears the element's internal effects queue if it contains
10798 * any additional effects that haven't started yet.
10799 * @return {Roo.Element} The Element
10801 stopFx : function(){
10802 if(this.hasActiveFx()){
10803 var cur = this.fxQueue[0];
10804 if(cur && cur.anim && cur.anim.isAnimated()){
10805 this.fxQueue = [cur]; // clear out others
10806 cur.anim.stop(true);
10813 beforeFx : function(o){
10814 if(this.hasActiveFx() && !o.concurrent){
10825 * Returns true if the element is currently blocking so that no other effect can be queued
10826 * until this effect is finished, else returns false if blocking is not set. This is commonly
10827 * used to ensure that an effect initiated by a user action runs to completion prior to the
10828 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10829 * @return {Boolean} True if blocking, else false
10831 hasFxBlock : function(){
10832 var q = this.fxQueue;
10833 return q && q[0] && q[0].block;
10837 queueFx : function(o, fn){
10841 if(!this.hasFxBlock()){
10842 Roo.applyIf(o, this.fxDefaults);
10844 var run = this.beforeFx(o);
10845 fn.block = o.block;
10846 this.fxQueue.push(fn);
10858 fxWrap : function(pos, o, vis){
10860 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10863 wrapXY = this.getXY();
10865 var div = document.createElement("div");
10866 div.style.visibility = vis;
10867 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10868 wrap.setPositioning(pos);
10869 if(wrap.getStyle("position") == "static"){
10870 wrap.position("relative");
10872 this.clearPositioning('auto');
10874 wrap.dom.appendChild(this.dom);
10876 wrap.setXY(wrapXY);
10883 fxUnwrap : function(wrap, pos, o){
10884 this.clearPositioning();
10885 this.setPositioning(pos);
10887 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10893 getFxRestore : function(){
10894 var st = this.dom.style;
10895 return {pos: this.getPositioning(), width: st.width, height : st.height};
10899 afterFx : function(o){
10901 this.applyStyles(o.afterStyle);
10904 this.addClass(o.afterCls);
10906 if(o.remove === true){
10909 Roo.callback(o.callback, o.scope, [this]);
10911 this.fxQueue.shift();
10917 getFxEl : function(){ // support for composite element fx
10918 return Roo.get(this.dom);
10922 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10923 animType = animType || 'run';
10925 var anim = Roo.lib.Anim[animType](
10927 (opt.duration || defaultDur) || .35,
10928 (opt.easing || defaultEase) || 'easeOut',
10930 Roo.callback(cb, this);
10939 // backwords compat
10940 Roo.Fx.resize = Roo.Fx.scale;
10942 //When included, Roo.Fx is automatically applied to Element so that all basic
10943 //effects are available directly via the Element API
10944 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10946 * Ext JS Library 1.1.1
10947 * Copyright(c) 2006-2007, Ext JS, LLC.
10949 * Originally Released Under LGPL - original licence link has changed is not relivant.
10952 * <script type="text/javascript">
10957 * @class Roo.CompositeElement
10958 * Standard composite class. Creates a Roo.Element for every element in the collection.
10960 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10961 * actions will be performed on all the elements in this collection.</b>
10963 * All methods return <i>this</i> and can be chained.
10965 var els = Roo.select("#some-el div.some-class", true);
10966 // or select directly from an existing element
10967 var el = Roo.get('some-el');
10968 el.select('div.some-class', true);
10970 els.setWidth(100); // all elements become 100 width
10971 els.hide(true); // all elements fade out and hide
10973 els.setWidth(100).hide(true);
10976 Roo.CompositeElement = function(els){
10977 this.elements = [];
10978 this.addElements(els);
10980 Roo.CompositeElement.prototype = {
10982 addElements : function(els){
10983 if(!els) return this;
10984 if(typeof els == "string"){
10985 els = Roo.Element.selectorFunction(els);
10987 var yels = this.elements;
10988 var index = yels.length-1;
10989 for(var i = 0, len = els.length; i < len; i++) {
10990 yels[++index] = Roo.get(els[i]);
10996 * Clears this composite and adds the elements returned by the passed selector.
10997 * @param {String/Array} els A string CSS selector, an array of elements or an element
10998 * @return {CompositeElement} this
11000 fill : function(els){
11001 this.elements = [];
11007 * Filters this composite to only elements that match the passed selector.
11008 * @param {String} selector A string CSS selector
11009 * @param {Boolean} inverse return inverse filter (not matches)
11010 * @return {CompositeElement} this
11012 filter : function(selector, inverse){
11014 inverse = inverse || false;
11015 this.each(function(el){
11016 var match = inverse ? !el.is(selector) : el.is(selector);
11018 els[els.length] = el.dom;
11025 invoke : function(fn, args){
11026 var els = this.elements;
11027 for(var i = 0, len = els.length; i < len; i++) {
11028 Roo.Element.prototype[fn].apply(els[i], args);
11033 * Adds elements to this composite.
11034 * @param {String/Array} els A string CSS selector, an array of elements or an element
11035 * @return {CompositeElement} this
11037 add : function(els){
11038 if(typeof els == "string"){
11039 this.addElements(Roo.Element.selectorFunction(els));
11040 }else if(els.length !== undefined){
11041 this.addElements(els);
11043 this.addElements([els]);
11048 * Calls the passed function passing (el, this, index) for each element in this composite.
11049 * @param {Function} fn The function to call
11050 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11051 * @return {CompositeElement} this
11053 each : function(fn, scope){
11054 var els = this.elements;
11055 for(var i = 0, len = els.length; i < len; i++){
11056 if(fn.call(scope || els[i], els[i], this, i) === false) {
11064 * Returns the Element object at the specified index
11065 * @param {Number} index
11066 * @return {Roo.Element}
11068 item : function(index){
11069 return this.elements[index] || null;
11073 * Returns the first Element
11074 * @return {Roo.Element}
11076 first : function(){
11077 return this.item(0);
11081 * Returns the last Element
11082 * @return {Roo.Element}
11085 return this.item(this.elements.length-1);
11089 * Returns the number of elements in this composite
11092 getCount : function(){
11093 return this.elements.length;
11097 * Returns true if this composite contains the passed element
11100 contains : function(el){
11101 return this.indexOf(el) !== -1;
11105 * Returns true if this composite contains the passed element
11108 indexOf : function(el){
11109 return this.elements.indexOf(Roo.get(el));
11114 * Removes the specified element(s).
11115 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11116 * or an array of any of those.
11117 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11118 * @return {CompositeElement} this
11120 removeElement : function(el, removeDom){
11121 if(el instanceof Array){
11122 for(var i = 0, len = el.length; i < len; i++){
11123 this.removeElement(el[i]);
11127 var index = typeof el == 'number' ? el : this.indexOf(el);
11130 var d = this.elements[index];
11134 d.parentNode.removeChild(d);
11137 this.elements.splice(index, 1);
11143 * Replaces the specified element with the passed element.
11144 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11146 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11147 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11148 * @return {CompositeElement} this
11150 replaceElement : function(el, replacement, domReplace){
11151 var index = typeof el == 'number' ? el : this.indexOf(el);
11154 this.elements[index].replaceWith(replacement);
11156 this.elements.splice(index, 1, Roo.get(replacement))
11163 * Removes all elements.
11165 clear : function(){
11166 this.elements = [];
11170 Roo.CompositeElement.createCall = function(proto, fnName){
11171 if(!proto[fnName]){
11172 proto[fnName] = function(){
11173 return this.invoke(fnName, arguments);
11177 for(var fnName in Roo.Element.prototype){
11178 if(typeof Roo.Element.prototype[fnName] == "function"){
11179 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11185 * Ext JS Library 1.1.1
11186 * Copyright(c) 2006-2007, Ext JS, LLC.
11188 * Originally Released Under LGPL - original licence link has changed is not relivant.
11191 * <script type="text/javascript">
11195 * @class Roo.CompositeElementLite
11196 * @extends Roo.CompositeElement
11197 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11199 var els = Roo.select("#some-el div.some-class");
11200 // or select directly from an existing element
11201 var el = Roo.get('some-el');
11202 el.select('div.some-class');
11204 els.setWidth(100); // all elements become 100 width
11205 els.hide(true); // all elements fade out and hide
11207 els.setWidth(100).hide(true);
11208 </code></pre><br><br>
11209 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11210 * actions will be performed on all the elements in this collection.</b>
11212 Roo.CompositeElementLite = function(els){
11213 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11214 this.el = new Roo.Element.Flyweight();
11216 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11217 addElements : function(els){
11219 if(els instanceof Array){
11220 this.elements = this.elements.concat(els);
11222 var yels = this.elements;
11223 var index = yels.length-1;
11224 for(var i = 0, len = els.length; i < len; i++) {
11225 yels[++index] = els[i];
11231 invoke : function(fn, args){
11232 var els = this.elements;
11234 for(var i = 0, len = els.length; i < len; i++) {
11236 Roo.Element.prototype[fn].apply(el, args);
11241 * Returns a flyweight Element of the dom element object at the specified index
11242 * @param {Number} index
11243 * @return {Roo.Element}
11245 item : function(index){
11246 if(!this.elements[index]){
11249 this.el.dom = this.elements[index];
11253 // fixes scope with flyweight
11254 addListener : function(eventName, handler, scope, opt){
11255 var els = this.elements;
11256 for(var i = 0, len = els.length; i < len; i++) {
11257 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11263 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11264 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11265 * a reference to the dom node, use el.dom.</b>
11266 * @param {Function} fn The function to call
11267 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11268 * @return {CompositeElement} this
11270 each : function(fn, scope){
11271 var els = this.elements;
11273 for(var i = 0, len = els.length; i < len; i++){
11275 if(fn.call(scope || el, el, this, i) === false){
11282 indexOf : function(el){
11283 return this.elements.indexOf(Roo.getDom(el));
11286 replaceElement : function(el, replacement, domReplace){
11287 var index = typeof el == 'number' ? el : this.indexOf(el);
11289 replacement = Roo.getDom(replacement);
11291 var d = this.elements[index];
11292 d.parentNode.insertBefore(replacement, d);
11293 d.parentNode.removeChild(d);
11295 this.elements.splice(index, 1, replacement);
11300 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11304 * Ext JS Library 1.1.1
11305 * Copyright(c) 2006-2007, Ext JS, LLC.
11307 * Originally Released Under LGPL - original licence link has changed is not relivant.
11310 * <script type="text/javascript">
11316 * @class Roo.data.Connection
11317 * @extends Roo.util.Observable
11318 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11319 * either to a configured URL, or to a URL specified at request time.<br><br>
11321 * Requests made by this class are asynchronous, and will return immediately. No data from
11322 * the server will be available to the statement immediately following the {@link #request} call.
11323 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11325 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11326 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11327 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11328 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11329 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11330 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11331 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11332 * standard DOM methods.
11334 * @param {Object} config a configuration object.
11336 Roo.data.Connection = function(config){
11337 Roo.apply(this, config);
11340 * @event beforerequest
11341 * Fires before a network request is made to retrieve a data object.
11342 * @param {Connection} conn This Connection object.
11343 * @param {Object} options The options config object passed to the {@link #request} method.
11345 "beforerequest" : true,
11347 * @event requestcomplete
11348 * Fires if the request was successfully completed.
11349 * @param {Connection} conn This Connection object.
11350 * @param {Object} response The XHR object containing the response data.
11351 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11352 * @param {Object} options The options config object passed to the {@link #request} method.
11354 "requestcomplete" : true,
11356 * @event requestexception
11357 * Fires if an error HTTP status was returned from the server.
11358 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11359 * @param {Connection} conn This Connection object.
11360 * @param {Object} response The XHR object containing the response data.
11361 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11362 * @param {Object} options The options config object passed to the {@link #request} method.
11364 "requestexception" : true
11366 Roo.data.Connection.superclass.constructor.call(this);
11369 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11371 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11374 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11375 * extra parameters to each request made by this object. (defaults to undefined)
11378 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11379 * to each request made by this object. (defaults to undefined)
11382 * @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)
11385 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11389 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11395 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11398 disableCaching: true,
11401 * Sends an HTTP request to a remote server.
11402 * @param {Object} options An object which may contain the following properties:<ul>
11403 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11404 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11405 * request, a url encoded string or a function to call to get either.</li>
11406 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11407 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11408 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11409 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11410 * <li>options {Object} The parameter to the request call.</li>
11411 * <li>success {Boolean} True if the request succeeded.</li>
11412 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11414 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11415 * The callback is passed the following parameters:<ul>
11416 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11417 * <li>options {Object} The parameter to the request call.</li>
11419 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11420 * The callback is passed the following parameters:<ul>
11421 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11422 * <li>options {Object} The parameter to the request call.</li>
11424 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11425 * for the callback function. Defaults to the browser window.</li>
11426 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11427 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11428 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11429 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11430 * params for the post data. Any params will be appended to the URL.</li>
11431 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11433 * @return {Number} transactionId
11435 request : function(o){
11436 if(this.fireEvent("beforerequest", this, o) !== false){
11439 if(typeof p == "function"){
11440 p = p.call(o.scope||window, o);
11442 if(typeof p == "object"){
11443 p = Roo.urlEncode(o.params);
11445 if(this.extraParams){
11446 var extras = Roo.urlEncode(this.extraParams);
11447 p = p ? (p + '&' + extras) : extras;
11450 var url = o.url || this.url;
11451 if(typeof url == 'function'){
11452 url = url.call(o.scope||window, o);
11456 var form = Roo.getDom(o.form);
11457 url = url || form.action;
11459 var enctype = form.getAttribute("enctype");
11460 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11461 return this.doFormUpload(o, p, url);
11463 var f = Roo.lib.Ajax.serializeForm(form);
11464 p = p ? (p + '&' + f) : f;
11467 var hs = o.headers;
11468 if(this.defaultHeaders){
11469 hs = Roo.apply(hs || {}, this.defaultHeaders);
11476 success: this.handleResponse,
11477 failure: this.handleFailure,
11479 argument: {options: o},
11480 timeout : o.timeout || this.timeout
11483 var method = o.method||this.method||(p ? "POST" : "GET");
11485 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11486 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11489 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11493 }else if(this.autoAbort !== false){
11497 if((method == 'GET' && p) || o.xmlData){
11498 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11501 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11502 return this.transId;
11504 Roo.callback(o.callback, o.scope, [o, null, null]);
11510 * Determine whether this object has a request outstanding.
11511 * @param {Number} transactionId (Optional) defaults to the last transaction
11512 * @return {Boolean} True if there is an outstanding request.
11514 isLoading : function(transId){
11516 return Roo.lib.Ajax.isCallInProgress(transId);
11518 return this.transId ? true : false;
11523 * Aborts any outstanding request.
11524 * @param {Number} transactionId (Optional) defaults to the last transaction
11526 abort : function(transId){
11527 if(transId || this.isLoading()){
11528 Roo.lib.Ajax.abort(transId || this.transId);
11533 handleResponse : function(response){
11534 this.transId = false;
11535 var options = response.argument.options;
11536 response.argument = options ? options.argument : null;
11537 this.fireEvent("requestcomplete", this, response, options);
11538 Roo.callback(options.success, options.scope, [response, options]);
11539 Roo.callback(options.callback, options.scope, [options, true, response]);
11543 handleFailure : function(response, e){
11544 this.transId = false;
11545 var options = response.argument.options;
11546 response.argument = options ? options.argument : null;
11547 this.fireEvent("requestexception", this, response, options, e);
11548 Roo.callback(options.failure, options.scope, [response, options]);
11549 Roo.callback(options.callback, options.scope, [options, false, response]);
11553 doFormUpload : function(o, ps, url){
11555 var frame = document.createElement('iframe');
11558 frame.className = 'x-hidden';
11560 frame.src = Roo.SSL_SECURE_URL;
11562 document.body.appendChild(frame);
11565 document.frames[id].name = id;
11568 var form = Roo.getDom(o.form);
11570 form.method = 'POST';
11571 form.enctype = form.encoding = 'multipart/form-data';
11577 if(ps){ // add dynamic params
11579 ps = Roo.urlDecode(ps, false);
11581 if(ps.hasOwnProperty(k)){
11582 hd = document.createElement('input');
11583 hd.type = 'hidden';
11586 form.appendChild(hd);
11593 var r = { // bogus response object
11598 r.argument = o ? o.argument : null;
11603 doc = frame.contentWindow.document;
11605 doc = (frame.contentDocument || window.frames[id].document);
11607 if(doc && doc.body){
11608 r.responseText = doc.body.innerHTML;
11610 if(doc && doc.XMLDocument){
11611 r.responseXML = doc.XMLDocument;
11613 r.responseXML = doc;
11620 Roo.EventManager.removeListener(frame, 'load', cb, this);
11622 this.fireEvent("requestcomplete", this, r, o);
11623 Roo.callback(o.success, o.scope, [r, o]);
11624 Roo.callback(o.callback, o.scope, [o, true, r]);
11626 setTimeout(function(){document.body.removeChild(frame);}, 100);
11629 Roo.EventManager.on(frame, 'load', cb, this);
11632 if(hiddens){ // remove dynamic params
11633 for(var i = 0, len = hiddens.length; i < len; i++){
11634 form.removeChild(hiddens[i]);
11641 * Ext JS Library 1.1.1
11642 * Copyright(c) 2006-2007, Ext JS, LLC.
11644 * Originally Released Under LGPL - original licence link has changed is not relivant.
11647 * <script type="text/javascript">
11651 * Global Ajax request class.
11654 * @extends Roo.data.Connection
11657 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11658 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11659 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11660 * @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)
11661 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11662 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11663 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11665 Roo.Ajax = new Roo.data.Connection({
11674 * Serialize the passed form into a url encoded string
11676 * @param {String/HTMLElement} form
11679 serializeForm : function(form){
11680 return Roo.lib.Ajax.serializeForm(form);
11684 * Ext JS Library 1.1.1
11685 * Copyright(c) 2006-2007, Ext JS, LLC.
11687 * Originally Released Under LGPL - original licence link has changed is not relivant.
11690 * <script type="text/javascript">
11695 * @class Roo.UpdateManager
11696 * @extends Roo.util.Observable
11697 * Provides AJAX-style update for Element object.<br><br>
11700 * // Get it from a Roo.Element object
11701 * var el = Roo.get("foo");
11702 * var mgr = el.getUpdateManager();
11703 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11705 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11707 * // or directly (returns the same UpdateManager instance)
11708 * var mgr = new Roo.UpdateManager("myElementId");
11709 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11710 * mgr.on("update", myFcnNeedsToKnow);
11712 // short handed call directly from the element object
11713 Roo.get("foo").load({
11717 text: "Loading Foo..."
11721 * Create new UpdateManager directly.
11722 * @param {String/HTMLElement/Roo.Element} el The element to update
11723 * @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).
11725 Roo.UpdateManager = function(el, forceNew){
11727 if(!forceNew && el.updateManager){
11728 return el.updateManager;
11731 * The Element object
11732 * @type Roo.Element
11736 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11739 this.defaultUrl = null;
11743 * @event beforeupdate
11744 * Fired before an update is made, return false from your handler and the update is cancelled.
11745 * @param {Roo.Element} el
11746 * @param {String/Object/Function} url
11747 * @param {String/Object} params
11749 "beforeupdate": true,
11752 * Fired after successful update is made.
11753 * @param {Roo.Element} el
11754 * @param {Object} oResponseObject The response Object
11759 * Fired on update failure.
11760 * @param {Roo.Element} el
11761 * @param {Object} oResponseObject The response Object
11765 var d = Roo.UpdateManager.defaults;
11767 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11770 this.sslBlankUrl = d.sslBlankUrl;
11772 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11775 this.disableCaching = d.disableCaching;
11777 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11780 this.indicatorText = d.indicatorText;
11782 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11785 this.showLoadIndicator = d.showLoadIndicator;
11787 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11790 this.timeout = d.timeout;
11793 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11796 this.loadScripts = d.loadScripts;
11799 * Transaction object of current executing transaction
11801 this.transaction = null;
11806 this.autoRefreshProcId = null;
11808 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11811 this.refreshDelegate = this.refresh.createDelegate(this);
11813 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11816 this.updateDelegate = this.update.createDelegate(this);
11818 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11821 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11825 this.successDelegate = this.processSuccess.createDelegate(this);
11829 this.failureDelegate = this.processFailure.createDelegate(this);
11831 if(!this.renderer){
11833 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11835 this.renderer = new Roo.UpdateManager.BasicRenderer();
11838 Roo.UpdateManager.superclass.constructor.call(this);
11841 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11843 * Get the Element this UpdateManager is bound to
11844 * @return {Roo.Element} The element
11846 getEl : function(){
11850 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11851 * @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:
11854 url: "your-url.php",<br/>
11855 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11856 callback: yourFunction,<br/>
11857 scope: yourObject, //(optional scope) <br/>
11858 discardUrl: false, <br/>
11859 nocache: false,<br/>
11860 text: "Loading...",<br/>
11862 scripts: false<br/>
11865 * The only required property is url. The optional properties nocache, text and scripts
11866 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11867 * @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}
11868 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11869 * @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.
11871 update : function(url, params, callback, discardUrl){
11872 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11873 var method = this.method,
11875 if(typeof url == "object"){ // must be config object
11878 params = params || cfg.params;
11879 callback = callback || cfg.callback;
11880 discardUrl = discardUrl || cfg.discardUrl;
11881 if(callback && cfg.scope){
11882 callback = callback.createDelegate(cfg.scope);
11884 if(typeof cfg.method != "undefined"){method = cfg.method;};
11885 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11886 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11887 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11888 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11890 this.showLoading();
11892 this.defaultUrl = url;
11894 if(typeof url == "function"){
11895 url = url.call(this);
11898 method = method || (params ? "POST" : "GET");
11899 if(method == "GET"){
11900 url = this.prepareUrl(url);
11903 var o = Roo.apply(cfg ||{}, {
11906 success: this.successDelegate,
11907 failure: this.failureDelegate,
11908 callback: undefined,
11909 timeout: (this.timeout*1000),
11910 argument: {"url": url, "form": null, "callback": callback, "params": params}
11912 Roo.log("updated manager called with timeout of " + o.timeout);
11913 this.transaction = Roo.Ajax.request(o);
11918 * 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.
11919 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11920 * @param {String/HTMLElement} form The form Id or form element
11921 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11922 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11923 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11925 formUpdate : function(form, url, reset, callback){
11926 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11927 if(typeof url == "function"){
11928 url = url.call(this);
11930 form = Roo.getDom(form);
11931 this.transaction = Roo.Ajax.request({
11934 success: this.successDelegate,
11935 failure: this.failureDelegate,
11936 timeout: (this.timeout*1000),
11937 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11939 this.showLoading.defer(1, this);
11944 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11945 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11947 refresh : function(callback){
11948 if(this.defaultUrl == null){
11951 this.update(this.defaultUrl, null, callback, true);
11955 * Set this element to auto refresh.
11956 * @param {Number} interval How often to update (in seconds).
11957 * @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)
11958 * @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}
11959 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11960 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11962 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11964 this.update(url || this.defaultUrl, params, callback, true);
11966 if(this.autoRefreshProcId){
11967 clearInterval(this.autoRefreshProcId);
11969 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11973 * Stop auto refresh on this element.
11975 stopAutoRefresh : function(){
11976 if(this.autoRefreshProcId){
11977 clearInterval(this.autoRefreshProcId);
11978 delete this.autoRefreshProcId;
11982 isAutoRefreshing : function(){
11983 return this.autoRefreshProcId ? true : false;
11986 * Called to update the element to "Loading" state. Override to perform custom action.
11988 showLoading : function(){
11989 if(this.showLoadIndicator){
11990 this.el.update(this.indicatorText);
11995 * Adds unique parameter to query string if disableCaching = true
11998 prepareUrl : function(url){
11999 if(this.disableCaching){
12000 var append = "_dc=" + (new Date().getTime());
12001 if(url.indexOf("?") !== -1){
12002 url += "&" + append;
12004 url += "?" + append;
12013 processSuccess : function(response){
12014 this.transaction = null;
12015 if(response.argument.form && response.argument.reset){
12016 try{ // put in try/catch since some older FF releases had problems with this
12017 response.argument.form.reset();
12020 if(this.loadScripts){
12021 this.renderer.render(this.el, response, this,
12022 this.updateComplete.createDelegate(this, [response]));
12024 this.renderer.render(this.el, response, this);
12025 this.updateComplete(response);
12029 updateComplete : function(response){
12030 this.fireEvent("update", this.el, response);
12031 if(typeof response.argument.callback == "function"){
12032 response.argument.callback(this.el, true, response);
12039 processFailure : function(response){
12040 this.transaction = null;
12041 this.fireEvent("failure", this.el, response);
12042 if(typeof response.argument.callback == "function"){
12043 response.argument.callback(this.el, false, response);
12048 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12049 * @param {Object} renderer The object implementing the render() method
12051 setRenderer : function(renderer){
12052 this.renderer = renderer;
12055 getRenderer : function(){
12056 return this.renderer;
12060 * Set the defaultUrl used for updates
12061 * @param {String/Function} defaultUrl The url or a function to call to get the url
12063 setDefaultUrl : function(defaultUrl){
12064 this.defaultUrl = defaultUrl;
12068 * Aborts the executing transaction
12070 abort : function(){
12071 if(this.transaction){
12072 Roo.Ajax.abort(this.transaction);
12077 * Returns true if an update is in progress
12078 * @return {Boolean}
12080 isUpdating : function(){
12081 if(this.transaction){
12082 return Roo.Ajax.isLoading(this.transaction);
12089 * @class Roo.UpdateManager.defaults
12090 * @static (not really - but it helps the doc tool)
12091 * The defaults collection enables customizing the default properties of UpdateManager
12093 Roo.UpdateManager.defaults = {
12095 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12101 * True to process scripts by default (Defaults to false).
12104 loadScripts : false,
12107 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12110 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12112 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12115 disableCaching : false,
12117 * Whether to show indicatorText when loading (Defaults to true).
12120 showLoadIndicator : true,
12122 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12125 indicatorText : '<div class="loading-indicator">Loading...</div>'
12129 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12131 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12132 * @param {String/HTMLElement/Roo.Element} el The element to update
12133 * @param {String} url The url
12134 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12135 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12138 * @member Roo.UpdateManager
12140 Roo.UpdateManager.updateElement = function(el, url, params, options){
12141 var um = Roo.get(el, true).getUpdateManager();
12142 Roo.apply(um, options);
12143 um.update(url, params, options ? options.callback : null);
12145 // alias for backwards compat
12146 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12148 * @class Roo.UpdateManager.BasicRenderer
12149 * Default Content renderer. Updates the elements innerHTML with the responseText.
12151 Roo.UpdateManager.BasicRenderer = function(){};
12153 Roo.UpdateManager.BasicRenderer.prototype = {
12155 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12156 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12157 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12158 * @param {Roo.Element} el The element being rendered
12159 * @param {Object} response The YUI Connect response object
12160 * @param {UpdateManager} updateManager The calling update manager
12161 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12163 render : function(el, response, updateManager, callback){
12164 el.update(response.responseText, updateManager.loadScripts, callback);
12170 * (c)) Alan Knowles
12176 * @class Roo.DomTemplate
12177 * @extends Roo.Template
12178 * An effort at a dom based template engine..
12180 * Similar to XTemplate, except it uses dom parsing to create the template..
12182 * Supported features:
12187 {a_variable} - output encoded.
12188 {a_variable.format:("Y-m-d")} - call a method on the variable
12189 {a_variable:raw} - unencoded output
12190 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12191 {a_variable:this.method_on_template(...)} - call a method on the template object.
12196 <div roo-for="a_variable or condition.."></div>
12197 <div roo-if="a_variable or condition"></div>
12198 <div roo-exec="some javascript"></div>
12199 <div roo-name="named_template"></div>
12204 Roo.DomTemplate = function()
12206 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12213 Roo.extend(Roo.DomTemplate, Roo.Template, {
12215 * id counter for sub templates.
12219 * flag to indicate if dom parser is inside a pre,
12220 * it will strip whitespace if not.
12225 * The various sub templates
12233 * basic tag replacing syntax
12236 * // you can fake an object call by doing this
12240 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12241 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12243 iterChild : function (node, method) {
12245 var oldPre = this.inPre;
12246 if (node.tagName == 'PRE') {
12249 for( var i = 0; i < node.childNodes.length; i++) {
12250 method.call(this, node.childNodes[i]);
12252 this.inPre = oldPre;
12258 * compile the template
12260 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12263 compile: function()
12267 // covert the html into DOM...
12271 doc = document.implementation.createHTMLDocument("");
12272 doc.documentElement.innerHTML = this.html ;
12273 div = doc.documentElement;
12275 // old IE... - nasty -- it causes all sorts of issues.. with
12276 // images getting pulled from server..
12277 div = document.createElement('div');
12278 div.innerHTML = this.html;
12280 //doc.documentElement.innerHTML = htmlBody
12286 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12288 var tpls = this.tpls;
12290 // create a top level template from the snippet..
12292 //Roo.log(div.innerHTML);
12299 body : div.innerHTML,
12312 Roo.each(tpls, function(tp){
12313 this.compileTpl(tp);
12314 this.tpls[tp.id] = tp;
12317 this.master = tpls[0];
12323 compileNode : function(node, istop) {
12328 // skip anything not a tag..
12329 if (node.nodeType != 1) {
12330 if (node.nodeType == 3 && !this.inPre) {
12331 // reduce white space..
12332 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12355 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12356 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12357 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12358 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12364 // just itterate children..
12365 this.iterChild(node,this.compileNode);
12368 tpl.uid = this.id++;
12369 tpl.value = node.getAttribute('roo-' + tpl.attr);
12370 node.removeAttribute('roo-'+ tpl.attr);
12371 if (tpl.attr != 'name') {
12372 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12373 node.parentNode.replaceChild(placeholder, node);
12376 var placeholder = document.createElement('span');
12377 placeholder.className = 'roo-tpl-' + tpl.value;
12378 node.parentNode.replaceChild(placeholder, node);
12381 // parent now sees '{domtplXXXX}
12382 this.iterChild(node,this.compileNode);
12384 // we should now have node body...
12385 var div = document.createElement('div');
12386 div.appendChild(node);
12388 // this has the unfortunate side effect of converting tagged attributes
12389 // eg. href="{...}" into %7C...%7D
12390 // this has been fixed by searching for those combo's although it's a bit hacky..
12393 tpl.body = div.innerHTML;
12400 switch (tpl.value) {
12401 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12402 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12403 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12408 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12412 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12416 tpl.id = tpl.value; // replace non characters???
12422 this.tpls.push(tpl);
12432 * Compile a segment of the template into a 'sub-template'
12438 compileTpl : function(tpl)
12440 var fm = Roo.util.Format;
12441 var useF = this.disableFormats !== true;
12443 var sep = Roo.isGecko ? "+\n" : ",\n";
12445 var undef = function(str) {
12446 Roo.debug && Roo.log("Property not found :" + str);
12450 //Roo.log(tpl.body);
12454 var fn = function(m, lbrace, name, format, args)
12457 //Roo.log(arguments);
12458 args = args ? args.replace(/\\'/g,"'") : args;
12459 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12460 if (typeof(format) == 'undefined') {
12461 format = 'htmlEncode';
12463 if (format == 'raw' ) {
12467 if(name.substr(0, 6) == 'domtpl'){
12468 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12471 // build an array of options to determine if value is undefined..
12473 // basically get 'xxxx.yyyy' then do
12474 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12475 // (function () { Roo.log("Property not found"); return ''; })() :
12480 Roo.each(name.split('.'), function(st) {
12481 lookfor += (lookfor.length ? '.': '') + st;
12482 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12485 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12488 if(format && useF){
12490 args = args ? ',' + args : "";
12492 if(format.substr(0, 5) != "this."){
12493 format = "fm." + format + '(';
12495 format = 'this.call("'+ format.substr(5) + '", ';
12499 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12502 if (args && args.length) {
12503 // called with xxyx.yuu:(test,test)
12505 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12507 // raw.. - :raw modifier..
12508 return "'"+ sep + udef_st + name + ")"+sep+"'";
12512 // branched to use + in gecko and [].join() in others
12514 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12515 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12518 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12519 body.push(tpl.body.replace(/(\r\n|\n)/g,
12520 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12521 body.push("'].join('');};};");
12522 body = body.join('');
12525 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12527 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12534 * same as applyTemplate, except it's done to one of the subTemplates
12535 * when using named templates, you can do:
12537 * var str = pl.applySubTemplate('your-name', values);
12540 * @param {Number} id of the template
12541 * @param {Object} values to apply to template
12542 * @param {Object} parent (normaly the instance of this object)
12544 applySubTemplate : function(id, values, parent)
12548 var t = this.tpls[id];
12552 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12553 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12557 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12564 if(t.execCall && t.execCall.call(this, values, parent)){
12568 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12574 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12575 parent = t.target ? values : parent;
12576 if(t.forCall && vs instanceof Array){
12578 for(var i = 0, len = vs.length; i < len; i++){
12580 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12582 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12584 //Roo.log(t.compiled);
12588 return buf.join('');
12591 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12596 return t.compiled.call(this, vs, parent);
12598 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12600 //Roo.log(t.compiled);
12608 applyTemplate : function(values){
12609 return this.master.compiled.call(this, values, {});
12610 //var s = this.subs;
12613 apply : function(){
12614 return this.applyTemplate.apply(this, arguments);
12619 Roo.DomTemplate.from = function(el){
12620 el = Roo.getDom(el);
12621 return new Roo.Domtemplate(el.value || el.innerHTML);
12624 * Ext JS Library 1.1.1
12625 * Copyright(c) 2006-2007, Ext JS, LLC.
12627 * Originally Released Under LGPL - original licence link has changed is not relivant.
12630 * <script type="text/javascript">
12634 * @class Roo.util.DelayedTask
12635 * Provides a convenient method of performing setTimeout where a new
12636 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12637 * You can use this class to buffer
12638 * the keypress events for a certain number of milliseconds, and perform only if they stop
12639 * for that amount of time.
12640 * @constructor The parameters to this constructor serve as defaults and are not required.
12641 * @param {Function} fn (optional) The default function to timeout
12642 * @param {Object} scope (optional) The default scope of that timeout
12643 * @param {Array} args (optional) The default Array of arguments
12645 Roo.util.DelayedTask = function(fn, scope, args){
12646 var id = null, d, t;
12648 var call = function(){
12649 var now = new Date().getTime();
12653 fn.apply(scope, args || []);
12657 * Cancels any pending timeout and queues a new one
12658 * @param {Number} delay The milliseconds to delay
12659 * @param {Function} newFn (optional) Overrides function passed to constructor
12660 * @param {Object} newScope (optional) Overrides scope passed to constructor
12661 * @param {Array} newArgs (optional) Overrides args passed to constructor
12663 this.delay = function(delay, newFn, newScope, newArgs){
12664 if(id && delay != d){
12668 t = new Date().getTime();
12670 scope = newScope || scope;
12671 args = newArgs || args;
12673 id = setInterval(call, d);
12678 * Cancel the last queued timeout
12680 this.cancel = function(){
12688 * Ext JS Library 1.1.1
12689 * Copyright(c) 2006-2007, Ext JS, LLC.
12691 * Originally Released Under LGPL - original licence link has changed is not relivant.
12694 * <script type="text/javascript">
12698 Roo.util.TaskRunner = function(interval){
12699 interval = interval || 10;
12700 var tasks = [], removeQueue = [];
12702 var running = false;
12704 var stopThread = function(){
12710 var startThread = function(){
12713 id = setInterval(runTasks, interval);
12717 var removeTask = function(task){
12718 removeQueue.push(task);
12724 var runTasks = function(){
12725 if(removeQueue.length > 0){
12726 for(var i = 0, len = removeQueue.length; i < len; i++){
12727 tasks.remove(removeQueue[i]);
12730 if(tasks.length < 1){
12735 var now = new Date().getTime();
12736 for(var i = 0, len = tasks.length; i < len; ++i){
12738 var itime = now - t.taskRunTime;
12739 if(t.interval <= itime){
12740 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12741 t.taskRunTime = now;
12742 if(rt === false || t.taskRunCount === t.repeat){
12747 if(t.duration && t.duration <= (now - t.taskStartTime)){
12754 * Queues a new task.
12755 * @param {Object} task
12757 this.start = function(task){
12759 task.taskStartTime = new Date().getTime();
12760 task.taskRunTime = 0;
12761 task.taskRunCount = 0;
12766 this.stop = function(task){
12771 this.stopAll = function(){
12773 for(var i = 0, len = tasks.length; i < len; i++){
12774 if(tasks[i].onStop){
12783 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12785 * Ext JS Library 1.1.1
12786 * Copyright(c) 2006-2007, Ext JS, LLC.
12788 * Originally Released Under LGPL - original licence link has changed is not relivant.
12791 * <script type="text/javascript">
12796 * @class Roo.util.MixedCollection
12797 * @extends Roo.util.Observable
12798 * A Collection class that maintains both numeric indexes and keys and exposes events.
12800 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12801 * collection (defaults to false)
12802 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12803 * and return the key value for that item. This is used when available to look up the key on items that
12804 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12805 * equivalent to providing an implementation for the {@link #getKey} method.
12807 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12815 * Fires when the collection is cleared.
12820 * Fires when an item is added to the collection.
12821 * @param {Number} index The index at which the item was added.
12822 * @param {Object} o The item added.
12823 * @param {String} key The key associated with the added item.
12828 * Fires when an item is replaced in the collection.
12829 * @param {String} key he key associated with the new added.
12830 * @param {Object} old The item being replaced.
12831 * @param {Object} new The new item.
12836 * Fires when an item is removed from the collection.
12837 * @param {Object} o The item being removed.
12838 * @param {String} key (optional) The key associated with the removed item.
12843 this.allowFunctions = allowFunctions === true;
12845 this.getKey = keyFn;
12847 Roo.util.MixedCollection.superclass.constructor.call(this);
12850 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12851 allowFunctions : false,
12854 * Adds an item to the collection.
12855 * @param {String} key The key to associate with the item
12856 * @param {Object} o The item to add.
12857 * @return {Object} The item added.
12859 add : function(key, o){
12860 if(arguments.length == 1){
12862 key = this.getKey(o);
12864 if(typeof key == "undefined" || key === null){
12866 this.items.push(o);
12867 this.keys.push(null);
12869 var old = this.map[key];
12871 return this.replace(key, o);
12874 this.items.push(o);
12876 this.keys.push(key);
12878 this.fireEvent("add", this.length-1, o, key);
12883 * MixedCollection has a generic way to fetch keys if you implement getKey.
12886 var mc = new Roo.util.MixedCollection();
12887 mc.add(someEl.dom.id, someEl);
12888 mc.add(otherEl.dom.id, otherEl);
12892 var mc = new Roo.util.MixedCollection();
12893 mc.getKey = function(el){
12899 // or via the constructor
12900 var mc = new Roo.util.MixedCollection(false, function(el){
12906 * @param o {Object} The item for which to find the key.
12907 * @return {Object} The key for the passed item.
12909 getKey : function(o){
12914 * Replaces an item in the collection.
12915 * @param {String} key The key associated with the item to replace, or the item to replace.
12916 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12917 * @return {Object} The new item.
12919 replace : function(key, o){
12920 if(arguments.length == 1){
12922 key = this.getKey(o);
12924 var old = this.item(key);
12925 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12926 return this.add(key, o);
12928 var index = this.indexOfKey(key);
12929 this.items[index] = o;
12931 this.fireEvent("replace", key, old, o);
12936 * Adds all elements of an Array or an Object to the collection.
12937 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12938 * an Array of values, each of which are added to the collection.
12940 addAll : function(objs){
12941 if(arguments.length > 1 || objs instanceof Array){
12942 var args = arguments.length > 1 ? arguments : objs;
12943 for(var i = 0, len = args.length; i < len; i++){
12947 for(var key in objs){
12948 if(this.allowFunctions || typeof objs[key] != "function"){
12949 this.add(key, objs[key]);
12956 * Executes the specified function once for every item in the collection, passing each
12957 * item as the first and only parameter. returning false from the function will stop the iteration.
12958 * @param {Function} fn The function to execute for each item.
12959 * @param {Object} scope (optional) The scope in which to execute the function.
12961 each : function(fn, scope){
12962 var items = [].concat(this.items); // each safe for removal
12963 for(var i = 0, len = items.length; i < len; i++){
12964 if(fn.call(scope || items[i], items[i], i, len) === false){
12971 * Executes the specified function once for every key in the collection, passing each
12972 * key, and its associated item as the first two parameters.
12973 * @param {Function} fn The function to execute for each item.
12974 * @param {Object} scope (optional) The scope in which to execute the function.
12976 eachKey : function(fn, scope){
12977 for(var i = 0, len = this.keys.length; i < len; i++){
12978 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12983 * Returns the first item in the collection which elicits a true return value from the
12984 * passed selection function.
12985 * @param {Function} fn The selection function to execute for each item.
12986 * @param {Object} scope (optional) The scope in which to execute the function.
12987 * @return {Object} The first item in the collection which returned true from the selection function.
12989 find : function(fn, scope){
12990 for(var i = 0, len = this.items.length; i < len; i++){
12991 if(fn.call(scope || window, this.items[i], this.keys[i])){
12992 return this.items[i];
12999 * Inserts an item at the specified index in the collection.
13000 * @param {Number} index The index to insert the item at.
13001 * @param {String} key The key to associate with the new item, or the item itself.
13002 * @param {Object} o (optional) If the second parameter was a key, the new item.
13003 * @return {Object} The item inserted.
13005 insert : function(index, key, o){
13006 if(arguments.length == 2){
13008 key = this.getKey(o);
13010 if(index >= this.length){
13011 return this.add(key, o);
13014 this.items.splice(index, 0, o);
13015 if(typeof key != "undefined" && key != null){
13018 this.keys.splice(index, 0, key);
13019 this.fireEvent("add", index, o, key);
13024 * Removed an item from the collection.
13025 * @param {Object} o The item to remove.
13026 * @return {Object} The item removed.
13028 remove : function(o){
13029 return this.removeAt(this.indexOf(o));
13033 * Remove an item from a specified index in the collection.
13034 * @param {Number} index The index within the collection of the item to remove.
13036 removeAt : function(index){
13037 if(index < this.length && index >= 0){
13039 var o = this.items[index];
13040 this.items.splice(index, 1);
13041 var key = this.keys[index];
13042 if(typeof key != "undefined"){
13043 delete this.map[key];
13045 this.keys.splice(index, 1);
13046 this.fireEvent("remove", o, key);
13051 * Removed an item associated with the passed key fom the collection.
13052 * @param {String} key The key of the item to remove.
13054 removeKey : function(key){
13055 return this.removeAt(this.indexOfKey(key));
13059 * Returns the number of items in the collection.
13060 * @return {Number} the number of items in the collection.
13062 getCount : function(){
13063 return this.length;
13067 * Returns index within the collection of the passed Object.
13068 * @param {Object} o The item to find the index of.
13069 * @return {Number} index of the item.
13071 indexOf : function(o){
13072 if(!this.items.indexOf){
13073 for(var i = 0, len = this.items.length; i < len; i++){
13074 if(this.items[i] == o) return i;
13078 return this.items.indexOf(o);
13083 * Returns index within the collection of the passed key.
13084 * @param {String} key The key to find the index of.
13085 * @return {Number} index of the key.
13087 indexOfKey : function(key){
13088 if(!this.keys.indexOf){
13089 for(var i = 0, len = this.keys.length; i < len; i++){
13090 if(this.keys[i] == key) return i;
13094 return this.keys.indexOf(key);
13099 * Returns the item associated with the passed key OR index. Key has priority over index.
13100 * @param {String/Number} key The key or index of the item.
13101 * @return {Object} The item associated with the passed key.
13103 item : function(key){
13104 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13105 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13109 * Returns the item at the specified index.
13110 * @param {Number} index The index of the item.
13113 itemAt : function(index){
13114 return this.items[index];
13118 * Returns the item associated with the passed key.
13119 * @param {String/Number} key The key of the item.
13120 * @return {Object} The item associated with the passed key.
13122 key : function(key){
13123 return this.map[key];
13127 * Returns true if the collection contains the passed Object as an item.
13128 * @param {Object} o The Object to look for in the collection.
13129 * @return {Boolean} True if the collection contains the Object as an item.
13131 contains : function(o){
13132 return this.indexOf(o) != -1;
13136 * Returns true if the collection contains the passed Object as a key.
13137 * @param {String} key The key to look for in the collection.
13138 * @return {Boolean} True if the collection contains the Object as a key.
13140 containsKey : function(key){
13141 return typeof this.map[key] != "undefined";
13145 * Removes all items from the collection.
13147 clear : function(){
13152 this.fireEvent("clear");
13156 * Returns the first item in the collection.
13157 * @return {Object} the first item in the collection..
13159 first : function(){
13160 return this.items[0];
13164 * Returns the last item in the collection.
13165 * @return {Object} the last item in the collection..
13168 return this.items[this.length-1];
13171 _sort : function(property, dir, fn){
13172 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13173 fn = fn || function(a, b){
13176 var c = [], k = this.keys, items = this.items;
13177 for(var i = 0, len = items.length; i < len; i++){
13178 c[c.length] = {key: k[i], value: items[i], index: i};
13180 c.sort(function(a, b){
13181 var v = fn(a[property], b[property]) * dsc;
13183 v = (a.index < b.index ? -1 : 1);
13187 for(var i = 0, len = c.length; i < len; i++){
13188 items[i] = c[i].value;
13191 this.fireEvent("sort", this);
13195 * Sorts this collection with the passed comparison function
13196 * @param {String} direction (optional) "ASC" or "DESC"
13197 * @param {Function} fn (optional) comparison function
13199 sort : function(dir, fn){
13200 this._sort("value", dir, fn);
13204 * Sorts this collection by keys
13205 * @param {String} direction (optional) "ASC" or "DESC"
13206 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13208 keySort : function(dir, fn){
13209 this._sort("key", dir, fn || function(a, b){
13210 return String(a).toUpperCase()-String(b).toUpperCase();
13215 * Returns a range of items in this collection
13216 * @param {Number} startIndex (optional) defaults to 0
13217 * @param {Number} endIndex (optional) default to the last item
13218 * @return {Array} An array of items
13220 getRange : function(start, end){
13221 var items = this.items;
13222 if(items.length < 1){
13225 start = start || 0;
13226 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13229 for(var i = start; i <= end; i++) {
13230 r[r.length] = items[i];
13233 for(var i = start; i >= end; i--) {
13234 r[r.length] = items[i];
13241 * Filter the <i>objects</i> in this collection by a specific property.
13242 * Returns a new collection that has been filtered.
13243 * @param {String} property A property on your objects
13244 * @param {String/RegExp} value Either string that the property values
13245 * should start with or a RegExp to test against the property
13246 * @return {MixedCollection} The new filtered collection
13248 filter : function(property, value){
13249 if(!value.exec){ // not a regex
13250 value = String(value);
13251 if(value.length == 0){
13252 return this.clone();
13254 value = new RegExp("^" + Roo.escapeRe(value), "i");
13256 return this.filterBy(function(o){
13257 return o && value.test(o[property]);
13262 * Filter by a function. * Returns a new collection that has been filtered.
13263 * The passed function will be called with each
13264 * object in the collection. If the function returns true, the value is included
13265 * otherwise it is filtered.
13266 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13267 * @param {Object} scope (optional) The scope of the function (defaults to this)
13268 * @return {MixedCollection} The new filtered collection
13270 filterBy : function(fn, scope){
13271 var r = new Roo.util.MixedCollection();
13272 r.getKey = this.getKey;
13273 var k = this.keys, it = this.items;
13274 for(var i = 0, len = it.length; i < len; i++){
13275 if(fn.call(scope||this, it[i], k[i])){
13276 r.add(k[i], it[i]);
13283 * Creates a duplicate of this collection
13284 * @return {MixedCollection}
13286 clone : function(){
13287 var r = new Roo.util.MixedCollection();
13288 var k = this.keys, it = this.items;
13289 for(var i = 0, len = it.length; i < len; i++){
13290 r.add(k[i], it[i]);
13292 r.getKey = this.getKey;
13297 * Returns the item associated with the passed key or index.
13299 * @param {String/Number} key The key or index of the item.
13300 * @return {Object} The item associated with the passed key.
13302 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13304 * Ext JS Library 1.1.1
13305 * Copyright(c) 2006-2007, Ext JS, LLC.
13307 * Originally Released Under LGPL - original licence link has changed is not relivant.
13310 * <script type="text/javascript">
13313 * @class Roo.util.JSON
13314 * Modified version of Douglas Crockford"s json.js that doesn"t
13315 * mess with the Object prototype
13316 * http://www.json.org/js.html
13319 Roo.util.JSON = new (function(){
13320 var useHasOwn = {}.hasOwnProperty ? true : false;
13322 // crashes Safari in some instances
13323 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13325 var pad = function(n) {
13326 return n < 10 ? "0" + n : n;
13339 var encodeString = function(s){
13340 if (/["\\\x00-\x1f]/.test(s)) {
13341 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13346 c = b.charCodeAt();
13348 Math.floor(c / 16).toString(16) +
13349 (c % 16).toString(16);
13352 return '"' + s + '"';
13355 var encodeArray = function(o){
13356 var a = ["["], b, i, l = o.length, v;
13357 for (i = 0; i < l; i += 1) {
13359 switch (typeof v) {
13368 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13376 var encodeDate = function(o){
13377 return '"' + o.getFullYear() + "-" +
13378 pad(o.getMonth() + 1) + "-" +
13379 pad(o.getDate()) + "T" +
13380 pad(o.getHours()) + ":" +
13381 pad(o.getMinutes()) + ":" +
13382 pad(o.getSeconds()) + '"';
13386 * Encodes an Object, Array or other value
13387 * @param {Mixed} o The variable to encode
13388 * @return {String} The JSON string
13390 this.encode = function(o)
13392 // should this be extended to fully wrap stringify..
13394 if(typeof o == "undefined" || o === null){
13396 }else if(o instanceof Array){
13397 return encodeArray(o);
13398 }else if(o instanceof Date){
13399 return encodeDate(o);
13400 }else if(typeof o == "string"){
13401 return encodeString(o);
13402 }else if(typeof o == "number"){
13403 return isFinite(o) ? String(o) : "null";
13404 }else if(typeof o == "boolean"){
13407 var a = ["{"], b, i, v;
13409 if(!useHasOwn || o.hasOwnProperty(i)) {
13411 switch (typeof v) {
13420 a.push(this.encode(i), ":",
13421 v === null ? "null" : this.encode(v));
13432 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13433 * @param {String} json The JSON string
13434 * @return {Object} The resulting object
13436 this.decode = function(json){
13438 return /** eval:var:json */ eval("(" + json + ')');
13442 * Shorthand for {@link Roo.util.JSON#encode}
13443 * @member Roo encode
13445 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13447 * Shorthand for {@link Roo.util.JSON#decode}
13448 * @member Roo decode
13450 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13453 * Ext JS Library 1.1.1
13454 * Copyright(c) 2006-2007, Ext JS, LLC.
13456 * Originally Released Under LGPL - original licence link has changed is not relivant.
13459 * <script type="text/javascript">
13463 * @class Roo.util.Format
13464 * Reusable data formatting functions
13467 Roo.util.Format = function(){
13468 var trimRe = /^\s+|\s+$/g;
13471 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13472 * @param {String} value The string to truncate
13473 * @param {Number} length The maximum length to allow before truncating
13474 * @return {String} The converted text
13476 ellipsis : function(value, len){
13477 if(value && value.length > len){
13478 return value.substr(0, len-3)+"...";
13484 * Checks a reference and converts it to empty string if it is undefined
13485 * @param {Mixed} value Reference to check
13486 * @return {Mixed} Empty string if converted, otherwise the original value
13488 undef : function(value){
13489 return typeof value != "undefined" ? value : "";
13493 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13494 * @param {String} value The string to encode
13495 * @return {String} The encoded text
13497 htmlEncode : function(value){
13498 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13502 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13503 * @param {String} value The string to decode
13504 * @return {String} The decoded text
13506 htmlDecode : function(value){
13507 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13511 * Trims any whitespace from either side of a string
13512 * @param {String} value The text to trim
13513 * @return {String} The trimmed text
13515 trim : function(value){
13516 return String(value).replace(trimRe, "");
13520 * Returns a substring from within an original string
13521 * @param {String} value The original text
13522 * @param {Number} start The start index of the substring
13523 * @param {Number} length The length of the substring
13524 * @return {String} The substring
13526 substr : function(value, start, length){
13527 return String(value).substr(start, length);
13531 * Converts a string to all lower case letters
13532 * @param {String} value The text to convert
13533 * @return {String} The converted text
13535 lowercase : function(value){
13536 return String(value).toLowerCase();
13540 * Converts a string to all upper case letters
13541 * @param {String} value The text to convert
13542 * @return {String} The converted text
13544 uppercase : function(value){
13545 return String(value).toUpperCase();
13549 * Converts the first character only of a string to upper case
13550 * @param {String} value The text to convert
13551 * @return {String} The converted text
13553 capitalize : function(value){
13554 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13558 call : function(value, fn){
13559 if(arguments.length > 2){
13560 var args = Array.prototype.slice.call(arguments, 2);
13561 args.unshift(value);
13563 return /** eval:var:value */ eval(fn).apply(window, args);
13565 /** eval:var:value */
13566 return /** eval:var:value */ eval(fn).call(window, value);
13572 * safer version of Math.toFixed..??/
13573 * @param {Number/String} value The numeric value to format
13574 * @param {Number/String} value Decimal places
13575 * @return {String} The formatted currency string
13577 toFixed : function(v, n)
13579 // why not use to fixed - precision is buggered???
13581 return Math.round(v-0);
13583 var fact = Math.pow(10,n+1);
13584 v = (Math.round((v-0)*fact))/fact;
13585 var z = (''+fact).substring(2);
13586 if (v == Math.floor(v)) {
13587 return Math.floor(v) + '.' + z;
13590 // now just padd decimals..
13591 var ps = String(v).split('.');
13592 var fd = (ps[1] + z);
13593 var r = fd.substring(0,n);
13594 var rm = fd.substring(n);
13596 return ps[0] + '.' + r;
13598 r*=1; // turn it into a number;
13600 if (String(r).length != n) {
13603 r = String(r).substring(1); // chop the end off.
13606 return ps[0] + '.' + r;
13611 * Format a number as US currency
13612 * @param {Number/String} value The numeric value to format
13613 * @return {String} The formatted currency string
13615 usMoney : function(v){
13616 return '$' + Roo.util.Format.number(v);
13621 * eventually this should probably emulate php's number_format
13622 * @param {Number/String} value The numeric value to format
13623 * @param {Number} decimals number of decimal places
13624 * @return {String} The formatted currency string
13626 number : function(v,decimals)
13628 // multiply and round.
13629 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13630 var mul = Math.pow(10, decimals);
13631 var zero = String(mul).substring(1);
13632 v = (Math.round((v-0)*mul))/mul;
13634 // if it's '0' number.. then
13636 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13638 var ps = v.split('.');
13642 var r = /(\d+)(\d{3})/;
13644 while (r.test(whole)) {
13645 whole = whole.replace(r, '$1' + ',' + '$2');
13651 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13652 // does not have decimals
13653 (decimals ? ('.' + zero) : '');
13656 return whole + sub ;
13660 * Parse a value into a formatted date using the specified format pattern.
13661 * @param {Mixed} value The value to format
13662 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13663 * @return {String} The formatted date string
13665 date : function(v, format){
13669 if(!(v instanceof Date)){
13670 v = new Date(Date.parse(v));
13672 return v.dateFormat(format || Roo.util.Format.defaults.date);
13676 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13677 * @param {String} format Any valid date format string
13678 * @return {Function} The date formatting function
13680 dateRenderer : function(format){
13681 return function(v){
13682 return Roo.util.Format.date(v, format);
13687 stripTagsRE : /<\/?[^>]+>/gi,
13690 * Strips all HTML tags
13691 * @param {Mixed} value The text from which to strip tags
13692 * @return {String} The stripped text
13694 stripTags : function(v){
13695 return !v ? v : String(v).replace(this.stripTagsRE, "");
13699 Roo.util.Format.defaults = {
13703 * Ext JS Library 1.1.1
13704 * Copyright(c) 2006-2007, Ext JS, LLC.
13706 * Originally Released Under LGPL - original licence link has changed is not relivant.
13709 * <script type="text/javascript">
13716 * @class Roo.MasterTemplate
13717 * @extends Roo.Template
13718 * Provides a template that can have child templates. The syntax is:
13720 var t = new Roo.MasterTemplate(
13721 '<select name="{name}">',
13722 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13725 t.add('options', {value: 'foo', text: 'bar'});
13726 // or you can add multiple child elements in one shot
13727 t.addAll('options', [
13728 {value: 'foo', text: 'bar'},
13729 {value: 'foo2', text: 'bar2'},
13730 {value: 'foo3', text: 'bar3'}
13732 // then append, applying the master template values
13733 t.append('my-form', {name: 'my-select'});
13735 * A name attribute for the child template is not required if you have only one child
13736 * template or you want to refer to them by index.
13738 Roo.MasterTemplate = function(){
13739 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13740 this.originalHtml = this.html;
13742 var m, re = this.subTemplateRe;
13745 while(m = re.exec(this.html)){
13746 var name = m[1], content = m[2];
13751 tpl : new Roo.Template(content)
13754 st[name] = st[subIndex];
13756 st[subIndex].tpl.compile();
13757 st[subIndex].tpl.call = this.call.createDelegate(this);
13760 this.subCount = subIndex;
13763 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13765 * The regular expression used to match sub templates
13769 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13772 * Applies the passed values to a child template.
13773 * @param {String/Number} name (optional) The name or index of the child template
13774 * @param {Array/Object} values The values to be applied to the template
13775 * @return {MasterTemplate} this
13777 add : function(name, values){
13778 if(arguments.length == 1){
13779 values = arguments[0];
13782 var s = this.subs[name];
13783 s.buffer[s.buffer.length] = s.tpl.apply(values);
13788 * Applies all the passed values to a child template.
13789 * @param {String/Number} name (optional) The name or index of the child template
13790 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13791 * @param {Boolean} reset (optional) True to reset the template first
13792 * @return {MasterTemplate} this
13794 fill : function(name, values, reset){
13796 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13804 for(var i = 0, len = values.length; i < len; i++){
13805 this.add(name, values[i]);
13811 * Resets the template for reuse
13812 * @return {MasterTemplate} this
13814 reset : function(){
13816 for(var i = 0; i < this.subCount; i++){
13822 applyTemplate : function(values){
13824 var replaceIndex = -1;
13825 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13826 return s[++replaceIndex].buffer.join("");
13828 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13831 apply : function(){
13832 return this.applyTemplate.apply(this, arguments);
13835 compile : function(){return this;}
13839 * Alias for fill().
13842 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13844 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13845 * var tpl = Roo.MasterTemplate.from('element-id');
13846 * @param {String/HTMLElement} el
13847 * @param {Object} config
13850 Roo.MasterTemplate.from = function(el, config){
13851 el = Roo.getDom(el);
13852 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13855 * Ext JS Library 1.1.1
13856 * Copyright(c) 2006-2007, Ext JS, LLC.
13858 * Originally Released Under LGPL - original licence link has changed is not relivant.
13861 * <script type="text/javascript">
13866 * @class Roo.util.CSS
13867 * Utility class for manipulating CSS rules
13870 Roo.util.CSS = function(){
13872 var doc = document;
13874 var camelRe = /(-[a-z])/gi;
13875 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13879 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13880 * tag and appended to the HEAD of the document.
13881 * @param {String|Object} cssText The text containing the css rules
13882 * @param {String} id An id to add to the stylesheet for later removal
13883 * @return {StyleSheet}
13885 createStyleSheet : function(cssText, id){
13887 var head = doc.getElementsByTagName("head")[0];
13888 var nrules = doc.createElement("style");
13889 nrules.setAttribute("type", "text/css");
13891 nrules.setAttribute("id", id);
13893 if (typeof(cssText) != 'string') {
13894 // support object maps..
13895 // not sure if this a good idea..
13896 // perhaps it should be merged with the general css handling
13897 // and handle js style props.
13898 var cssTextNew = [];
13899 for(var n in cssText) {
13901 for(var k in cssText[n]) {
13902 citems.push( k + ' : ' +cssText[n][k] + ';' );
13904 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13907 cssText = cssTextNew.join("\n");
13913 head.appendChild(nrules);
13914 ss = nrules.styleSheet;
13915 ss.cssText = cssText;
13918 nrules.appendChild(doc.createTextNode(cssText));
13920 nrules.cssText = cssText;
13922 head.appendChild(nrules);
13923 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13925 this.cacheStyleSheet(ss);
13930 * Removes a style or link tag by id
13931 * @param {String} id The id of the tag
13933 removeStyleSheet : function(id){
13934 var existing = doc.getElementById(id);
13936 existing.parentNode.removeChild(existing);
13941 * Dynamically swaps an existing stylesheet reference for a new one
13942 * @param {String} id The id of an existing link tag to remove
13943 * @param {String} url The href of the new stylesheet to include
13945 swapStyleSheet : function(id, url){
13946 this.removeStyleSheet(id);
13947 var ss = doc.createElement("link");
13948 ss.setAttribute("rel", "stylesheet");
13949 ss.setAttribute("type", "text/css");
13950 ss.setAttribute("id", id);
13951 ss.setAttribute("href", url);
13952 doc.getElementsByTagName("head")[0].appendChild(ss);
13956 * Refresh the rule cache if you have dynamically added stylesheets
13957 * @return {Object} An object (hash) of rules indexed by selector
13959 refreshCache : function(){
13960 return this.getRules(true);
13964 cacheStyleSheet : function(stylesheet){
13968 try{// try catch for cross domain access issue
13969 var ssRules = stylesheet.cssRules || stylesheet.rules;
13970 for(var j = ssRules.length-1; j >= 0; --j){
13971 rules[ssRules[j].selectorText] = ssRules[j];
13977 * Gets all css rules for the document
13978 * @param {Boolean} refreshCache true to refresh the internal cache
13979 * @return {Object} An object (hash) of rules indexed by selector
13981 getRules : function(refreshCache){
13982 if(rules == null || refreshCache){
13984 var ds = doc.styleSheets;
13985 for(var i =0, len = ds.length; i < len; i++){
13987 this.cacheStyleSheet(ds[i]);
13995 * Gets an an individual CSS rule by selector(s)
13996 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13997 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13998 * @return {CSSRule} The CSS rule or null if one is not found
14000 getRule : function(selector, refreshCache){
14001 var rs = this.getRules(refreshCache);
14002 if(!(selector instanceof Array)){
14003 return rs[selector];
14005 for(var i = 0; i < selector.length; i++){
14006 if(rs[selector[i]]){
14007 return rs[selector[i]];
14015 * Updates a rule property
14016 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14017 * @param {String} property The css property
14018 * @param {String} value The new value for the property
14019 * @return {Boolean} true If a rule was found and updated
14021 updateRule : function(selector, property, value){
14022 if(!(selector instanceof Array)){
14023 var rule = this.getRule(selector);
14025 rule.style[property.replace(camelRe, camelFn)] = value;
14029 for(var i = 0; i < selector.length; i++){
14030 if(this.updateRule(selector[i], property, value)){
14040 * Ext JS Library 1.1.1
14041 * Copyright(c) 2006-2007, Ext JS, LLC.
14043 * Originally Released Under LGPL - original licence link has changed is not relivant.
14046 * <script type="text/javascript">
14052 * @class Roo.util.ClickRepeater
14053 * @extends Roo.util.Observable
14055 * A wrapper class which can be applied to any element. Fires a "click" event while the
14056 * mouse is pressed. The interval between firings may be specified in the config but
14057 * defaults to 10 milliseconds.
14059 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14061 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14062 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14063 * Similar to an autorepeat key delay.
14064 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14065 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14066 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14067 * "interval" and "delay" are ignored. "immediate" is honored.
14068 * @cfg {Boolean} preventDefault True to prevent the default click event
14069 * @cfg {Boolean} stopDefault True to stop the default click event
14072 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14073 * 2007-02-02 jvs Renamed to ClickRepeater
14074 * 2007-02-03 jvs Modifications for FF Mac and Safari
14077 * @param {String/HTMLElement/Element} el The element to listen on
14078 * @param {Object} config
14080 Roo.util.ClickRepeater = function(el, config)
14082 this.el = Roo.get(el);
14083 this.el.unselectable();
14085 Roo.apply(this, config);
14090 * Fires when the mouse button is depressed.
14091 * @param {Roo.util.ClickRepeater} this
14093 "mousedown" : true,
14096 * Fires on a specified interval during the time the element is pressed.
14097 * @param {Roo.util.ClickRepeater} this
14102 * Fires when the mouse key is released.
14103 * @param {Roo.util.ClickRepeater} this
14108 this.el.on("mousedown", this.handleMouseDown, this);
14109 if(this.preventDefault || this.stopDefault){
14110 this.el.on("click", function(e){
14111 if(this.preventDefault){
14112 e.preventDefault();
14114 if(this.stopDefault){
14120 // allow inline handler
14122 this.on("click", this.handler, this.scope || this);
14125 Roo.util.ClickRepeater.superclass.constructor.call(this);
14128 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14131 preventDefault : true,
14132 stopDefault : false,
14136 handleMouseDown : function(){
14137 clearTimeout(this.timer);
14139 if(this.pressClass){
14140 this.el.addClass(this.pressClass);
14142 this.mousedownTime = new Date();
14144 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14145 this.el.on("mouseout", this.handleMouseOut, this);
14147 this.fireEvent("mousedown", this);
14148 this.fireEvent("click", this);
14150 this.timer = this.click.defer(this.delay || this.interval, this);
14154 click : function(){
14155 this.fireEvent("click", this);
14156 this.timer = this.click.defer(this.getInterval(), this);
14160 getInterval: function(){
14161 if(!this.accelerate){
14162 return this.interval;
14164 var pressTime = this.mousedownTime.getElapsed();
14165 if(pressTime < 500){
14167 }else if(pressTime < 1700){
14169 }else if(pressTime < 2600){
14171 }else if(pressTime < 3500){
14173 }else if(pressTime < 4400){
14175 }else if(pressTime < 5300){
14177 }else if(pressTime < 6200){
14185 handleMouseOut : function(){
14186 clearTimeout(this.timer);
14187 if(this.pressClass){
14188 this.el.removeClass(this.pressClass);
14190 this.el.on("mouseover", this.handleMouseReturn, this);
14194 handleMouseReturn : function(){
14195 this.el.un("mouseover", this.handleMouseReturn);
14196 if(this.pressClass){
14197 this.el.addClass(this.pressClass);
14203 handleMouseUp : function(){
14204 clearTimeout(this.timer);
14205 this.el.un("mouseover", this.handleMouseReturn);
14206 this.el.un("mouseout", this.handleMouseOut);
14207 Roo.get(document).un("mouseup", this.handleMouseUp);
14208 this.el.removeClass(this.pressClass);
14209 this.fireEvent("mouseup", this);
14213 * Ext JS Library 1.1.1
14214 * Copyright(c) 2006-2007, Ext JS, LLC.
14216 * Originally Released Under LGPL - original licence link has changed is not relivant.
14219 * <script type="text/javascript">
14224 * @class Roo.KeyNav
14225 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14226 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14227 * way to implement custom navigation schemes for any UI component.</p>
14228 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14229 * pageUp, pageDown, del, home, end. Usage:</p>
14231 var nav = new Roo.KeyNav("my-element", {
14232 "left" : function(e){
14233 this.moveLeft(e.ctrlKey);
14235 "right" : function(e){
14236 this.moveRight(e.ctrlKey);
14238 "enter" : function(e){
14245 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14246 * @param {Object} config The config
14248 Roo.KeyNav = function(el, config){
14249 this.el = Roo.get(el);
14250 Roo.apply(this, config);
14251 if(!this.disabled){
14252 this.disabled = true;
14257 Roo.KeyNav.prototype = {
14259 * @cfg {Boolean} disabled
14260 * True to disable this KeyNav instance (defaults to false)
14264 * @cfg {String} defaultEventAction
14265 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14266 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14267 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14269 defaultEventAction: "stopEvent",
14271 * @cfg {Boolean} forceKeyDown
14272 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14273 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14274 * handle keydown instead of keypress.
14276 forceKeyDown : false,
14279 prepareEvent : function(e){
14280 var k = e.getKey();
14281 var h = this.keyToHandler[k];
14282 //if(h && this[h]){
14283 // e.stopPropagation();
14285 if(Roo.isSafari && h && k >= 37 && k <= 40){
14291 relay : function(e){
14292 var k = e.getKey();
14293 var h = this.keyToHandler[k];
14295 if(this.doRelay(e, this[h], h) !== true){
14296 e[this.defaultEventAction]();
14302 doRelay : function(e, h, hname){
14303 return h.call(this.scope || this, e);
14306 // possible handlers
14320 // quick lookup hash
14337 * Enable this KeyNav
14339 enable: function(){
14341 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14342 // the EventObject will normalize Safari automatically
14343 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14344 this.el.on("keydown", this.relay, this);
14346 this.el.on("keydown", this.prepareEvent, this);
14347 this.el.on("keypress", this.relay, this);
14349 this.disabled = false;
14354 * Disable this KeyNav
14356 disable: function(){
14357 if(!this.disabled){
14358 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14359 this.el.un("keydown", this.relay);
14361 this.el.un("keydown", this.prepareEvent);
14362 this.el.un("keypress", this.relay);
14364 this.disabled = true;
14369 * Ext JS Library 1.1.1
14370 * Copyright(c) 2006-2007, Ext JS, LLC.
14372 * Originally Released Under LGPL - original licence link has changed is not relivant.
14375 * <script type="text/javascript">
14380 * @class Roo.KeyMap
14381 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14382 * The constructor accepts the same config object as defined by {@link #addBinding}.
14383 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14384 * combination it will call the function with this signature (if the match is a multi-key
14385 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14386 * A KeyMap can also handle a string representation of keys.<br />
14389 // map one key by key code
14390 var map = new Roo.KeyMap("my-element", {
14391 key: 13, // or Roo.EventObject.ENTER
14396 // map multiple keys to one action by string
14397 var map = new Roo.KeyMap("my-element", {
14403 // map multiple keys to multiple actions by strings and array of codes
14404 var map = new Roo.KeyMap("my-element", [
14407 fn: function(){ alert("Return was pressed"); }
14410 fn: function(){ alert('a, b or c was pressed'); }
14415 fn: function(){ alert('Control + shift + tab was pressed.'); }
14419 * <b>Note: A KeyMap starts enabled</b>
14421 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14422 * @param {Object} config The config (see {@link #addBinding})
14423 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14425 Roo.KeyMap = function(el, config, eventName){
14426 this.el = Roo.get(el);
14427 this.eventName = eventName || "keydown";
14428 this.bindings = [];
14430 this.addBinding(config);
14435 Roo.KeyMap.prototype = {
14437 * True to stop the event from bubbling and prevent the default browser action if the
14438 * key was handled by the KeyMap (defaults to false)
14444 * Add a new binding to this KeyMap. The following config object properties are supported:
14446 Property Type Description
14447 ---------- --------------- ----------------------------------------------------------------------
14448 key String/Array A single keycode or an array of keycodes to handle
14449 shift Boolean True to handle key only when shift is pressed (defaults to false)
14450 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14451 alt Boolean True to handle key only when alt is pressed (defaults to false)
14452 fn Function The function to call when KeyMap finds the expected key combination
14453 scope Object The scope of the callback function
14459 var map = new Roo.KeyMap(document, {
14460 key: Roo.EventObject.ENTER,
14465 //Add a new binding to the existing KeyMap later
14473 * @param {Object/Array} config A single KeyMap config or an array of configs
14475 addBinding : function(config){
14476 if(config instanceof Array){
14477 for(var i = 0, len = config.length; i < len; i++){
14478 this.addBinding(config[i]);
14482 var keyCode = config.key,
14483 shift = config.shift,
14484 ctrl = config.ctrl,
14487 scope = config.scope;
14488 if(typeof keyCode == "string"){
14490 var keyString = keyCode.toUpperCase();
14491 for(var j = 0, len = keyString.length; j < len; j++){
14492 ks.push(keyString.charCodeAt(j));
14496 var keyArray = keyCode instanceof Array;
14497 var handler = function(e){
14498 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14499 var k = e.getKey();
14501 for(var i = 0, len = keyCode.length; i < len; i++){
14502 if(keyCode[i] == k){
14503 if(this.stopEvent){
14506 fn.call(scope || window, k, e);
14512 if(this.stopEvent){
14515 fn.call(scope || window, k, e);
14520 this.bindings.push(handler);
14524 * Shorthand for adding a single key listener
14525 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14526 * following options:
14527 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14528 * @param {Function} fn The function to call
14529 * @param {Object} scope (optional) The scope of the function
14531 on : function(key, fn, scope){
14532 var keyCode, shift, ctrl, alt;
14533 if(typeof key == "object" && !(key instanceof Array)){
14552 handleKeyDown : function(e){
14553 if(this.enabled){ //just in case
14554 var b = this.bindings;
14555 for(var i = 0, len = b.length; i < len; i++){
14556 b[i].call(this, e);
14562 * Returns true if this KeyMap is enabled
14563 * @return {Boolean}
14565 isEnabled : function(){
14566 return this.enabled;
14570 * Enables this KeyMap
14572 enable: function(){
14574 this.el.on(this.eventName, this.handleKeyDown, this);
14575 this.enabled = true;
14580 * Disable this KeyMap
14582 disable: function(){
14584 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14585 this.enabled = false;
14590 * Ext JS Library 1.1.1
14591 * Copyright(c) 2006-2007, Ext JS, LLC.
14593 * Originally Released Under LGPL - original licence link has changed is not relivant.
14596 * <script type="text/javascript">
14601 * @class Roo.util.TextMetrics
14602 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14603 * wide, in pixels, a given block of text will be.
14606 Roo.util.TextMetrics = function(){
14610 * Measures the size of the specified text
14611 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14612 * that can affect the size of the rendered text
14613 * @param {String} text The text to measure
14614 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14615 * in order to accurately measure the text height
14616 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14618 measure : function(el, text, fixedWidth){
14620 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14623 shared.setFixedWidth(fixedWidth || 'auto');
14624 return shared.getSize(text);
14628 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14629 * the overhead of multiple calls to initialize the style properties on each measurement.
14630 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14631 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14632 * in order to accurately measure the text height
14633 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14635 createInstance : function(el, fixedWidth){
14636 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14643 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14644 var ml = new Roo.Element(document.createElement('div'));
14645 document.body.appendChild(ml.dom);
14646 ml.position('absolute');
14647 ml.setLeftTop(-1000, -1000);
14651 ml.setWidth(fixedWidth);
14656 * Returns the size of the specified text based on the internal element's style and width properties
14657 * @memberOf Roo.util.TextMetrics.Instance#
14658 * @param {String} text The text to measure
14659 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14661 getSize : function(text){
14663 var s = ml.getSize();
14669 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14670 * that can affect the size of the rendered text
14671 * @memberOf Roo.util.TextMetrics.Instance#
14672 * @param {String/HTMLElement} el The element, dom node or id
14674 bind : function(el){
14676 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14681 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14682 * to set a fixed width in order to accurately measure the text height.
14683 * @memberOf Roo.util.TextMetrics.Instance#
14684 * @param {Number} width The width to set on the element
14686 setFixedWidth : function(width){
14687 ml.setWidth(width);
14691 * Returns the measured width of the specified text
14692 * @memberOf Roo.util.TextMetrics.Instance#
14693 * @param {String} text The text to measure
14694 * @return {Number} width The width in pixels
14696 getWidth : function(text){
14697 ml.dom.style.width = 'auto';
14698 return this.getSize(text).width;
14702 * Returns the measured height of the specified text. For multiline text, be sure to call
14703 * {@link #setFixedWidth} if necessary.
14704 * @memberOf Roo.util.TextMetrics.Instance#
14705 * @param {String} text The text to measure
14706 * @return {Number} height The height in pixels
14708 getHeight : function(text){
14709 return this.getSize(text).height;
14713 instance.bind(bindTo);
14718 // backwards compat
14719 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14721 * Ext JS Library 1.1.1
14722 * Copyright(c) 2006-2007, Ext JS, LLC.
14724 * Originally Released Under LGPL - original licence link has changed is not relivant.
14727 * <script type="text/javascript">
14731 * @class Roo.state.Provider
14732 * Abstract base class for state provider implementations. This class provides methods
14733 * for encoding and decoding <b>typed</b> variables including dates and defines the
14734 * Provider interface.
14736 Roo.state.Provider = function(){
14738 * @event statechange
14739 * Fires when a state change occurs.
14740 * @param {Provider} this This state provider
14741 * @param {String} key The state key which was changed
14742 * @param {String} value The encoded value for the state
14745 "statechange": true
14748 Roo.state.Provider.superclass.constructor.call(this);
14750 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14752 * Returns the current value for a key
14753 * @param {String} name The key name
14754 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14755 * @return {Mixed} The state data
14757 get : function(name, defaultValue){
14758 return typeof this.state[name] == "undefined" ?
14759 defaultValue : this.state[name];
14763 * Clears a value from the state
14764 * @param {String} name The key name
14766 clear : function(name){
14767 delete this.state[name];
14768 this.fireEvent("statechange", this, name, null);
14772 * Sets the value for a key
14773 * @param {String} name The key name
14774 * @param {Mixed} value The value to set
14776 set : function(name, value){
14777 this.state[name] = value;
14778 this.fireEvent("statechange", this, name, value);
14782 * Decodes a string previously encoded with {@link #encodeValue}.
14783 * @param {String} value The value to decode
14784 * @return {Mixed} The decoded value
14786 decodeValue : function(cookie){
14787 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14788 var matches = re.exec(unescape(cookie));
14789 if(!matches || !matches[1]) return; // non state cookie
14790 var type = matches[1];
14791 var v = matches[2];
14794 return parseFloat(v);
14796 return new Date(Date.parse(v));
14801 var values = v.split("^");
14802 for(var i = 0, len = values.length; i < len; i++){
14803 all.push(this.decodeValue(values[i]));
14808 var values = v.split("^");
14809 for(var i = 0, len = values.length; i < len; i++){
14810 var kv = values[i].split("=");
14811 all[kv[0]] = this.decodeValue(kv[1]);
14820 * Encodes a value including type information. Decode with {@link #decodeValue}.
14821 * @param {Mixed} value The value to encode
14822 * @return {String} The encoded value
14824 encodeValue : function(v){
14826 if(typeof v == "number"){
14828 }else if(typeof v == "boolean"){
14829 enc = "b:" + (v ? "1" : "0");
14830 }else if(v instanceof Date){
14831 enc = "d:" + v.toGMTString();
14832 }else if(v instanceof Array){
14834 for(var i = 0, len = v.length; i < len; i++){
14835 flat += this.encodeValue(v[i]);
14836 if(i != len-1) flat += "^";
14839 }else if(typeof v == "object"){
14842 if(typeof v[key] != "function"){
14843 flat += key + "=" + this.encodeValue(v[key]) + "^";
14846 enc = "o:" + flat.substring(0, flat.length-1);
14850 return escape(enc);
14856 * Ext JS Library 1.1.1
14857 * Copyright(c) 2006-2007, Ext JS, LLC.
14859 * Originally Released Under LGPL - original licence link has changed is not relivant.
14862 * <script type="text/javascript">
14865 * @class Roo.state.Manager
14866 * This is the global state manager. By default all components that are "state aware" check this class
14867 * for state information if you don't pass them a custom state provider. In order for this class
14868 * to be useful, it must be initialized with a provider when your application initializes.
14870 // in your initialization function
14872 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14874 // supposed you have a {@link Roo.BorderLayout}
14875 var layout = new Roo.BorderLayout(...);
14876 layout.restoreState();
14877 // or a {Roo.BasicDialog}
14878 var dialog = new Roo.BasicDialog(...);
14879 dialog.restoreState();
14883 Roo.state.Manager = function(){
14884 var provider = new Roo.state.Provider();
14888 * Configures the default state provider for your application
14889 * @param {Provider} stateProvider The state provider to set
14891 setProvider : function(stateProvider){
14892 provider = stateProvider;
14896 * Returns the current value for a key
14897 * @param {String} name The key name
14898 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14899 * @return {Mixed} The state data
14901 get : function(key, defaultValue){
14902 return provider.get(key, defaultValue);
14906 * Sets the value for a key
14907 * @param {String} name The key name
14908 * @param {Mixed} value The state data
14910 set : function(key, value){
14911 provider.set(key, value);
14915 * Clears a value from the state
14916 * @param {String} name The key name
14918 clear : function(key){
14919 provider.clear(key);
14923 * Gets the currently configured state provider
14924 * @return {Provider} The state provider
14926 getProvider : function(){
14933 * Ext JS Library 1.1.1
14934 * Copyright(c) 2006-2007, Ext JS, LLC.
14936 * Originally Released Under LGPL - original licence link has changed is not relivant.
14939 * <script type="text/javascript">
14942 * @class Roo.state.CookieProvider
14943 * @extends Roo.state.Provider
14944 * The default Provider implementation which saves state via cookies.
14947 var cp = new Roo.state.CookieProvider({
14949 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14950 domain: "roojs.com"
14952 Roo.state.Manager.setProvider(cp);
14954 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14955 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14956 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14957 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14958 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14959 * domain the page is running on including the 'www' like 'www.roojs.com')
14960 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14962 * Create a new CookieProvider
14963 * @param {Object} config The configuration object
14965 Roo.state.CookieProvider = function(config){
14966 Roo.state.CookieProvider.superclass.constructor.call(this);
14968 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14969 this.domain = null;
14970 this.secure = false;
14971 Roo.apply(this, config);
14972 this.state = this.readCookies();
14975 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14977 set : function(name, value){
14978 if(typeof value == "undefined" || value === null){
14982 this.setCookie(name, value);
14983 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14987 clear : function(name){
14988 this.clearCookie(name);
14989 Roo.state.CookieProvider.superclass.clear.call(this, name);
14993 readCookies : function(){
14995 var c = document.cookie + ";";
14996 var re = /\s?(.*?)=(.*?);/g;
14998 while((matches = re.exec(c)) != null){
14999 var name = matches[1];
15000 var value = matches[2];
15001 if(name && name.substring(0,3) == "ys-"){
15002 cookies[name.substr(3)] = this.decodeValue(value);
15009 setCookie : function(name, value){
15010 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15011 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15012 ((this.path == null) ? "" : ("; path=" + this.path)) +
15013 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15014 ((this.secure == true) ? "; secure" : "");
15018 clearCookie : function(name){
15019 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15020 ((this.path == null) ? "" : ("; path=" + this.path)) +
15021 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15022 ((this.secure == true) ? "; secure" : "");
15026 * Ext JS Library 1.1.1
15027 * Copyright(c) 2006-2007, Ext JS, LLC.
15029 * Originally Released Under LGPL - original licence link has changed is not relivant.
15032 * <script type="text/javascript">
15037 * @class Roo.ComponentMgr
15038 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15041 Roo.ComponentMgr = function(){
15042 var all = new Roo.util.MixedCollection();
15046 * Registers a component.
15047 * @param {Roo.Component} c The component
15049 register : function(c){
15054 * Unregisters a component.
15055 * @param {Roo.Component} c The component
15057 unregister : function(c){
15062 * Returns a component by id
15063 * @param {String} id The component id
15065 get : function(id){
15066 return all.get(id);
15070 * Registers a function that will be called when a specified component is added to ComponentMgr
15071 * @param {String} id The component id
15072 * @param {Funtction} fn The callback function
15073 * @param {Object} scope The scope of the callback
15075 onAvailable : function(id, fn, scope){
15076 all.on("add", function(index, o){
15078 fn.call(scope || o, o);
15079 all.un("add", fn, scope);
15086 * Ext JS Library 1.1.1
15087 * Copyright(c) 2006-2007, Ext JS, LLC.
15089 * Originally Released Under LGPL - original licence link has changed is not relivant.
15092 * <script type="text/javascript">
15096 * @class Roo.Component
15097 * @extends Roo.util.Observable
15098 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15099 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15100 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15101 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15102 * All visual components (widgets) that require rendering into a layout should subclass Component.
15104 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15105 * element and its id used as the component id. If a string is passed, it is assumed to be the id of an existing element
15106 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15108 Roo.Component = function(config){
15109 config = config || {};
15110 if(config.tagName || config.dom || typeof config == "string"){ // element object
15111 config = {el: config, id: config.id || config};
15113 this.initialConfig = config;
15115 Roo.apply(this, config);
15119 * Fires after the component is disabled.
15120 * @param {Roo.Component} this
15125 * Fires after the component is enabled.
15126 * @param {Roo.Component} this
15130 * @event beforeshow
15131 * Fires before the component is shown. Return false to stop the show.
15132 * @param {Roo.Component} this
15137 * Fires after the component is shown.
15138 * @param {Roo.Component} this
15142 * @event beforehide
15143 * Fires before the component is hidden. Return false to stop the hide.
15144 * @param {Roo.Component} this
15149 * Fires after the component is hidden.
15150 * @param {Roo.Component} this
15154 * @event beforerender
15155 * Fires before the component is rendered. Return false to stop the render.
15156 * @param {Roo.Component} this
15158 beforerender : true,
15161 * Fires after the component is rendered.
15162 * @param {Roo.Component} this
15166 * @event beforedestroy
15167 * Fires before the component is destroyed. Return false to stop the destroy.
15168 * @param {Roo.Component} this
15170 beforedestroy : true,
15173 * Fires after the component is destroyed.
15174 * @param {Roo.Component} this
15179 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
15181 Roo.ComponentMgr.register(this);
15182 Roo.Component.superclass.constructor.call(this);
15183 this.initComponent();
15184 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15185 this.render(this.renderTo);
15186 delete this.renderTo;
15191 Roo.Component.AUTO_ID = 1000;
15193 Roo.extend(Roo.Component, Roo.util.Observable, {
15195 * @scope Roo.Component.prototype
15197 * true if this component is hidden. Read-only.
15202 * true if this component is disabled. Read-only.
15207 * true if this component has been rendered. Read-only.
15211 /** @cfg {String} disableClass
15212 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15214 disabledClass : "x-item-disabled",
15215 /** @cfg {Boolean} allowDomMove
15216 * Whether the component can move the Dom node when rendering (defaults to true).
15218 allowDomMove : true,
15219 /** @cfg {String} hideMode (display|visibility)
15220 * How this component should hidden. Supported values are
15221 * "visibility" (css visibility), "offsets" (negative offset position) and
15222 * "display" (css display) - defaults to "display".
15224 hideMode: 'display',
15227 ctype : "Roo.Component",
15230 * @cfg {String} actionMode
15231 * which property holds the element that used for hide() / show() / disable() / enable()
15237 getActionEl : function(){
15238 return this[this.actionMode];
15241 initComponent : Roo.emptyFn,
15243 * If this is a lazy rendering component, render it to its container element.
15244 * @param {String/HTMLElement/Element} container (optional) The element this component should be rendered into. If it is being applied to existing markup, this should be left off.
15246 render : function(container, position){
15247 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15248 if(!container && this.el){
15249 this.el = Roo.get(this.el);
15250 container = this.el.dom.parentNode;
15251 this.allowDomMove = false;
15253 this.container = Roo.get(container);
15254 this.rendered = true;
15255 if(position !== undefined){
15256 if(typeof position == 'number'){
15257 position = this.container.dom.childNodes[position];
15259 position = Roo.getDom(position);
15262 this.onRender(this.container, position || null);
15264 this.el.addClass(this.cls);
15268 this.el.applyStyles(this.style);
15271 this.fireEvent("render", this);
15272 this.afterRender(this.container);
15284 // default function is not really useful
15285 onRender : function(ct, position){
15287 this.el = Roo.get(this.el);
15288 if(this.allowDomMove !== false){
15289 ct.dom.insertBefore(this.el.dom, position);
15295 getAutoCreate : function(){
15296 var cfg = typeof this.autoCreate == "object" ?
15297 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15298 if(this.id && !cfg.id){
15305 afterRender : Roo.emptyFn,
15308 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15309 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15311 destroy : function(){
15312 if(this.fireEvent("beforedestroy", this) !== false){
15313 this.purgeListeners();
15314 this.beforeDestroy();
15316 this.el.removeAllListeners();
15318 if(this.actionMode == "container"){
15319 this.container.remove();
15323 Roo.ComponentMgr.unregister(this);
15324 this.fireEvent("destroy", this);
15329 beforeDestroy : function(){
15334 onDestroy : function(){
15339 * Returns the underlying {@link Roo.Element}.
15340 * @return {Roo.Element} The element
15342 getEl : function(){
15347 * Returns the id of this component.
15350 getId : function(){
15355 * Try to focus this component.
15356 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15357 * @return {Roo.Component} this
15359 focus : function(selectText){
15362 if(selectText === true){
15363 this.el.dom.select();
15378 * Disable this component.
15379 * @return {Roo.Component} this
15381 disable : function(){
15385 this.disabled = true;
15386 this.fireEvent("disable", this);
15391 onDisable : function(){
15392 this.getActionEl().addClass(this.disabledClass);
15393 this.el.dom.disabled = true;
15397 * Enable this component.
15398 * @return {Roo.Component} this
15400 enable : function(){
15404 this.disabled = false;
15405 this.fireEvent("enable", this);
15410 onEnable : function(){
15411 this.getActionEl().removeClass(this.disabledClass);
15412 this.el.dom.disabled = false;
15416 * Convenience function for setting disabled/enabled by boolean.
15417 * @param {Boolean} disabled
15419 setDisabled : function(disabled){
15420 this[disabled ? "disable" : "enable"]();
15424 * Show this component.
15425 * @return {Roo.Component} this
15428 if(this.fireEvent("beforeshow", this) !== false){
15429 this.hidden = false;
15433 this.fireEvent("show", this);
15439 onShow : function(){
15440 var ae = this.getActionEl();
15441 if(this.hideMode == 'visibility'){
15442 ae.dom.style.visibility = "visible";
15443 }else if(this.hideMode == 'offsets'){
15444 ae.removeClass('x-hidden');
15446 ae.dom.style.display = "";
15451 * Hide this component.
15452 * @return {Roo.Component} this
15455 if(this.fireEvent("beforehide", this) !== false){
15456 this.hidden = true;
15460 this.fireEvent("hide", this);
15466 onHide : function(){
15467 var ae = this.getActionEl();
15468 if(this.hideMode == 'visibility'){
15469 ae.dom.style.visibility = "hidden";
15470 }else if(this.hideMode == 'offsets'){
15471 ae.addClass('x-hidden');
15473 ae.dom.style.display = "none";
15478 * Convenience function to hide or show this component by boolean.
15479 * @param {Boolean} visible True to show, false to hide
15480 * @return {Roo.Component} this
15482 setVisible: function(visible){
15492 * Returns true if this component is visible.
15494 isVisible : function(){
15495 return this.getActionEl().isVisible();
15498 cloneConfig : function(overrides){
15499 overrides = overrides || {};
15500 var id = overrides.id || Roo.id();
15501 var cfg = Roo.applyIf(overrides, this.initialConfig);
15502 cfg.id = id; // prevent dup id
15503 return new this.constructor(cfg);
15507 * Ext JS Library 1.1.1
15508 * Copyright(c) 2006-2007, Ext JS, LLC.
15510 * Originally Released Under LGPL - original licence link has changed is not relivant.
15513 * <script type="text/javascript">
15517 * @class Roo.BoxComponent
15518 * @extends Roo.Component
15519 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15520 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15521 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15522 * layout containers.
15524 * @param {Roo.Element/String/Object} config The configuration options.
15526 Roo.BoxComponent = function(config){
15527 Roo.Component.call(this, config);
15531 * Fires after the component is resized.
15532 * @param {Roo.Component} this
15533 * @param {Number} adjWidth The box-adjusted width that was set
15534 * @param {Number} adjHeight The box-adjusted height that was set
15535 * @param {Number} rawWidth The width that was originally specified
15536 * @param {Number} rawHeight The height that was originally specified
15541 * Fires after the component is moved.
15542 * @param {Roo.Component} this
15543 * @param {Number} x The new x position
15544 * @param {Number} y The new y position
15550 Roo.extend(Roo.BoxComponent, Roo.Component, {
15551 // private, set in afterRender to signify that the component has been rendered
15553 // private, used to defer height settings to subclasses
15554 deferHeight: false,
15555 /** @cfg {Number} width
15556 * width (optional) size of component
15558 /** @cfg {Number} height
15559 * height (optional) size of component
15563 * Sets the width and height of the component. This method fires the resize event. This method can accept
15564 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15565 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15566 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15567 * @return {Roo.BoxComponent} this
15569 setSize : function(w, h){
15570 // support for standard size objects
15571 if(typeof w == 'object'){
15576 if(!this.boxReady){
15582 // prevent recalcs when not needed
15583 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15586 this.lastSize = {width: w, height: h};
15588 var adj = this.adjustSize(w, h);
15589 var aw = adj.width, ah = adj.height;
15590 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15591 var rz = this.getResizeEl();
15592 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15593 rz.setSize(aw, ah);
15594 }else if(!this.deferHeight && ah !== undefined){
15596 }else if(aw !== undefined){
15599 this.onResize(aw, ah, w, h);
15600 this.fireEvent('resize', this, aw, ah, w, h);
15606 * Gets the current size of the component's underlying element.
15607 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15609 getSize : function(){
15610 return this.el.getSize();
15614 * Gets the current XY position of the component's underlying element.
15615 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15616 * @return {Array} The XY position of the element (e.g., [100, 200])
15618 getPosition : function(local){
15619 if(local === true){
15620 return [this.el.getLeft(true), this.el.getTop(true)];
15622 return this.xy || this.el.getXY();
15626 * Gets the current box measurements of the component's underlying element.
15627 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15628 * @returns {Object} box An object in the format {x, y, width, height}
15630 getBox : function(local){
15631 var s = this.el.getSize();
15633 s.x = this.el.getLeft(true);
15634 s.y = this.el.getTop(true);
15636 var xy = this.xy || this.el.getXY();
15644 * Sets the current box measurements of the component's underlying element.
15645 * @param {Object} box An object in the format {x, y, width, height}
15646 * @returns {Roo.BoxComponent} this
15648 updateBox : function(box){
15649 this.setSize(box.width, box.height);
15650 this.setPagePosition(box.x, box.y);
15655 getResizeEl : function(){
15656 return this.resizeEl || this.el;
15660 getPositionEl : function(){
15661 return this.positionEl || this.el;
15665 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15666 * This method fires the move event.
15667 * @param {Number} left The new left
15668 * @param {Number} top The new top
15669 * @returns {Roo.BoxComponent} this
15671 setPosition : function(x, y){
15674 if(!this.boxReady){
15677 var adj = this.adjustPosition(x, y);
15678 var ax = adj.x, ay = adj.y;
15680 var el = this.getPositionEl();
15681 if(ax !== undefined || ay !== undefined){
15682 if(ax !== undefined && ay !== undefined){
15683 el.setLeftTop(ax, ay);
15684 }else if(ax !== undefined){
15686 }else if(ay !== undefined){
15689 this.onPosition(ax, ay);
15690 this.fireEvent('move', this, ax, ay);
15696 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15697 * This method fires the move event.
15698 * @param {Number} x The new x position
15699 * @param {Number} y The new y position
15700 * @returns {Roo.BoxComponent} this
15702 setPagePosition : function(x, y){
15705 if(!this.boxReady){
15708 if(x === undefined || y === undefined){ // cannot translate undefined points
15711 var p = this.el.translatePoints(x, y);
15712 this.setPosition(p.left, p.top);
15717 onRender : function(ct, position){
15718 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15720 this.resizeEl = Roo.get(this.resizeEl);
15722 if(this.positionEl){
15723 this.positionEl = Roo.get(this.positionEl);
15728 afterRender : function(){
15729 Roo.BoxComponent.superclass.afterRender.call(this);
15730 this.boxReady = true;
15731 this.setSize(this.width, this.height);
15732 if(this.x || this.y){
15733 this.setPosition(this.x, this.y);
15735 if(this.pageX || this.pageY){
15736 this.setPagePosition(this.pageX, this.pageY);
15741 * Force the component's size to recalculate based on the underlying element's current height and width.
15742 * @returns {Roo.BoxComponent} this
15744 syncSize : function(){
15745 delete this.lastSize;
15746 this.setSize(this.el.getWidth(), this.el.getHeight());
15751 * Called after the component is resized, this method is empty by default but can be implemented by any
15752 * subclass that needs to perform custom logic after a resize occurs.
15753 * @param {Number} adjWidth The box-adjusted width that was set
15754 * @param {Number} adjHeight The box-adjusted height that was set
15755 * @param {Number} rawWidth The width that was originally specified
15756 * @param {Number} rawHeight The height that was originally specified
15758 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15763 * Called after the component is moved, this method is empty by default but can be implemented by any
15764 * subclass that needs to perform custom logic after a move occurs.
15765 * @param {Number} x The new x position
15766 * @param {Number} y The new y position
15768 onPosition : function(x, y){
15773 adjustSize : function(w, h){
15774 if(this.autoWidth){
15777 if(this.autoHeight){
15780 return {width : w, height: h};
15784 adjustPosition : function(x, y){
15785 return {x : x, y: y};
15788 * Original code for Roojs - LGPL
15789 * <script type="text/javascript">
15793 * @class Roo.XComponent
15794 * A delayed Element creator...
15795 * Or a way to group chunks of interface together.
15796 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15797 * used in conjunction with XComponent.build() it will create an instance of each element,
15798 * then call addxtype() to build the User interface.
15800 * Mypart.xyx = new Roo.XComponent({
15802 parent : 'Mypart.xyz', // empty == document.element.!!
15806 disabled : function() {}
15808 tree : function() { // return an tree of xtype declared components
15812 xtype : 'NestedLayoutPanel',
15819 * It can be used to build a big heiracy, with parent etc.
15820 * or you can just use this to render a single compoent to a dom element
15821 * MYPART.render(Roo.Element | String(id) | dom_element )
15828 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15829 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15831 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15833 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15834 * - if mulitple topModules exist, the last one is defined as the top module.
15838 * When the top level or multiple modules are to embedded into a existing HTML page,
15839 * the parent element can container '#id' of the element where the module will be drawn.
15843 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15844 * it relies more on a include mechanism, where sub modules are included into an outer page.
15845 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15847 * Bootstrap Roo Included elements
15849 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15850 * hence confusing the component builder as it thinks there are multiple top level elements.
15854 * @extends Roo.util.Observable
15856 * @param cfg {Object} configuration of component
15859 Roo.XComponent = function(cfg) {
15860 Roo.apply(this, cfg);
15864 * Fires when this the componnt is built
15865 * @param {Roo.XComponent} c the component
15870 this.region = this.region || 'center'; // default..
15871 Roo.XComponent.register(this);
15872 this.modules = false;
15873 this.el = false; // where the layout goes..
15877 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15880 * The created element (with Roo.factory())
15881 * @type {Roo.Layout}
15887 * for BC - use el in new code
15888 * @type {Roo.Layout}
15894 * for BC - use el in new code
15895 * @type {Roo.Layout}
15900 * @cfg {Function|boolean} disabled
15901 * If this module is disabled by some rule, return true from the funtion
15906 * @cfg {String} parent
15907 * Name of parent element which it get xtype added to..
15912 * @cfg {String} order
15913 * Used to set the order in which elements are created (usefull for multiple tabs)
15918 * @cfg {String} name
15919 * String to display while loading.
15923 * @cfg {String} region
15924 * Region to render component to (defaults to center)
15929 * @cfg {Array} items
15930 * A single item array - the first element is the root of the tree..
15931 * It's done this way to stay compatible with the Xtype system...
15937 * The method that retuns the tree of parts that make up this compoennt
15944 * render element to dom or tree
15945 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
15948 render : function(el)
15952 var hp = this.parent ? 1 : 0;
15953 Roo.debug && Roo.log(this);
15955 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
15956 // if parent is a '#.....' string, then let's use that..
15957 var ename = this.parent.substr(1);
15958 this.parent = false;
15959 Roo.debug && Roo.log(ename);
15961 case 'bootstrap-body' :
15962 if (typeof(Roo.bootstrap.Body) != 'undefined') {
15963 this.parent = { el : new Roo.bootstrap.Body() };
15964 Roo.debug && Roo.log("setting el to doc body");
15967 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
15971 this.parent = { el : true};
15974 el = Roo.get(ename);
15979 if (!el && !this.parent) {
15980 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
15984 Roo.debug && Roo.log("EL:");
15985 Roo.debug && Roo.log(el);
15986 Roo.debug && Roo.log("this.parent.el:");
15987 Roo.debug && Roo.log(this.parent.el);
15989 var tree = this._tree ? this._tree() : this.tree();
15991 // altertive root elements ??? - we need a better way to indicate these.
15992 var is_alt = (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
15993 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
15995 if (!this.parent && is_alt) {
15996 //el = Roo.get(document.body);
15997 this.parent = { el : true };
16002 if (!this.parent) {
16004 Roo.debug && Roo.log("no parent - creating one");
16006 el = el ? Roo.get(el) : false;
16008 // it's a top level one..
16010 el : new Roo.BorderLayout(el || document.body, {
16016 tabPosition: 'top',
16017 //resizeTabs: true,
16018 alwaysShowTabs: el && hp? false : true,
16019 hideTabs: el || !hp ? true : false,
16026 if (!this.parent.el) {
16027 // probably an old style ctor, which has been disabled.
16031 // The 'tree' method is '_tree now'
16033 tree.region = tree.region || this.region;
16035 if (this.parent.el === true) {
16036 // bootstrap... - body..
16037 this.parent.el = Roo.factory(tree);
16040 this.el = this.parent.el.addxtype(tree);
16041 this.fireEvent('built', this);
16043 this.panel = this.el;
16044 this.layout = this.panel.layout;
16045 this.parentLayout = this.parent.layout || false;
16051 Roo.apply(Roo.XComponent, {
16053 * @property hideProgress
16054 * true to disable the building progress bar.. usefull on single page renders.
16057 hideProgress : false,
16059 * @property buildCompleted
16060 * True when the builder has completed building the interface.
16063 buildCompleted : false,
16066 * @property topModule
16067 * the upper most module - uses document.element as it's constructor.
16074 * @property modules
16075 * array of modules to be created by registration system.
16076 * @type {Array} of Roo.XComponent
16081 * @property elmodules
16082 * array of modules to be created by which use #ID
16083 * @type {Array} of Roo.XComponent
16089 * @property build_from_html
16090 * Build elements from html - used by bootstrap HTML stuff
16091 * - this is cleared after build is completed
16092 * @type {boolean} true (default false)
16095 build_from_html : false,
16098 * Register components to be built later.
16100 * This solves the following issues
16101 * - Building is not done on page load, but after an authentication process has occured.
16102 * - Interface elements are registered on page load
16103 * - Parent Interface elements may not be loaded before child, so this handles that..
16110 module : 'Pman.Tab.projectMgr',
16112 parent : 'Pman.layout',
16113 disabled : false, // or use a function..
16116 * * @param {Object} details about module
16118 register : function(obj) {
16120 Roo.XComponent.event.fireEvent('register', obj);
16121 switch(typeof(obj.disabled) ) {
16127 if ( obj.disabled() ) {
16133 if (obj.disabled) {
16139 this.modules.push(obj);
16143 * convert a string to an object..
16144 * eg. 'AAA.BBB' -> finds AAA.BBB
16148 toObject : function(str)
16150 if (!str || typeof(str) == 'object') {
16153 if (str.substring(0,1) == '#') {
16157 var ar = str.split('.');
16162 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16164 throw "Module not found : " + str;
16168 throw "Module not found : " + str;
16170 Roo.each(ar, function(e) {
16171 if (typeof(o[e]) == 'undefined') {
16172 throw "Module not found : " + str;
16183 * move modules into their correct place in the tree..
16186 preBuild : function ()
16189 Roo.each(this.modules , function (obj)
16191 Roo.XComponent.event.fireEvent('beforebuild', obj);
16193 var opar = obj.parent;
16195 obj.parent = this.toObject(opar);
16197 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16202 Roo.debug && Roo.log("GOT top level module");
16203 Roo.debug && Roo.log(obj);
16204 obj.modules = new Roo.util.MixedCollection(false,
16205 function(o) { return o.order + '' }
16207 this.topModule = obj;
16210 // parent is a string (usually a dom element name..)
16211 if (typeof(obj.parent) == 'string') {
16212 this.elmodules.push(obj);
16215 if (obj.parent.constructor != Roo.XComponent) {
16216 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16218 if (!obj.parent.modules) {
16219 obj.parent.modules = new Roo.util.MixedCollection(false,
16220 function(o) { return o.order + '' }
16223 if (obj.parent.disabled) {
16224 obj.disabled = true;
16226 obj.parent.modules.add(obj);
16231 * make a list of modules to build.
16232 * @return {Array} list of modules.
16235 buildOrder : function()
16238 var cmp = function(a,b) {
16239 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16241 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16242 throw "No top level modules to build";
16245 // make a flat list in order of modules to build.
16246 var mods = this.topModule ? [ this.topModule ] : [];
16249 // elmodules (is a list of DOM based modules )
16250 Roo.each(this.elmodules, function(e) {
16252 if (!this.topModule &&
16253 typeof(e.parent) == 'string' &&
16254 e.parent.substring(0,1) == '#' &&
16255 Roo.get(e.parent.substr(1))
16258 _this.topModule = e;
16264 // add modules to their parents..
16265 var addMod = function(m) {
16266 Roo.debug && Roo.log("build Order: add: " + m.name);
16269 if (m.modules && !m.disabled) {
16270 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16271 m.modules.keySort('ASC', cmp );
16272 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16274 m.modules.each(addMod);
16276 Roo.debug && Roo.log("build Order: no child modules");
16278 // not sure if this is used any more..
16280 m.finalize.name = m.name + " (clean up) ";
16281 mods.push(m.finalize);
16285 if (this.topModule && this.topModule.modules) {
16286 this.topModule.modules.keySort('ASC', cmp );
16287 this.topModule.modules.each(addMod);
16293 * Build the registered modules.
16294 * @param {Object} parent element.
16295 * @param {Function} optional method to call after module has been added.
16299 build : function(opts)
16302 if (typeof(opts) != 'undefined') {
16303 Roo.apply(this,opts);
16307 var mods = this.buildOrder();
16309 //this.allmods = mods;
16310 //Roo.debug && Roo.log(mods);
16312 if (!mods.length) { // should not happen
16313 throw "NO modules!!!";
16317 var msg = "Building Interface...";
16318 // flash it up as modal - so we store the mask!?
16319 if (!this.hideProgress && Roo.MessageBox) {
16320 Roo.MessageBox.show({ title: 'loading' });
16321 Roo.MessageBox.show({
16322 title: "Please wait...",
16331 var total = mods.length;
16334 var progressRun = function() {
16335 if (!mods.length) {
16336 Roo.debug && Roo.log('hide?');
16337 if (!this.hideProgress && Roo.MessageBox) {
16338 Roo.MessageBox.hide();
16340 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16342 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16348 var m = mods.shift();
16351 Roo.debug && Roo.log(m);
16352 // not sure if this is supported any more.. - modules that are are just function
16353 if (typeof(m) == 'function') {
16355 return progressRun.defer(10, _this);
16359 msg = "Building Interface " + (total - mods.length) +
16361 (m.name ? (' - ' + m.name) : '');
16362 Roo.debug && Roo.log(msg);
16363 if (!this.hideProgress && Roo.MessageBox) {
16364 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16368 // is the module disabled?
16369 var disabled = (typeof(m.disabled) == 'function') ?
16370 m.disabled.call(m.module.disabled) : m.disabled;
16374 return progressRun(); // we do not update the display!
16382 // it's 10 on top level, and 1 on others??? why...
16383 return progressRun.defer(10, _this);
16386 progressRun.defer(1, _this);
16400 * wrapper for event.on - aliased later..
16401 * Typically use to register a event handler for register:
16403 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16412 Roo.XComponent.event = new Roo.util.Observable({
16416 * Fires when an Component is registered,
16417 * set the disable property on the Component to stop registration.
16418 * @param {Roo.XComponent} c the component being registerd.
16423 * @event beforebuild
16424 * Fires before each Component is built
16425 * can be used to apply permissions.
16426 * @param {Roo.XComponent} c the component being registerd.
16429 'beforebuild' : true,
16431 * @event buildcomplete
16432 * Fires on the top level element when all elements have been built
16433 * @param {Roo.XComponent} the top level component.
16435 'buildcomplete' : true
16440 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);