4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0,
64 isTouch = 'ontouchstart' in window || window.DocumentTouch && document instanceof DocumentTouch;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
89 * Turn on debugging output (currently only the factory uses this)
96 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
99 enableGarbageCollector : true,
102 * True to automatically purge event listeners after uncaching an element (defaults to false).
103 * Note: this only happens if enableGarbageCollector is true.
106 enableListenerCollection:false,
109 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
110 * the IE insecure content warning (defaults to javascript:false).
113 SSL_SECURE_URL : "javascript:false",
116 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
117 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
120 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
122 emptyFn : function(){},
125 * Copies all the properties of config to obj if they don't already exist.
126 * @param {Object} obj The receiver of the properties
127 * @param {Object} config The source of the properties
128 * @return {Object} returns obj
130 applyIf : function(o, c){
133 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
140 * Applies event listeners to elements by selectors when the document is ready.
141 * The event name is specified with an @ suffix.
144 // add a listener for click on all anchors in element with id foo
145 '#foo a@click' : function(e, t){
149 // add the same listener to multiple selectors (separated by comma BEFORE the @)
150 '#foo a, #bar span.some-class@mouseover' : function(){
155 * @param {Object} obj The list of behaviors to apply
157 addBehaviors : function(o){
159 Roo.onReady(function(){
164 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
166 var parts = b.split('@');
167 if(parts[1]){ // for Object prototype breakers
170 cache[s] = Roo.select(s);
172 cache[s].on(parts[1], o[b]);
179 * Generates unique ids. If the element already has an id, it is unchanged
180 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
181 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
182 * @return {String} The generated Id.
184 id : function(el, prefix){
185 prefix = prefix || "roo-gen";
187 var id = prefix + (++idSeed);
188 return el ? (el.id ? el.id : (el.id = id)) : id;
193 * Extends one class with another class and optionally overrides members with the passed literal. This class
194 * also adds the function "override()" to the class that can be used to override
195 * members on an instance.
196 * @param {Object} subclass The class inheriting the functionality
197 * @param {Object} superclass The class being extended
198 * @param {Object} overrides (optional) A literal with members
203 var io = function(o){
208 return function(sb, sp, overrides){
209 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
212 sb = function(){sp.apply(this, arguments);};
214 var F = function(){}, sbp, spp = sp.prototype;
216 sbp = sb.prototype = new F();
220 if(spp.constructor == Object.prototype.constructor){
225 sb.override = function(o){
229 Roo.override(sb, overrides);
235 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
237 Roo.override(MyClass, {
238 newMethod1: function(){
241 newMethod2: function(foo){
246 * @param {Object} origclass The class to override
247 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
248 * containing one or more methods.
251 override : function(origclass, overrides){
253 var p = origclass.prototype;
254 for(var method in overrides){
255 p[method] = overrides[method];
260 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
262 Roo.namespace('Company', 'Company.data');
263 Company.Widget = function() { ... }
264 Company.data.CustomStore = function(config) { ... }
266 * @param {String} namespace1
267 * @param {String} namespace2
268 * @param {String} etc
271 namespace : function(){
272 var a=arguments, o=null, i, j, d, rt;
273 for (i=0; i<a.length; ++i) {
277 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
278 for (j=1; j<d.length; ++j) {
279 o[d[j]]=o[d[j]] || {};
285 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
287 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
288 Roo.factory(conf, Roo.data);
290 * @param {String} classname
291 * @param {String} namespace (optional)
295 factory : function(c, ns)
297 // no xtype, no ns or c.xns - or forced off by c.xns
298 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
301 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
302 if (c.constructor == ns[c.xtype]) {// already created...
306 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
307 var ret = new ns[c.xtype](c);
311 c.xns = false; // prevent recursion..
315 * Logs to console if it can.
317 * @param {String|Object} string
322 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
329 * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2". Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
333 urlEncode : function(o){
339 var ov = o[key], k = Roo.encodeURIComponent(key);
340 var type = typeof ov;
341 if(type == 'undefined'){
343 }else if(type != "function" && type != "object"){
344 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
345 }else if(ov instanceof Array){
347 for(var i = 0, len = ov.length; i < len; i++) {
348 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
359 * Safe version of encodeURIComponent
360 * @param {String} data
364 encodeURIComponent : function (data)
367 return encodeURIComponent(data);
368 } catch(e) {} // should be an uri encode error.
370 if (data == '' || data == null){
373 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
374 function nibble_to_hex(nibble){
375 var chars = '0123456789ABCDEF';
376 return chars.charAt(nibble);
378 data = data.toString();
380 for(var i=0; i<data.length; i++){
381 var c = data.charCodeAt(i);
382 var bs = new Array();
385 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
386 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
387 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
388 bs[3] = 0x80 | (c & 0x3F);
389 }else if (c > 0x800){
391 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
392 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
393 bs[2] = 0x80 | (c & 0x3F);
396 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
397 bs[1] = 0x80 | (c & 0x3F);
402 for(var j=0; j<bs.length; j++){
404 var hex = nibble_to_hex((b & 0xF0) >>> 4)
405 + nibble_to_hex(b &0x0F);
414 * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
415 * @param {String} string
416 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
417 * @return {Object} A literal with members
419 urlDecode : function(string, overwrite){
420 if(!string || !string.length){
424 var pairs = string.split('&');
425 var pair, name, value;
426 for(var i = 0, len = pairs.length; i < len; i++){
427 pair = pairs[i].split('=');
428 name = decodeURIComponent(pair[0]);
429 value = decodeURIComponent(pair[1]);
430 if(overwrite !== true){
431 if(typeof obj[name] == "undefined"){
433 }else if(typeof obj[name] == "string"){
434 obj[name] = [obj[name]];
435 obj[name].push(value);
437 obj[name].push(value);
447 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
448 * passed array is not really an array, your function is called once with it.
449 * The supplied function is called with (Object item, Number index, Array allItems).
450 * @param {Array/NodeList/Mixed} array
451 * @param {Function} fn
452 * @param {Object} scope
454 each : function(array, fn, scope){
455 if(typeof array.length == "undefined" || typeof array == "string"){
458 for(var i = 0, len = array.length; i < len; i++){
459 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
464 combine : function(){
465 var as = arguments, l = as.length, r = [];
466 for(var i = 0; i < l; i++){
468 if(a instanceof Array){
470 }else if(a.length !== undefined && !a.substr){
471 r = r.concat(Array.prototype.slice.call(a, 0));
480 * Escapes the passed string for use in a regular expression
481 * @param {String} str
484 escapeRe : function(s) {
485 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
489 callback : function(cb, scope, args, delay){
490 if(typeof cb == "function"){
492 cb.defer(delay, scope, args || []);
494 cb.apply(scope, args || []);
500 * Return the dom node for the passed string (id), dom node, or Roo.Element
501 * @param {String/HTMLElement/Roo.Element} el
502 * @return HTMLElement
504 getDom : function(el){
508 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
512 * Shorthand for {@link Roo.ComponentMgr#get}
514 * @return Roo.Component
516 getCmp : function(id){
517 return Roo.ComponentMgr.get(id);
520 num : function(v, defaultValue){
521 if(typeof v != 'number'){
527 destroy : function(){
528 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
532 as.removeAllListeners();
536 if(typeof as.purgeListeners == 'function'){
539 if(typeof as.destroy == 'function'){
546 // inpired by a similar function in mootools library
548 * Returns the type of object that is passed in. If the object passed in is null or undefined it
549 * return false otherwise it returns one of the following values:<ul>
550 * <li><b>string</b>: If the object passed is a string</li>
551 * <li><b>number</b>: If the object passed is a number</li>
552 * <li><b>boolean</b>: If the object passed is a boolean value</li>
553 * <li><b>function</b>: If the object passed is a function reference</li>
554 * <li><b>object</b>: If the object passed is an object</li>
555 * <li><b>array</b>: If the object passed is an array</li>
556 * <li><b>regexp</b>: If the object passed is a regular expression</li>
557 * <li><b>element</b>: If the object passed is a DOM Element</li>
558 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
559 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
560 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
561 * @param {Mixed} object
565 if(o === undefined || o === null){
572 if(t == 'object' && o.nodeName) {
574 case 1: return 'element';
575 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
578 if(t == 'object' || t == 'function') {
579 switch(o.constructor) {
580 case Array: return 'array';
581 case RegExp: return 'regexp';
583 if(typeof o.length == 'number' && typeof o.item == 'function') {
591 * Returns true if the passed value is null, undefined or an empty string (optional).
592 * @param {Mixed} value The value to test
593 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
596 isEmpty : function(v, allowBlank){
597 return v === null || v === undefined || (!allowBlank ? v === '' : false);
611 isBorderBox : isBorderBox,
613 isWindows : isWindows,
622 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
623 * you may want to set this to true.
626 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
631 * Selects a single element as a Roo Element
632 * This is about as close as you can get to jQuery's $('do crazy stuff')
633 * @param {String} selector The selector/xpath query
634 * @param {Node} root (optional) The start of the query (defaults to document).
635 * @return {Roo.Element}
637 selectNode : function(selector, root)
639 var node = Roo.DomQuery.selectNode(selector,root);
640 return node ? Roo.get(node) : new Roo.Element(false);
648 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
649 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout",
652 "Roo.bootstrap.dash");
655 * Ext JS Library 1.1.1
656 * Copyright(c) 2006-2007, Ext JS, LLC.
658 * Originally Released Under LGPL - original licence link has changed is not relivant.
661 * <script type="text/javascript">
665 // wrappedn so fnCleanup is not in global scope...
667 function fnCleanUp() {
668 var p = Function.prototype;
669 delete p.createSequence;
671 delete p.createDelegate;
672 delete p.createCallback;
673 delete p.createInterceptor;
675 window.detachEvent("onunload", fnCleanUp);
677 window.attachEvent("onunload", fnCleanUp);
684 * These functions are available on every Function object (any JavaScript function).
686 Roo.apply(Function.prototype, {
688 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
689 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
690 * Will create a function that is bound to those 2 args.
691 * @return {Function} The new function
693 createCallback : function(/*args...*/){
694 // make args available, in function below
695 var args = arguments;
698 return method.apply(window, args);
703 * Creates a delegate (callback) that sets the scope to obj.
704 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
705 * Will create a function that is automatically scoped to this.
706 * @param {Object} obj (optional) The object for which the scope is set
707 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
708 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
709 * if a number the args are inserted at the specified position
710 * @return {Function} The new function
712 createDelegate : function(obj, args, appendArgs){
715 var callArgs = args || arguments;
716 if(appendArgs === true){
717 callArgs = Array.prototype.slice.call(arguments, 0);
718 callArgs = callArgs.concat(args);
719 }else if(typeof appendArgs == "number"){
720 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
721 var applyArgs = [appendArgs, 0].concat(args); // create method call params
722 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
724 return method.apply(obj || window, callArgs);
729 * Calls this function after the number of millseconds specified.
730 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
731 * @param {Object} obj (optional) The object for which the scope is set
732 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
733 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
734 * if a number the args are inserted at the specified position
735 * @return {Number} The timeout id that can be used with clearTimeout
737 defer : function(millis, obj, args, appendArgs){
738 var fn = this.createDelegate(obj, args, appendArgs);
740 return setTimeout(fn, millis);
746 * Create a combined function call sequence of the original function + the passed function.
747 * The resulting function returns the results of the original function.
748 * The passed fcn is called with the parameters of the original function
749 * @param {Function} fcn The function to sequence
750 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
751 * @return {Function} The new function
753 createSequence : function(fcn, scope){
754 if(typeof fcn != "function"){
759 var retval = method.apply(this || window, arguments);
760 fcn.apply(scope || this || window, arguments);
766 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
767 * The resulting function returns the results of the original function.
768 * The passed fcn is called with the parameters of the original function.
770 * @param {Function} fcn The function to call before the original
771 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
772 * @return {Function} The new function
774 createInterceptor : function(fcn, scope){
775 if(typeof fcn != "function"){
782 if(fcn.apply(scope || this || window, arguments) === false){
785 return method.apply(this || window, arguments);
791 * Ext JS Library 1.1.1
792 * Copyright(c) 2006-2007, Ext JS, LLC.
794 * Originally Released Under LGPL - original licence link has changed is not relivant.
797 * <script type="text/javascript">
800 Roo.applyIf(String, {
805 * Escapes the passed string for ' and \
806 * @param {String} string The string to escape
807 * @return {String} The escaped string
810 escape : function(string) {
811 return string.replace(/('|\\)/g, "\\$1");
815 * Pads the left side of a string with a specified character. This is especially useful
816 * for normalizing number and date strings. Example usage:
818 var s = String.leftPad('123', 5, '0');
819 // s now contains the string: '00123'
821 * @param {String} string The original string
822 * @param {Number} size The total length of the output string
823 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
824 * @return {String} The padded string
827 leftPad : function (val, size, ch) {
828 var result = new String(val);
829 if(ch === null || ch === undefined || ch === '') {
832 while (result.length < size) {
833 result = ch + result;
839 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
840 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
842 var cls = 'my-class', text = 'Some text';
843 var s = String.format('<div class="{0}">{1}</div>', cls, text);
844 // s now contains the string: '<div class="my-class">Some text</div>'
846 * @param {String} string The tokenized string to be formatted
847 * @param {String} value1 The value to replace token {0}
848 * @param {String} value2 Etc...
849 * @return {String} The formatted string
852 format : function(format){
853 var args = Array.prototype.slice.call(arguments, 1);
854 return format.replace(/\{(\d+)\}/g, function(m, i){
855 return Roo.util.Format.htmlEncode(args[i]);
861 * Utility function that allows you to easily switch a string between two alternating values. The passed value
862 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
863 * they are already different, the first value passed in is returned. Note that this method returns the new value
864 * but does not change the current string.
866 // alternate sort directions
867 sort = sort.toggle('ASC', 'DESC');
869 // instead of conditional logic:
870 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
872 * @param {String} value The value to compare to the current string
873 * @param {String} other The new value to use if the string already equals the first value passed in
874 * @return {String} The new value
877 String.prototype.toggle = function(value, other){
878 return this == value ? other : value;
881 * Ext JS Library 1.1.1
882 * Copyright(c) 2006-2007, Ext JS, LLC.
884 * Originally Released Under LGPL - original licence link has changed is not relivant.
887 * <script type="text/javascript">
893 Roo.applyIf(Number.prototype, {
895 * Checks whether or not the current number is within a desired range. If the number is already within the
896 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
897 * exceeded. Note that this method returns the constrained value but does not change the current number.
898 * @param {Number} min The minimum number in the range
899 * @param {Number} max The maximum number in the range
900 * @return {Number} The constrained value if outside the range, otherwise the current value
902 constrain : function(min, max){
903 return Math.min(Math.max(this, min), max);
907 * Ext JS Library 1.1.1
908 * Copyright(c) 2006-2007, Ext JS, LLC.
910 * Originally Released Under LGPL - original licence link has changed is not relivant.
913 * <script type="text/javascript">
918 Roo.applyIf(Array.prototype, {
920 * Checks whether or not the specified object exists in the array.
921 * @param {Object} o The object to check for
922 * @return {Number} The index of o in the array (or -1 if it is not found)
924 indexOf : function(o){
925 for (var i = 0, len = this.length; i < len; i++){
926 if(this[i] == o) return i;
932 * Removes the specified object from the array. If the object is not found nothing happens.
933 * @param {Object} o The object to remove
935 remove : function(o){
936 var index = this.indexOf(o);
938 this.splice(index, 1);
942 * Map (JS 1.6 compatibility)
943 * @param {Function} function to call
947 var len = this.length >>> 0;
948 if (typeof fun != "function")
949 throw new TypeError();
951 var res = new Array(len);
952 var thisp = arguments[1];
953 for (var i = 0; i < len; i++)
956 res[i] = fun.call(thisp, this[i], i, this);
967 * Ext JS Library 1.1.1
968 * Copyright(c) 2006-2007, Ext JS, LLC.
970 * Originally Released Under LGPL - original licence link has changed is not relivant.
973 * <script type="text/javascript">
979 * The date parsing and format syntax is a subset of
980 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
981 * supported will provide results equivalent to their PHP versions.
983 * Following is the list of all currently supported formats:
986 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
988 Format Output Description
989 ------ ---------- --------------------------------------------------------------
990 d 10 Day of the month, 2 digits with leading zeros
991 D Wed A textual representation of a day, three letters
992 j 10 Day of the month without leading zeros
993 l Wednesday A full textual representation of the day of the week
994 S th English ordinal day of month suffix, 2 chars (use with j)
995 w 3 Numeric representation of the day of the week
996 z 9 The julian date, or day of the year (0-365)
997 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
998 F January A full textual representation of the month
999 m 01 Numeric representation of a month, with leading zeros
1000 M Jan Month name abbreviation, three letters
1001 n 1 Numeric representation of a month, without leading zeros
1002 t 31 Number of days in the given month
1003 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1004 Y 2007 A full numeric representation of a year, 4 digits
1005 y 07 A two digit representation of a year
1006 a pm Lowercase Ante meridiem and Post meridiem
1007 A PM Uppercase Ante meridiem and Post meridiem
1008 g 3 12-hour format of an hour without leading zeros
1009 G 15 24-hour format of an hour without leading zeros
1010 h 03 12-hour format of an hour with leading zeros
1011 H 15 24-hour format of an hour with leading zeros
1012 i 05 Minutes with leading zeros
1013 s 01 Seconds, with leading zeros
1014 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1015 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1016 T CST Timezone setting of the machine running the code
1017 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1020 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1022 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1023 document.write(dt.format('Y-m-d')); //2007-01-10
1024 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1025 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
1028 * Here are some standard date/time patterns that you might find helpful. They
1029 * are not part of the source of Date.js, but to use them you can simply copy this
1030 * block of code into any script that is included after Date.js and they will also become
1031 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1034 ISO8601Long:"Y-m-d H:i:s",
1035 ISO8601Short:"Y-m-d",
1037 LongDate: "l, F d, Y",
1038 FullDateTime: "l, F d, Y g:i:s A",
1041 LongTime: "g:i:s A",
1042 SortableDateTime: "Y-m-d\\TH:i:s",
1043 UniversalSortableDateTime: "Y-m-d H:i:sO",
1050 var dt = new Date();
1051 document.write(dt.format(Date.patterns.ShortDate));
1056 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1057 * They generate precompiled functions from date formats instead of parsing and
1058 * processing the pattern every time you format a date. These functions are available
1059 * on every Date object (any javascript function).
1061 * The original article and download are here:
1062 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1069 Returns the number of milliseconds between this date and date
1070 @param {Date} date (optional) Defaults to now
1071 @return {Number} The diff in milliseconds
1072 @member Date getElapsed
1074 Date.prototype.getElapsed = function(date) {
1075 return Math.abs((date || new Date()).getTime()-this.getTime());
1077 // was in date file..
1081 Date.parseFunctions = {count:0};
1083 Date.parseRegexes = [];
1085 Date.formatFunctions = {count:0};
1088 Date.prototype.dateFormat = function(format) {
1089 if (Date.formatFunctions[format] == null) {
1090 Date.createNewFormat(format);
1092 var func = Date.formatFunctions[format];
1093 return this[func]();
1098 * Formats a date given the supplied format string
1099 * @param {String} format The format string
1100 * @return {String} The formatted date
1103 Date.prototype.format = Date.prototype.dateFormat;
1106 Date.createNewFormat = function(format) {
1107 var funcName = "format" + Date.formatFunctions.count++;
1108 Date.formatFunctions[format] = funcName;
1109 var code = "Date.prototype." + funcName + " = function(){return ";
1110 var special = false;
1112 for (var i = 0; i < format.length; ++i) {
1113 ch = format.charAt(i);
1114 if (!special && ch == "\\") {
1119 code += "'" + String.escape(ch) + "' + ";
1122 code += Date.getFormatCode(ch);
1125 /** eval:var:zzzzzzzzzzzzz */
1126 eval(code.substring(0, code.length - 3) + ";}");
1130 Date.getFormatCode = function(character) {
1131 switch (character) {
1133 return "String.leftPad(this.getDate(), 2, '0') + ";
1135 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1137 return "this.getDate() + ";
1139 return "Date.dayNames[this.getDay()] + ";
1141 return "this.getSuffix() + ";
1143 return "this.getDay() + ";
1145 return "this.getDayOfYear() + ";
1147 return "this.getWeekOfYear() + ";
1149 return "Date.monthNames[this.getMonth()] + ";
1151 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1153 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1155 return "(this.getMonth() + 1) + ";
1157 return "this.getDaysInMonth() + ";
1159 return "(this.isLeapYear() ? 1 : 0) + ";
1161 return "this.getFullYear() + ";
1163 return "('' + this.getFullYear()).substring(2, 4) + ";
1165 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1167 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1169 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1171 return "this.getHours() + ";
1173 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1175 return "String.leftPad(this.getHours(), 2, '0') + ";
1177 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1179 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1181 return "this.getGMTOffset() + ";
1183 return "this.getGMTColonOffset() + ";
1185 return "this.getTimezone() + ";
1187 return "(this.getTimezoneOffset() * -60) + ";
1189 return "'" + String.escape(character) + "' + ";
1194 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1195 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1196 * the date format that is not specified will default to the current date value for that part. Time parts can also
1197 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1198 * string or the parse operation will fail.
1201 //dt = Fri May 25 2007 (current date)
1202 var dt = new Date();
1204 //dt = Thu May 25 2006 (today's month/day in 2006)
1205 dt = Date.parseDate("2006", "Y");
1207 //dt = Sun Jan 15 2006 (all date parts specified)
1208 dt = Date.parseDate("2006-1-15", "Y-m-d");
1210 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1211 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1213 * @param {String} input The unparsed date as a string
1214 * @param {String} format The format the date is in
1215 * @return {Date} The parsed date
1218 Date.parseDate = function(input, format) {
1219 if (Date.parseFunctions[format] == null) {
1220 Date.createParser(format);
1222 var func = Date.parseFunctions[format];
1223 return Date[func](input);
1228 Date.createParser = function(format) {
1229 var funcName = "parse" + Date.parseFunctions.count++;
1230 var regexNum = Date.parseRegexes.length;
1231 var currentGroup = 1;
1232 Date.parseFunctions[format] = funcName;
1234 var code = "Date." + funcName + " = function(input){\n"
1235 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1236 + "var d = new Date();\n"
1237 + "y = d.getFullYear();\n"
1238 + "m = d.getMonth();\n"
1239 + "d = d.getDate();\n"
1240 + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
1241 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1242 + "if (results && results.length > 0) {";
1245 var special = false;
1247 for (var i = 0; i < format.length; ++i) {
1248 ch = format.charAt(i);
1249 if (!special && ch == "\\") {
1254 regex += String.escape(ch);
1257 var obj = Date.formatCodeToRegex(ch, currentGroup);
1258 currentGroup += obj.g;
1260 if (obj.g && obj.c) {
1266 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1267 + "{v = new Date(y, m, d, h, i, s);}\n"
1268 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1269 + "{v = new Date(y, m, d, h, i);}\n"
1270 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1271 + "{v = new Date(y, m, d, h);}\n"
1272 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1273 + "{v = new Date(y, m, d);}\n"
1274 + "else if (y >= 0 && m >= 0)\n"
1275 + "{v = new Date(y, m);}\n"
1276 + "else if (y >= 0)\n"
1277 + "{v = new Date(y);}\n"
1278 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1279 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1280 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1283 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1284 /** eval:var:zzzzzzzzzzzzz */
1289 Date.formatCodeToRegex = function(character, currentGroup) {
1290 switch (character) {
1294 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1297 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1298 s:"(\\d{1,2})"}; // day of month without leading zeroes
1301 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1302 s:"(\\d{2})"}; // day of month with leading zeroes
1306 s:"(?:" + Date.dayNames.join("|") + ")"};
1310 s:"(?:st|nd|rd|th)"};
1325 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1326 s:"(" + Date.monthNames.join("|") + ")"};
1329 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1330 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1333 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1334 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1337 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1338 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1349 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1353 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1354 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1358 c:"if (results[" + currentGroup + "] == 'am') {\n"
1359 + "if (h == 12) { h = 0; }\n"
1360 + "} else { if (h < 12) { h += 12; }}",
1364 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1365 + "if (h == 12) { h = 0; }\n"
1366 + "} else { if (h < 12) { h += 12; }}",
1371 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1372 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1376 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1377 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1380 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1384 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1389 "o = results[", currentGroup, "];\n",
1390 "var sn = o.substring(0,1);\n", // get + / - sign
1391 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1392 "var mn = o.substring(3,5) % 60;\n", // get minutes
1393 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1394 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1396 s:"([+\-]\\d{2,4})"};
1402 "o = results[", currentGroup, "];\n",
1403 "var sn = o.substring(0,1);\n",
1404 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1405 "var mn = o.substring(4,6) % 60;\n",
1406 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1407 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1413 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1416 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1417 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1418 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1422 s:String.escape(character)};
1427 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1428 * @return {String} The abbreviated timezone name (e.g. 'CST')
1430 Date.prototype.getTimezone = function() {
1431 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1435 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1436 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1438 Date.prototype.getGMTOffset = function() {
1439 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1440 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1441 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1445 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1446 * @return {String} 2-characters representing hours and 2-characters representing minutes
1447 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1449 Date.prototype.getGMTColonOffset = function() {
1450 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1451 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1453 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1457 * Get the numeric day number of the year, adjusted for leap year.
1458 * @return {Number} 0 through 364 (365 in leap years)
1460 Date.prototype.getDayOfYear = function() {
1462 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1463 for (var i = 0; i < this.getMonth(); ++i) {
1464 num += Date.daysInMonth[i];
1466 return num + this.getDate() - 1;
1470 * Get the string representation of the numeric week number of the year
1471 * (equivalent to the format specifier 'W').
1472 * @return {String} '00' through '52'
1474 Date.prototype.getWeekOfYear = function() {
1475 // Skip to Thursday of this week
1476 var now = this.getDayOfYear() + (4 - this.getDay());
1477 // Find the first Thursday of the year
1478 var jan1 = new Date(this.getFullYear(), 0, 1);
1479 var then = (7 - jan1.getDay() + 4);
1480 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1484 * Whether or not the current date is in a leap year.
1485 * @return {Boolean} True if the current date is in a leap year, else false
1487 Date.prototype.isLeapYear = function() {
1488 var year = this.getFullYear();
1489 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1493 * Get the first day of the current month, adjusted for leap year. The returned value
1494 * is the numeric day index within the week (0-6) which can be used in conjunction with
1495 * the {@link #monthNames} array to retrieve the textual day name.
1498 var dt = new Date('1/10/2007');
1499 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1501 * @return {Number} The day number (0-6)
1503 Date.prototype.getFirstDayOfMonth = function() {
1504 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1505 return (day < 0) ? (day + 7) : day;
1509 * Get the last day of the current month, adjusted for leap year. The returned value
1510 * is the numeric day index within the week (0-6) which can be used in conjunction with
1511 * the {@link #monthNames} array to retrieve the textual day name.
1514 var dt = new Date('1/10/2007');
1515 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1517 * @return {Number} The day number (0-6)
1519 Date.prototype.getLastDayOfMonth = function() {
1520 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1521 return (day < 0) ? (day + 7) : day;
1526 * Get the first date of this date's month
1529 Date.prototype.getFirstDateOfMonth = function() {
1530 return new Date(this.getFullYear(), this.getMonth(), 1);
1534 * Get the last date of this date's month
1537 Date.prototype.getLastDateOfMonth = function() {
1538 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1541 * Get the number of days in the current month, adjusted for leap year.
1542 * @return {Number} The number of days in the month
1544 Date.prototype.getDaysInMonth = function() {
1545 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1546 return Date.daysInMonth[this.getMonth()];
1550 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1551 * @return {String} 'st, 'nd', 'rd' or 'th'
1553 Date.prototype.getSuffix = function() {
1554 switch (this.getDate()) {
1571 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1574 * An array of textual month names.
1575 * Override these values for international dates, for example...
1576 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1595 * An array of textual day names.
1596 * Override these values for international dates, for example...
1597 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1613 Date.monthNumbers = {
1628 * Creates and returns a new Date instance with the exact same date value as the called instance.
1629 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1630 * variable will also be changed. When the intention is to create a new variable that will not
1631 * modify the original instance, you should create a clone.
1633 * Example of correctly cloning a date:
1636 var orig = new Date('10/1/2006');
1639 document.write(orig); //returns 'Thu Oct 05 2006'!
1642 var orig = new Date('10/1/2006');
1643 var copy = orig.clone();
1645 document.write(orig); //returns 'Thu Oct 01 2006'
1647 * @return {Date} The new Date instance
1649 Date.prototype.clone = function() {
1650 return new Date(this.getTime());
1654 * Clears any time information from this date
1655 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1656 @return {Date} this or the clone
1658 Date.prototype.clearTime = function(clone){
1660 return this.clone().clearTime();
1665 this.setMilliseconds(0);
1670 // safari setMonth is broken
1672 Date.brokenSetMonth = Date.prototype.setMonth;
1673 Date.prototype.setMonth = function(num){
1675 var n = Math.ceil(-num);
1676 var back_year = Math.ceil(n/12);
1677 var month = (n % 12) ? 12 - n % 12 : 0 ;
1678 this.setFullYear(this.getFullYear() - back_year);
1679 return Date.brokenSetMonth.call(this, month);
1681 return Date.brokenSetMonth.apply(this, arguments);
1686 /** Date interval constant
1690 /** Date interval constant
1694 /** Date interval constant
1698 /** Date interval constant
1702 /** Date interval constant
1706 /** Date interval constant
1710 /** Date interval constant
1716 * Provides a convenient method of performing basic date arithmetic. This method
1717 * does not modify the Date instance being called - it creates and returns
1718 * a new Date instance containing the resulting date value.
1723 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1724 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1726 //Negative values will subtract correctly:
1727 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1728 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1730 //You can even chain several calls together in one line!
1731 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1732 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1735 * @param {String} interval A valid date interval enum value
1736 * @param {Number} value The amount to add to the current date
1737 * @return {Date} The new Date instance
1739 Date.prototype.add = function(interval, value){
1740 var d = this.clone();
1741 if (!interval || value === 0) return d;
1742 switch(interval.toLowerCase()){
1744 d.setMilliseconds(this.getMilliseconds() + value);
1747 d.setSeconds(this.getSeconds() + value);
1750 d.setMinutes(this.getMinutes() + value);
1753 d.setHours(this.getHours() + value);
1756 d.setDate(this.getDate() + value);
1759 var day = this.getDate();
1761 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1764 d.setMonth(this.getMonth() + value);
1767 d.setFullYear(this.getFullYear() + value);
1774 * Ext JS Library 1.1.1
1775 * Copyright(c) 2006-2007, Ext JS, LLC.
1777 * Originally Released Under LGPL - original licence link has changed is not relivant.
1780 * <script type="text/javascript">
1784 * @class Roo.lib.Dom
1787 * Dom utils (from YIU afaik)
1792 * Get the view width
1793 * @param {Boolean} full True will get the full document, otherwise it's the view width
1794 * @return {Number} The width
1797 getViewWidth : function(full) {
1798 return full ? this.getDocumentWidth() : this.getViewportWidth();
1801 * Get the view height
1802 * @param {Boolean} full True will get the full document, otherwise it's the view height
1803 * @return {Number} The height
1805 getViewHeight : function(full) {
1806 return full ? this.getDocumentHeight() : this.getViewportHeight();
1809 getDocumentHeight: function() {
1810 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1811 return Math.max(scrollHeight, this.getViewportHeight());
1814 getDocumentWidth: function() {
1815 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1816 return Math.max(scrollWidth, this.getViewportWidth());
1819 getViewportHeight: function() {
1820 var height = self.innerHeight;
1821 var mode = document.compatMode;
1823 if ((mode || Roo.isIE) && !Roo.isOpera) {
1824 height = (mode == "CSS1Compat") ?
1825 document.documentElement.clientHeight :
1826 document.body.clientHeight;
1832 getViewportWidth: function() {
1833 var width = self.innerWidth;
1834 var mode = document.compatMode;
1836 if (mode || Roo.isIE) {
1837 width = (mode == "CSS1Compat") ?
1838 document.documentElement.clientWidth :
1839 document.body.clientWidth;
1844 isAncestor : function(p, c) {
1851 if (p.contains && !Roo.isSafari) {
1852 return p.contains(c);
1853 } else if (p.compareDocumentPosition) {
1854 return !!(p.compareDocumentPosition(c) & 16);
1856 var parent = c.parentNode;
1861 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1864 parent = parent.parentNode;
1870 getRegion : function(el) {
1871 return Roo.lib.Region.getRegion(el);
1874 getY : function(el) {
1875 return this.getXY(el)[1];
1878 getX : function(el) {
1879 return this.getXY(el)[0];
1882 getXY : function(el) {
1883 var p, pe, b, scroll, bd = document.body;
1884 el = Roo.getDom(el);
1885 var fly = Roo.lib.AnimBase.fly;
1886 if (el.getBoundingClientRect) {
1887 b = el.getBoundingClientRect();
1888 scroll = fly(document).getScroll();
1889 return [b.left + scroll.left, b.top + scroll.top];
1895 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1902 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1909 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1910 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1917 if (p != el && pe.getStyle('overflow') != 'visible') {
1925 if (Roo.isSafari && hasAbsolute) {
1930 if (Roo.isGecko && !hasAbsolute) {
1932 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1933 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1937 while (p && p != bd) {
1938 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1950 setXY : function(el, xy) {
1951 el = Roo.fly(el, '_setXY');
1953 var pts = el.translatePoints(xy);
1954 if (xy[0] !== false) {
1955 el.dom.style.left = pts.left + "px";
1957 if (xy[1] !== false) {
1958 el.dom.style.top = pts.top + "px";
1962 setX : function(el, x) {
1963 this.setXY(el, [x, false]);
1966 setY : function(el, y) {
1967 this.setXY(el, [false, y]);
1971 * Portions of this file are based on pieces of Yahoo User Interface Library
1972 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1973 * YUI licensed under the BSD License:
1974 * http://developer.yahoo.net/yui/license.txt
1975 * <script type="text/javascript">
1979 Roo.lib.Event = function() {
1980 var loadComplete = false;
1982 var unloadListeners = [];
1984 var onAvailStack = [];
1986 var lastError = null;
1999 startInterval: function() {
2000 if (!this._interval) {
2002 var callback = function() {
2003 self._tryPreloadAttach();
2005 this._interval = setInterval(callback, this.POLL_INTERVAL);
2010 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2011 onAvailStack.push({ id: p_id,
2014 override: p_override,
2015 checkReady: false });
2017 retryCount = this.POLL_RETRYS;
2018 this.startInterval();
2022 addListener: function(el, eventName, fn) {
2023 el = Roo.getDom(el);
2028 if ("unload" == eventName) {
2029 unloadListeners[unloadListeners.length] =
2030 [el, eventName, fn];
2034 var wrappedFn = function(e) {
2035 return fn(Roo.lib.Event.getEvent(e));
2038 var li = [el, eventName, fn, wrappedFn];
2040 var index = listeners.length;
2041 listeners[index] = li;
2043 this.doAdd(el, eventName, wrappedFn, false);
2049 removeListener: function(el, eventName, fn) {
2052 el = Roo.getDom(el);
2055 return this.purgeElement(el, false, eventName);
2059 if ("unload" == eventName) {
2061 for (i = 0,len = unloadListeners.length; i < len; i++) {
2062 var li = unloadListeners[i];
2065 li[1] == eventName &&
2067 unloadListeners.splice(i, 1);
2075 var cacheItem = null;
2078 var index = arguments[3];
2080 if ("undefined" == typeof index) {
2081 index = this._getCacheIndex(el, eventName, fn);
2085 cacheItem = listeners[index];
2088 if (!el || !cacheItem) {
2092 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2094 delete listeners[index][this.WFN];
2095 delete listeners[index][this.FN];
2096 listeners.splice(index, 1);
2103 getTarget: function(ev, resolveTextNode) {
2104 ev = ev.browserEvent || ev;
2105 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2106 var t = ev.target || ev.srcElement;
2107 return this.resolveTextNode(t);
2111 resolveTextNode: function(node) {
2112 if (Roo.isSafari && node && 3 == node.nodeType) {
2113 return node.parentNode;
2120 getPageX: function(ev) {
2121 ev = ev.browserEvent || ev;
2122 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2124 if (!x && 0 !== x) {
2125 x = ev.clientX || 0;
2128 x += this.getScroll()[1];
2136 getPageY: function(ev) {
2137 ev = ev.browserEvent || ev;
2138 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2140 if (!y && 0 !== y) {
2141 y = ev.clientY || 0;
2144 y += this.getScroll()[0];
2153 getXY: function(ev) {
2154 ev = ev.browserEvent || ev;
2155 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2156 return [this.getPageX(ev), this.getPageY(ev)];
2160 getRelatedTarget: function(ev) {
2161 ev = ev.browserEvent || ev;
2162 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2163 var t = ev.relatedTarget;
2165 if (ev.type == "mouseout") {
2167 } else if (ev.type == "mouseover") {
2172 return this.resolveTextNode(t);
2176 getTime: function(ev) {
2177 ev = ev.browserEvent || ev;
2178 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2180 var t = new Date().getTime();
2184 this.lastError = ex;
2193 stopEvent: function(ev) {
2194 this.stopPropagation(ev);
2195 this.preventDefault(ev);
2199 stopPropagation: function(ev) {
2200 ev = ev.browserEvent || ev;
2201 if (ev.stopPropagation) {
2202 ev.stopPropagation();
2204 ev.cancelBubble = true;
2209 preventDefault: function(ev) {
2210 ev = ev.browserEvent || ev;
2211 if(ev.preventDefault) {
2212 ev.preventDefault();
2214 ev.returnValue = false;
2219 getEvent: function(e) {
2220 var ev = e || window.event;
2222 var c = this.getEvent.caller;
2224 ev = c.arguments[0];
2225 if (ev && Event == ev.constructor) {
2235 getCharCode: function(ev) {
2236 ev = ev.browserEvent || ev;
2237 return ev.charCode || ev.keyCode || 0;
2241 _getCacheIndex: function(el, eventName, fn) {
2242 for (var i = 0,len = listeners.length; i < len; ++i) {
2243 var li = listeners[i];
2245 li[this.FN] == fn &&
2246 li[this.EL] == el &&
2247 li[this.TYPE] == eventName) {
2259 getEl: function(id) {
2260 return document.getElementById(id);
2264 clearCache: function() {
2268 _load: function(e) {
2269 loadComplete = true;
2270 var EU = Roo.lib.Event;
2274 EU.doRemove(window, "load", EU._load);
2279 _tryPreloadAttach: function() {
2288 var tryAgain = !loadComplete;
2290 tryAgain = (retryCount > 0);
2295 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2296 var item = onAvailStack[i];
2298 var el = this.getEl(item.id);
2301 if (!item.checkReady ||
2304 (document && document.body)) {
2307 if (item.override) {
2308 if (item.override === true) {
2311 scope = item.override;
2314 item.fn.call(scope, item.obj);
2315 onAvailStack[i] = null;
2318 notAvail.push(item);
2323 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2327 this.startInterval();
2329 clearInterval(this._interval);
2330 this._interval = null;
2333 this.locked = false;
2340 purgeElement: function(el, recurse, eventName) {
2341 var elListeners = this.getListeners(el, eventName);
2343 for (var i = 0,len = elListeners.length; i < len; ++i) {
2344 var l = elListeners[i];
2345 this.removeListener(el, l.type, l.fn);
2349 if (recurse && el && el.childNodes) {
2350 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2351 this.purgeElement(el.childNodes[i], recurse, eventName);
2357 getListeners: function(el, eventName) {
2358 var results = [], searchLists;
2360 searchLists = [listeners, unloadListeners];
2361 } else if (eventName == "unload") {
2362 searchLists = [unloadListeners];
2364 searchLists = [listeners];
2367 for (var j = 0; j < searchLists.length; ++j) {
2368 var searchList = searchLists[j];
2369 if (searchList && searchList.length > 0) {
2370 for (var i = 0,len = searchList.length; i < len; ++i) {
2371 var l = searchList[i];
2372 if (l && l[this.EL] === el &&
2373 (!eventName || eventName === l[this.TYPE])) {
2378 adjust: l[this.ADJ_SCOPE],
2386 return (results.length) ? results : null;
2390 _unload: function(e) {
2392 var EU = Roo.lib.Event, i, j, l, len, index;
2394 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2395 l = unloadListeners[i];
2398 if (l[EU.ADJ_SCOPE]) {
2399 if (l[EU.ADJ_SCOPE] === true) {
2402 scope = l[EU.ADJ_SCOPE];
2405 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2406 unloadListeners[i] = null;
2412 unloadListeners = null;
2414 if (listeners && listeners.length > 0) {
2415 j = listeners.length;
2418 l = listeners[index];
2420 EU.removeListener(l[EU.EL], l[EU.TYPE],
2430 EU.doRemove(window, "unload", EU._unload);
2435 getScroll: function() {
2436 var dd = document.documentElement, db = document.body;
2437 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2438 return [dd.scrollTop, dd.scrollLeft];
2440 return [db.scrollTop, db.scrollLeft];
2447 doAdd: function () {
2448 if (window.addEventListener) {
2449 return function(el, eventName, fn, capture) {
2450 el.addEventListener(eventName, fn, (capture));
2452 } else if (window.attachEvent) {
2453 return function(el, eventName, fn, capture) {
2454 el.attachEvent("on" + eventName, fn);
2463 doRemove: function() {
2464 if (window.removeEventListener) {
2465 return function (el, eventName, fn, capture) {
2466 el.removeEventListener(eventName, fn, (capture));
2468 } else if (window.detachEvent) {
2469 return function (el, eventName, fn) {
2470 el.detachEvent("on" + eventName, fn);
2482 var E = Roo.lib.Event;
2483 E.on = E.addListener;
2484 E.un = E.removeListener;
2486 if (document && document.body) {
2489 E.doAdd(window, "load", E._load);
2491 E.doAdd(window, "unload", E._unload);
2492 E._tryPreloadAttach();
2496 * Portions of this file are based on pieces of Yahoo User Interface Library
2497 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2498 * YUI licensed under the BSD License:
2499 * http://developer.yahoo.net/yui/license.txt
2500 * <script type="text/javascript">
2506 * @class Roo.lib.Ajax
2513 request : function(method, uri, cb, data, options) {
2515 var hs = options.headers;
2518 if(hs.hasOwnProperty(h)){
2519 this.initHeader(h, hs[h], false);
2523 if(options.xmlData){
2524 this.initHeader('Content-Type', 'text/xml', false);
2526 data = options.xmlData;
2530 return this.asyncRequest(method, uri, cb, data);
2533 serializeForm : function(form) {
2534 if(typeof form == 'string') {
2535 form = (document.getElementById(form) || document.forms[form]);
2538 var el, name, val, disabled, data = '', hasSubmit = false;
2539 for (var i = 0; i < form.elements.length; i++) {
2540 el = form.elements[i];
2541 disabled = form.elements[i].disabled;
2542 name = form.elements[i].name;
2543 val = form.elements[i].value;
2545 if (!disabled && name){
2549 case 'select-multiple':
2550 for (var j = 0; j < el.options.length; j++) {
2551 if (el.options[j].selected) {
2553 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2556 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2564 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2577 if(hasSubmit == false) {
2578 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2583 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2588 data = data.substr(0, data.length - 1);
2596 useDefaultHeader:true,
2598 defaultPostHeader:'application/x-www-form-urlencoded',
2600 useDefaultXhrHeader:true,
2602 defaultXhrHeader:'XMLHttpRequest',
2604 hasDefaultHeaders:true,
2616 setProgId:function(id)
2618 this.activeX.unshift(id);
2621 setDefaultPostHeader:function(b)
2623 this.useDefaultHeader = b;
2626 setDefaultXhrHeader:function(b)
2628 this.useDefaultXhrHeader = b;
2631 setPollingInterval:function(i)
2633 if (typeof i == 'number' && isFinite(i)) {
2634 this.pollInterval = i;
2638 createXhrObject:function(transactionId)
2644 http = new XMLHttpRequest();
2646 obj = { conn:http, tId:transactionId };
2650 for (var i = 0; i < this.activeX.length; ++i) {
2654 http = new ActiveXObject(this.activeX[i]);
2656 obj = { conn:http, tId:transactionId };
2669 getConnectionObject:function()
2672 var tId = this.transactionId;
2676 o = this.createXhrObject(tId);
2678 this.transactionId++;
2689 asyncRequest:function(method, uri, callback, postData)
2691 var o = this.getConnectionObject();
2697 o.conn.open(method, uri, true);
2699 if (this.useDefaultXhrHeader) {
2700 if (!this.defaultHeaders['X-Requested-With']) {
2701 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2705 if(postData && this.useDefaultHeader){
2706 this.initHeader('Content-Type', this.defaultPostHeader);
2709 if (this.hasDefaultHeaders || this.hasHeaders) {
2713 this.handleReadyState(o, callback);
2714 o.conn.send(postData || null);
2720 handleReadyState:function(o, callback)
2724 if (callback && callback.timeout) {
2726 this.timeout[o.tId] = window.setTimeout(function() {
2727 oConn.abort(o, callback, true);
2728 }, callback.timeout);
2731 this.poll[o.tId] = window.setInterval(
2733 if (o.conn && o.conn.readyState == 4) {
2734 window.clearInterval(oConn.poll[o.tId]);
2735 delete oConn.poll[o.tId];
2737 if(callback && callback.timeout) {
2738 window.clearTimeout(oConn.timeout[o.tId]);
2739 delete oConn.timeout[o.tId];
2742 oConn.handleTransactionResponse(o, callback);
2745 , this.pollInterval);
2748 handleTransactionResponse:function(o, callback, isAbort)
2752 this.releaseObject(o);
2756 var httpStatus, responseObject;
2760 if (o.conn.status !== undefined && o.conn.status != 0) {
2761 httpStatus = o.conn.status;
2773 if (httpStatus >= 200 && httpStatus < 300) {
2774 responseObject = this.createResponseObject(o, callback.argument);
2775 if (callback.success) {
2776 if (!callback.scope) {
2777 callback.success(responseObject);
2782 callback.success.apply(callback.scope, [responseObject]);
2787 switch (httpStatus) {
2795 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2796 if (callback.failure) {
2797 if (!callback.scope) {
2798 callback.failure(responseObject);
2801 callback.failure.apply(callback.scope, [responseObject]);
2806 responseObject = this.createResponseObject(o, callback.argument);
2807 if (callback.failure) {
2808 if (!callback.scope) {
2809 callback.failure(responseObject);
2812 callback.failure.apply(callback.scope, [responseObject]);
2818 this.releaseObject(o);
2819 responseObject = null;
2822 createResponseObject:function(o, callbackArg)
2829 var headerStr = o.conn.getAllResponseHeaders();
2830 var header = headerStr.split('\n');
2831 for (var i = 0; i < header.length; i++) {
2832 var delimitPos = header[i].indexOf(':');
2833 if (delimitPos != -1) {
2834 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2842 obj.status = o.conn.status;
2843 obj.statusText = o.conn.statusText;
2844 obj.getResponseHeader = headerObj;
2845 obj.getAllResponseHeaders = headerStr;
2846 obj.responseText = o.conn.responseText;
2847 obj.responseXML = o.conn.responseXML;
2849 if (typeof callbackArg !== undefined) {
2850 obj.argument = callbackArg;
2856 createExceptionObject:function(tId, callbackArg, isAbort)
2859 var COMM_ERROR = 'communication failure';
2860 var ABORT_CODE = -1;
2861 var ABORT_ERROR = 'transaction aborted';
2867 obj.status = ABORT_CODE;
2868 obj.statusText = ABORT_ERROR;
2871 obj.status = COMM_CODE;
2872 obj.statusText = COMM_ERROR;
2876 obj.argument = callbackArg;
2882 initHeader:function(label, value, isDefault)
2884 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2886 if (headerObj[label] === undefined) {
2887 headerObj[label] = value;
2892 headerObj[label] = value + "," + headerObj[label];
2896 this.hasDefaultHeaders = true;
2899 this.hasHeaders = true;
2904 setHeader:function(o)
2906 if (this.hasDefaultHeaders) {
2907 for (var prop in this.defaultHeaders) {
2908 if (this.defaultHeaders.hasOwnProperty(prop)) {
2909 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2914 if (this.hasHeaders) {
2915 for (var prop in this.headers) {
2916 if (this.headers.hasOwnProperty(prop)) {
2917 o.conn.setRequestHeader(prop, this.headers[prop]);
2921 this.hasHeaders = false;
2925 resetDefaultHeaders:function() {
2926 delete this.defaultHeaders;
2927 this.defaultHeaders = {};
2928 this.hasDefaultHeaders = false;
2931 abort:function(o, callback, isTimeout)
2933 if(this.isCallInProgress(o)) {
2935 window.clearInterval(this.poll[o.tId]);
2936 delete this.poll[o.tId];
2938 delete this.timeout[o.tId];
2941 this.handleTransactionResponse(o, callback, true);
2951 isCallInProgress:function(o)
2954 return o.conn.readyState != 4 && o.conn.readyState != 0;
2963 releaseObject:function(o)
2972 'MSXML2.XMLHTTP.3.0',
2980 * Portions of this file are based on pieces of Yahoo User Interface Library
2981 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2982 * YUI licensed under the BSD License:
2983 * http://developer.yahoo.net/yui/license.txt
2984 * <script type="text/javascript">
2988 Roo.lib.Region = function(t, r, b, l) {
2998 Roo.lib.Region.prototype = {
2999 contains : function(region) {
3000 return ( region.left >= this.left &&
3001 region.right <= this.right &&
3002 region.top >= this.top &&
3003 region.bottom <= this.bottom );
3007 getArea : function() {
3008 return ( (this.bottom - this.top) * (this.right - this.left) );
3011 intersect : function(region) {
3012 var t = Math.max(this.top, region.top);
3013 var r = Math.min(this.right, region.right);
3014 var b = Math.min(this.bottom, region.bottom);
3015 var l = Math.max(this.left, region.left);
3017 if (b >= t && r >= l) {
3018 return new Roo.lib.Region(t, r, b, l);
3023 union : function(region) {
3024 var t = Math.min(this.top, region.top);
3025 var r = Math.max(this.right, region.right);
3026 var b = Math.max(this.bottom, region.bottom);
3027 var l = Math.min(this.left, region.left);
3029 return new Roo.lib.Region(t, r, b, l);
3032 adjust : function(t, l, b, r) {
3041 Roo.lib.Region.getRegion = function(el) {
3042 var p = Roo.lib.Dom.getXY(el);
3045 var r = p[0] + el.offsetWidth;
3046 var b = p[1] + el.offsetHeight;
3049 return new Roo.lib.Region(t, r, b, l);
3052 * Portions of this file are based on pieces of Yahoo User Interface Library
3053 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3054 * YUI licensed under the BSD License:
3055 * http://developer.yahoo.net/yui/license.txt
3056 * <script type="text/javascript">
3059 //@@dep Roo.lib.Region
3062 Roo.lib.Point = function(x, y) {
3063 if (x instanceof Array) {
3067 this.x = this.right = this.left = this[0] = x;
3068 this.y = this.top = this.bottom = this[1] = y;
3071 Roo.lib.Point.prototype = new Roo.lib.Region();
3073 * Portions of this file are based on pieces of Yahoo User Interface Library
3074 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3075 * YUI licensed under the BSD License:
3076 * http://developer.yahoo.net/yui/license.txt
3077 * <script type="text/javascript">
3084 scroll : function(el, args, duration, easing, cb, scope) {
3085 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3088 motion : function(el, args, duration, easing, cb, scope) {
3089 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3092 color : function(el, args, duration, easing, cb, scope) {
3093 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3096 run : function(el, args, duration, easing, cb, scope, type) {
3097 type = type || Roo.lib.AnimBase;
3098 if (typeof easing == "string") {
3099 easing = Roo.lib.Easing[easing];
3101 var anim = new type(el, args, duration, easing);
3102 anim.animateX(function() {
3103 Roo.callback(cb, scope);
3109 * Portions of this file are based on pieces of Yahoo User Interface Library
3110 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3111 * YUI licensed under the BSD License:
3112 * http://developer.yahoo.net/yui/license.txt
3113 * <script type="text/javascript">
3121 if (!libFlyweight) {
3122 libFlyweight = new Roo.Element.Flyweight();
3124 libFlyweight.dom = el;
3125 return libFlyweight;
3128 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3132 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3134 this.init(el, attributes, duration, method);
3138 Roo.lib.AnimBase.fly = fly;
3142 Roo.lib.AnimBase.prototype = {
3144 toString: function() {
3145 var el = this.getEl();
3146 var id = el.id || el.tagName;
3147 return ("Anim " + id);
3151 noNegatives: /width|height|opacity|padding/i,
3152 offsetAttribute: /^((width|height)|(top|left))$/,
3153 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3154 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3158 doMethod: function(attr, start, end) {
3159 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3163 setAttribute: function(attr, val, unit) {
3164 if (this.patterns.noNegatives.test(attr)) {
3165 val = (val > 0) ? val : 0;
3168 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3172 getAttribute: function(attr) {
3173 var el = this.getEl();
3174 var val = fly(el).getStyle(attr);
3176 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3177 return parseFloat(val);
3180 var a = this.patterns.offsetAttribute.exec(attr) || [];
3181 var pos = !!( a[3] );
3182 var box = !!( a[2] );
3185 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3186 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3195 getDefaultUnit: function(attr) {
3196 if (this.patterns.defaultUnit.test(attr)) {
3203 animateX : function(callback, scope) {
3204 var f = function() {
3205 this.onComplete.removeListener(f);
3206 if (typeof callback == "function") {
3207 callback.call(scope || this, this);
3210 this.onComplete.addListener(f, this);
3215 setRuntimeAttribute: function(attr) {
3218 var attributes = this.attributes;
3220 this.runtimeAttributes[attr] = {};
3222 var isset = function(prop) {
3223 return (typeof prop !== 'undefined');
3226 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3230 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3233 if (isset(attributes[attr]['to'])) {
3234 end = attributes[attr]['to'];
3235 } else if (isset(attributes[attr]['by'])) {
3236 if (start.constructor == Array) {
3238 for (var i = 0, len = start.length; i < len; ++i) {
3239 end[i] = start[i] + attributes[attr]['by'][i];
3242 end = start + attributes[attr]['by'];
3246 this.runtimeAttributes[attr].start = start;
3247 this.runtimeAttributes[attr].end = end;
3250 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3254 init: function(el, attributes, duration, method) {
3256 var isAnimated = false;
3259 var startTime = null;
3262 var actualFrames = 0;
3265 el = Roo.getDom(el);
3268 this.attributes = attributes || {};
3271 this.duration = duration || 1;
3274 this.method = method || Roo.lib.Easing.easeNone;
3277 this.useSeconds = true;
3280 this.currentFrame = 0;
3283 this.totalFrames = Roo.lib.AnimMgr.fps;
3286 this.getEl = function() {
3291 this.isAnimated = function() {
3296 this.getStartTime = function() {
3300 this.runtimeAttributes = {};
3303 this.animate = function() {
3304 if (this.isAnimated()) {
3308 this.currentFrame = 0;
3310 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3312 Roo.lib.AnimMgr.registerElement(this);
3316 this.stop = function(finish) {
3318 this.currentFrame = this.totalFrames;
3319 this._onTween.fire();
3321 Roo.lib.AnimMgr.stop(this);
3324 var onStart = function() {
3325 this.onStart.fire();
3327 this.runtimeAttributes = {};
3328 for (var attr in this.attributes) {
3329 this.setRuntimeAttribute(attr);
3334 startTime = new Date();
3338 var onTween = function() {
3340 duration: new Date() - this.getStartTime(),
3341 currentFrame: this.currentFrame
3344 data.toString = function() {
3346 'duration: ' + data.duration +
3347 ', currentFrame: ' + data.currentFrame
3351 this.onTween.fire(data);
3353 var runtimeAttributes = this.runtimeAttributes;
3355 for (var attr in runtimeAttributes) {
3356 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3362 var onComplete = function() {
3363 var actual_duration = (new Date() - startTime) / 1000 ;
3366 duration: actual_duration,
3367 frames: actualFrames,
3368 fps: actualFrames / actual_duration
3371 data.toString = function() {
3373 'duration: ' + data.duration +
3374 ', frames: ' + data.frames +
3375 ', fps: ' + data.fps
3381 this.onComplete.fire(data);
3385 this._onStart = new Roo.util.Event(this);
3386 this.onStart = new Roo.util.Event(this);
3387 this.onTween = new Roo.util.Event(this);
3388 this._onTween = new Roo.util.Event(this);
3389 this.onComplete = new Roo.util.Event(this);
3390 this._onComplete = new Roo.util.Event(this);
3391 this._onStart.addListener(onStart);
3392 this._onTween.addListener(onTween);
3393 this._onComplete.addListener(onComplete);
3398 * Portions of this file are based on pieces of Yahoo User Interface Library
3399 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3400 * YUI licensed under the BSD License:
3401 * http://developer.yahoo.net/yui/license.txt
3402 * <script type="text/javascript">
3406 Roo.lib.AnimMgr = new function() {
3423 this.registerElement = function(tween) {
3424 queue[queue.length] = tween;
3426 tween._onStart.fire();
3431 this.unRegister = function(tween, index) {
3432 tween._onComplete.fire();
3433 index = index || getIndex(tween);
3435 queue.splice(index, 1);
3439 if (tweenCount <= 0) {
3445 this.start = function() {
3446 if (thread === null) {
3447 thread = setInterval(this.run, this.delay);
3452 this.stop = function(tween) {
3454 clearInterval(thread);
3456 for (var i = 0, len = queue.length; i < len; ++i) {
3457 if (queue[0].isAnimated()) {
3458 this.unRegister(queue[0], 0);
3467 this.unRegister(tween);
3472 this.run = function() {
3473 for (var i = 0, len = queue.length; i < len; ++i) {
3474 var tween = queue[i];
3475 if (!tween || !tween.isAnimated()) {
3479 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3481 tween.currentFrame += 1;
3483 if (tween.useSeconds) {
3484 correctFrame(tween);
3486 tween._onTween.fire();
3489 Roo.lib.AnimMgr.stop(tween, i);
3494 var getIndex = function(anim) {
3495 for (var i = 0, len = queue.length; i < len; ++i) {
3496 if (queue[i] == anim) {
3504 var correctFrame = function(tween) {
3505 var frames = tween.totalFrames;
3506 var frame = tween.currentFrame;
3507 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3508 var elapsed = (new Date() - tween.getStartTime());
3511 if (elapsed < tween.duration * 1000) {
3512 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3514 tweak = frames - (frame + 1);
3516 if (tweak > 0 && isFinite(tweak)) {
3517 if (tween.currentFrame + tweak >= frames) {
3518 tweak = frames - (frame + 1);
3521 tween.currentFrame += tweak;
3527 * Portions of this file are based on pieces of Yahoo User Interface Library
3528 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3529 * YUI licensed under the BSD License:
3530 * http://developer.yahoo.net/yui/license.txt
3531 * <script type="text/javascript">
3534 Roo.lib.Bezier = new function() {
3536 this.getPosition = function(points, t) {
3537 var n = points.length;
3540 for (var i = 0; i < n; ++i) {
3541 tmp[i] = [points[i][0], points[i][1]];
3544 for (var j = 1; j < n; ++j) {
3545 for (i = 0; i < n - j; ++i) {
3546 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3547 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3551 return [ tmp[0][0], tmp[0][1] ];
3555 * Portions of this file are based on pieces of Yahoo User Interface Library
3556 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3557 * YUI licensed under the BSD License:
3558 * http://developer.yahoo.net/yui/license.txt
3559 * <script type="text/javascript">
3564 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3565 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3568 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3570 var fly = Roo.lib.AnimBase.fly;
3572 var superclass = Y.ColorAnim.superclass;
3573 var proto = Y.ColorAnim.prototype;
3575 proto.toString = function() {
3576 var el = this.getEl();
3577 var id = el.id || el.tagName;
3578 return ("ColorAnim " + id);
3581 proto.patterns.color = /color$/i;
3582 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3583 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3584 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3585 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3588 proto.parseColor = function(s) {
3589 if (s.length == 3) {
3593 var c = this.patterns.hex.exec(s);
3594 if (c && c.length == 4) {
3595 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3598 c = this.patterns.rgb.exec(s);
3599 if (c && c.length == 4) {
3600 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3603 c = this.patterns.hex3.exec(s);
3604 if (c && c.length == 4) {
3605 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3610 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3611 proto.getAttribute = function(attr) {
3612 var el = this.getEl();
3613 if (this.patterns.color.test(attr)) {
3614 var val = fly(el).getStyle(attr);
3616 if (this.patterns.transparent.test(val)) {
3617 var parent = el.parentNode;
3618 val = fly(parent).getStyle(attr);
3620 while (parent && this.patterns.transparent.test(val)) {
3621 parent = parent.parentNode;
3622 val = fly(parent).getStyle(attr);
3623 if (parent.tagName.toUpperCase() == 'HTML') {
3629 val = superclass.getAttribute.call(this, attr);
3634 proto.getAttribute = function(attr) {
3635 var el = this.getEl();
3636 if (this.patterns.color.test(attr)) {
3637 var val = fly(el).getStyle(attr);
3639 if (this.patterns.transparent.test(val)) {
3640 var parent = el.parentNode;
3641 val = fly(parent).getStyle(attr);
3643 while (parent && this.patterns.transparent.test(val)) {
3644 parent = parent.parentNode;
3645 val = fly(parent).getStyle(attr);
3646 if (parent.tagName.toUpperCase() == 'HTML') {
3652 val = superclass.getAttribute.call(this, attr);
3658 proto.doMethod = function(attr, start, end) {
3661 if (this.patterns.color.test(attr)) {
3663 for (var i = 0, len = start.length; i < len; ++i) {
3664 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3667 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3670 val = superclass.doMethod.call(this, attr, start, end);
3676 proto.setRuntimeAttribute = function(attr) {
3677 superclass.setRuntimeAttribute.call(this, attr);
3679 if (this.patterns.color.test(attr)) {
3680 var attributes = this.attributes;
3681 var start = this.parseColor(this.runtimeAttributes[attr].start);
3682 var end = this.parseColor(this.runtimeAttributes[attr].end);
3684 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3685 end = this.parseColor(attributes[attr].by);
3687 for (var i = 0, len = start.length; i < len; ++i) {
3688 end[i] = start[i] + end[i];
3692 this.runtimeAttributes[attr].start = start;
3693 this.runtimeAttributes[attr].end = end;
3699 * Portions of this file are based on pieces of Yahoo User Interface Library
3700 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3701 * YUI licensed under the BSD License:
3702 * http://developer.yahoo.net/yui/license.txt
3703 * <script type="text/javascript">
3709 easeNone: function (t, b, c, d) {
3710 return c * t / d + b;
3714 easeIn: function (t, b, c, d) {
3715 return c * (t /= d) * t + b;
3719 easeOut: function (t, b, c, d) {
3720 return -c * (t /= d) * (t - 2) + b;
3724 easeBoth: function (t, b, c, d) {
3725 if ((t /= d / 2) < 1) {
3726 return c / 2 * t * t + b;
3729 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3733 easeInStrong: function (t, b, c, d) {
3734 return c * (t /= d) * t * t * t + b;
3738 easeOutStrong: function (t, b, c, d) {
3739 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3743 easeBothStrong: function (t, b, c, d) {
3744 if ((t /= d / 2) < 1) {
3745 return c / 2 * t * t * t * t + b;
3748 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3753 elasticIn: function (t, b, c, d, a, p) {
3757 if ((t /= d) == 1) {
3764 if (!a || a < Math.abs(c)) {
3769 var s = p / (2 * Math.PI) * Math.asin(c / a);
3772 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3776 elasticOut: function (t, b, c, d, a, p) {
3780 if ((t /= d) == 1) {
3787 if (!a || a < Math.abs(c)) {
3792 var s = p / (2 * Math.PI) * Math.asin(c / a);
3795 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3799 elasticBoth: function (t, b, c, d, a, p) {
3804 if ((t /= d / 2) == 2) {
3812 if (!a || a < Math.abs(c)) {
3817 var s = p / (2 * Math.PI) * Math.asin(c / a);
3821 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3822 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3824 return a * Math.pow(2, -10 * (t -= 1)) *
3825 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3830 backIn: function (t, b, c, d, s) {
3831 if (typeof s == 'undefined') {
3834 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3838 backOut: function (t, b, c, d, s) {
3839 if (typeof s == 'undefined') {
3842 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3846 backBoth: function (t, b, c, d, s) {
3847 if (typeof s == 'undefined') {
3851 if ((t /= d / 2 ) < 1) {
3852 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3854 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3858 bounceIn: function (t, b, c, d) {
3859 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3863 bounceOut: function (t, b, c, d) {
3864 if ((t /= d) < (1 / 2.75)) {
3865 return c * (7.5625 * t * t) + b;
3866 } else if (t < (2 / 2.75)) {
3867 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3868 } else if (t < (2.5 / 2.75)) {
3869 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3871 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3875 bounceBoth: function (t, b, c, d) {
3877 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3879 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3882 * Portions of this file are based on pieces of Yahoo User Interface Library
3883 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3884 * YUI licensed under the BSD License:
3885 * http://developer.yahoo.net/yui/license.txt
3886 * <script type="text/javascript">
3890 Roo.lib.Motion = function(el, attributes, duration, method) {
3892 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3896 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3900 var superclass = Y.Motion.superclass;
3901 var proto = Y.Motion.prototype;
3903 proto.toString = function() {
3904 var el = this.getEl();
3905 var id = el.id || el.tagName;
3906 return ("Motion " + id);
3909 proto.patterns.points = /^points$/i;
3911 proto.setAttribute = function(attr, val, unit) {
3912 if (this.patterns.points.test(attr)) {
3913 unit = unit || 'px';
3914 superclass.setAttribute.call(this, 'left', val[0], unit);
3915 superclass.setAttribute.call(this, 'top', val[1], unit);
3917 superclass.setAttribute.call(this, attr, val, unit);
3921 proto.getAttribute = function(attr) {
3922 if (this.patterns.points.test(attr)) {
3924 superclass.getAttribute.call(this, 'left'),
3925 superclass.getAttribute.call(this, 'top')
3928 val = superclass.getAttribute.call(this, attr);
3934 proto.doMethod = function(attr, start, end) {
3937 if (this.patterns.points.test(attr)) {
3938 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3939 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3941 val = superclass.doMethod.call(this, attr, start, end);
3946 proto.setRuntimeAttribute = function(attr) {
3947 if (this.patterns.points.test(attr)) {
3948 var el = this.getEl();
3949 var attributes = this.attributes;
3951 var control = attributes['points']['control'] || [];
3955 if (control.length > 0 && !(control[0] instanceof Array)) {
3956 control = [control];
3959 for (i = 0,len = control.length; i < len; ++i) {
3960 tmp[i] = control[i];
3965 Roo.fly(el).position();
3967 if (isset(attributes['points']['from'])) {
3968 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3971 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3974 start = this.getAttribute('points');
3977 if (isset(attributes['points']['to'])) {
3978 end = translateValues.call(this, attributes['points']['to'], start);
3980 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3981 for (i = 0,len = control.length; i < len; ++i) {
3982 control[i] = translateValues.call(this, control[i], start);
3986 } else if (isset(attributes['points']['by'])) {
3987 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3989 for (i = 0,len = control.length; i < len; ++i) {
3990 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3994 this.runtimeAttributes[attr] = [start];
3996 if (control.length > 0) {
3997 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4000 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4003 superclass.setRuntimeAttribute.call(this, attr);
4007 var translateValues = function(val, start) {
4008 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4009 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4014 var isset = function(prop) {
4015 return (typeof prop !== 'undefined');
4019 * Portions of this file are based on pieces of Yahoo User Interface Library
4020 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4021 * YUI licensed under the BSD License:
4022 * http://developer.yahoo.net/yui/license.txt
4023 * <script type="text/javascript">
4027 Roo.lib.Scroll = function(el, attributes, duration, method) {
4029 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4033 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4037 var superclass = Y.Scroll.superclass;
4038 var proto = Y.Scroll.prototype;
4040 proto.toString = function() {
4041 var el = this.getEl();
4042 var id = el.id || el.tagName;
4043 return ("Scroll " + id);
4046 proto.doMethod = function(attr, start, end) {
4049 if (attr == 'scroll') {
4051 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4052 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4056 val = superclass.doMethod.call(this, attr, start, end);
4061 proto.getAttribute = function(attr) {
4063 var el = this.getEl();
4065 if (attr == 'scroll') {
4066 val = [ el.scrollLeft, el.scrollTop ];
4068 val = superclass.getAttribute.call(this, attr);
4074 proto.setAttribute = function(attr, val, unit) {
4075 var el = this.getEl();
4077 if (attr == 'scroll') {
4078 el.scrollLeft = val[0];
4079 el.scrollTop = val[1];
4081 superclass.setAttribute.call(this, attr, val, unit);
4087 * Ext JS Library 1.1.1
4088 * Copyright(c) 2006-2007, Ext JS, LLC.
4090 * Originally Released Under LGPL - original licence link has changed is not relivant.
4093 * <script type="text/javascript">
4097 // nasty IE9 hack - what a pile of crap that is..
4099 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4100 Range.prototype.createContextualFragment = function (html) {
4101 var doc = window.document;
4102 var container = doc.createElement("div");
4103 container.innerHTML = html;
4104 var frag = doc.createDocumentFragment(), n;
4105 while ((n = container.firstChild)) {
4106 frag.appendChild(n);
4113 * @class Roo.DomHelper
4114 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4115 * 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>.
4118 Roo.DomHelper = function(){
4119 var tempTableEl = null;
4120 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4121 var tableRe = /^table|tbody|tr|td$/i;
4123 // build as innerHTML where available
4125 var createHtml = function(o){
4126 if(typeof o == 'string'){
4135 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4136 if(attr == "style"){
4138 if(typeof s == "function"){
4141 if(typeof s == "string"){
4142 b += ' style="' + s + '"';
4143 }else if(typeof s == "object"){
4146 if(typeof s[key] != "function"){
4147 b += key + ":" + s[key] + ";";
4154 b += ' class="' + o["cls"] + '"';
4155 }else if(attr == "htmlFor"){
4156 b += ' for="' + o["htmlFor"] + '"';
4158 b += " " + attr + '="' + o[attr] + '"';
4162 if(emptyTags.test(o.tag)){
4166 var cn = o.children || o.cn;
4168 //http://bugs.kde.org/show_bug.cgi?id=71506
4169 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4170 for(var i = 0, len = cn.length; i < len; i++) {
4171 b += createHtml(cn[i], b);
4174 b += createHtml(cn, b);
4180 b += "</" + o.tag + ">";
4187 var createDom = function(o, parentNode){
4189 // defininition craeted..
4191 if (o.ns && o.ns != 'html') {
4193 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4194 xmlns[o.ns] = o.xmlns;
4197 if (typeof(xmlns[o.ns]) == 'undefined') {
4198 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4204 if (typeof(o) == 'string') {
4205 return parentNode.appendChild(document.createTextNode(o));
4207 o.tag = o.tag || div;
4208 if (o.ns && Roo.isIE) {
4210 o.tag = o.ns + ':' + o.tag;
4213 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4214 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4217 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4218 attr == "style" || typeof o[attr] == "function") continue;
4220 if(attr=="cls" && Roo.isIE){
4221 el.className = o["cls"];
4223 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4224 else el[attr] = o[attr];
4227 Roo.DomHelper.applyStyles(el, o.style);
4228 var cn = o.children || o.cn;
4230 //http://bugs.kde.org/show_bug.cgi?id=71506
4231 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4232 for(var i = 0, len = cn.length; i < len; i++) {
4233 createDom(cn[i], el);
4240 el.innerHTML = o.html;
4243 parentNode.appendChild(el);
4248 var ieTable = function(depth, s, h, e){
4249 tempTableEl.innerHTML = [s, h, e].join('');
4250 var i = -1, el = tempTableEl;
4257 // kill repeat to save bytes
4261 tbe = '</tbody>'+te,
4267 * Nasty code for IE's broken table implementation
4269 var insertIntoTable = function(tag, where, el, html){
4271 tempTableEl = document.createElement('div');
4276 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4279 if(where == 'beforebegin'){
4283 before = el.nextSibling;
4286 node = ieTable(4, trs, html, tre);
4288 else if(tag == 'tr'){
4289 if(where == 'beforebegin'){
4292 node = ieTable(3, tbs, html, tbe);
4293 } else if(where == 'afterend'){
4294 before = el.nextSibling;
4296 node = ieTable(3, tbs, html, tbe);
4297 } else{ // INTO a TR
4298 if(where == 'afterbegin'){
4299 before = el.firstChild;
4301 node = ieTable(4, trs, html, tre);
4303 } else if(tag == 'tbody'){
4304 if(where == 'beforebegin'){
4307 node = ieTable(2, ts, html, te);
4308 } else if(where == 'afterend'){
4309 before = el.nextSibling;
4311 node = ieTable(2, ts, html, te);
4313 if(where == 'afterbegin'){
4314 before = el.firstChild;
4316 node = ieTable(3, tbs, html, tbe);
4319 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4322 if(where == 'afterbegin'){
4323 before = el.firstChild;
4325 node = ieTable(2, ts, html, te);
4327 el.insertBefore(node, before);
4332 /** True to force the use of DOM instead of html fragments @type Boolean */
4336 * Returns the markup for the passed Element(s) config
4337 * @param {Object} o The Dom object spec (and children)
4340 markup : function(o){
4341 return createHtml(o);
4345 * Applies a style specification to an element
4346 * @param {String/HTMLElement} el The element to apply styles to
4347 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4348 * a function which returns such a specification.
4350 applyStyles : function(el, styles){
4353 if(typeof styles == "string"){
4354 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4356 while ((matches = re.exec(styles)) != null){
4357 el.setStyle(matches[1], matches[2]);
4359 }else if (typeof styles == "object"){
4360 for (var style in styles){
4361 el.setStyle(style, styles[style]);
4363 }else if (typeof styles == "function"){
4364 Roo.DomHelper.applyStyles(el, styles.call());
4370 * Inserts an HTML fragment into the Dom
4371 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4372 * @param {HTMLElement} el The context element
4373 * @param {String} html The HTML fragmenet
4374 * @return {HTMLElement} The new node
4376 insertHtml : function(where, el, html){
4377 where = where.toLowerCase();
4378 if(el.insertAdjacentHTML){
4379 if(tableRe.test(el.tagName)){
4381 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4387 el.insertAdjacentHTML('BeforeBegin', html);
4388 return el.previousSibling;
4390 el.insertAdjacentHTML('AfterBegin', html);
4391 return el.firstChild;
4393 el.insertAdjacentHTML('BeforeEnd', html);
4394 return el.lastChild;
4396 el.insertAdjacentHTML('AfterEnd', html);
4397 return el.nextSibling;
4399 throw 'Illegal insertion point -> "' + where + '"';
4401 var range = el.ownerDocument.createRange();
4405 range.setStartBefore(el);
4406 frag = range.createContextualFragment(html);
4407 el.parentNode.insertBefore(frag, el);
4408 return el.previousSibling;
4411 range.setStartBefore(el.firstChild);
4412 frag = range.createContextualFragment(html);
4413 el.insertBefore(frag, el.firstChild);
4414 return el.firstChild;
4416 el.innerHTML = html;
4417 return el.firstChild;
4421 range.setStartAfter(el.lastChild);
4422 frag = range.createContextualFragment(html);
4423 el.appendChild(frag);
4424 return el.lastChild;
4426 el.innerHTML = html;
4427 return el.lastChild;
4430 range.setStartAfter(el);
4431 frag = range.createContextualFragment(html);
4432 el.parentNode.insertBefore(frag, el.nextSibling);
4433 return el.nextSibling;
4435 throw 'Illegal insertion point -> "' + where + '"';
4439 * Creates new Dom element(s) and inserts them before el
4440 * @param {String/HTMLElement/Element} el The context element
4441 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4442 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4443 * @return {HTMLElement/Roo.Element} The new node
4445 insertBefore : function(el, o, returnElement){
4446 return this.doInsert(el, o, returnElement, "beforeBegin");
4450 * Creates new Dom element(s) and inserts them after el
4451 * @param {String/HTMLElement/Element} el The context element
4452 * @param {Object} o The Dom object spec (and children)
4453 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4454 * @return {HTMLElement/Roo.Element} The new node
4456 insertAfter : function(el, o, returnElement){
4457 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4461 * Creates new Dom element(s) and inserts them as the first child of el
4462 * @param {String/HTMLElement/Element} el The context element
4463 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4464 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4465 * @return {HTMLElement/Roo.Element} The new node
4467 insertFirst : function(el, o, returnElement){
4468 return this.doInsert(el, o, returnElement, "afterBegin");
4472 doInsert : function(el, o, returnElement, pos, sibling){
4473 el = Roo.getDom(el);
4475 if(this.useDom || o.ns){
4476 newNode = createDom(o, null);
4477 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4479 var html = createHtml(o);
4480 newNode = this.insertHtml(pos, el, html);
4482 return returnElement ? Roo.get(newNode, true) : newNode;
4486 * Creates new Dom element(s) and appends them to el
4487 * @param {String/HTMLElement/Element} el The context element
4488 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4489 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4490 * @return {HTMLElement/Roo.Element} The new node
4492 append : function(el, o, returnElement){
4493 el = Roo.getDom(el);
4495 if(this.useDom || o.ns){
4496 newNode = createDom(o, null);
4497 el.appendChild(newNode);
4499 var html = createHtml(o);
4500 newNode = this.insertHtml("beforeEnd", el, html);
4502 return returnElement ? Roo.get(newNode, true) : newNode;
4506 * Creates new Dom element(s) and overwrites the contents of el with them
4507 * @param {String/HTMLElement/Element} el The context element
4508 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4509 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4510 * @return {HTMLElement/Roo.Element} The new node
4512 overwrite : function(el, o, returnElement){
4513 el = Roo.getDom(el);
4516 while (el.childNodes.length) {
4517 el.removeChild(el.firstChild);
4521 el.innerHTML = createHtml(o);
4524 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4528 * Creates a new Roo.DomHelper.Template from the Dom object spec
4529 * @param {Object} o The Dom object spec (and children)
4530 * @return {Roo.DomHelper.Template} The new template
4532 createTemplate : function(o){
4533 var html = createHtml(o);
4534 return new Roo.Template(html);
4540 * Ext JS Library 1.1.1
4541 * Copyright(c) 2006-2007, Ext JS, LLC.
4543 * Originally Released Under LGPL - original licence link has changed is not relivant.
4546 * <script type="text/javascript">
4550 * @class Roo.Template
4551 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4552 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4555 var t = new Roo.Template({
4556 html : '<div name="{id}">' +
4557 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4559 myformat: function (value, allValues) {
4560 return 'XX' + value;
4563 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4565 * For more information see this blog post with examples:
4566 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4567 - Create Elements using DOM, HTML fragments and Templates</a>.
4569 * @param {Object} cfg - Configuration object.
4571 Roo.Template = function(cfg){
4573 if(cfg instanceof Array){
4575 }else if(arguments.length > 1){
4576 cfg = Array.prototype.join.call(arguments, "");
4580 if (typeof(cfg) == 'object') {
4591 Roo.Template.prototype = {
4594 * @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..
4595 * it should be fixed so that template is observable...
4599 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4603 * Returns an HTML fragment of this template with the specified values applied.
4604 * @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'})
4605 * @return {String} The HTML fragment
4607 applyTemplate : function(values){
4611 return this.compiled(values);
4613 var useF = this.disableFormats !== true;
4614 var fm = Roo.util.Format, tpl = this;
4615 var fn = function(m, name, format, args){
4617 if(format.substr(0, 5) == "this."){
4618 return tpl.call(format.substr(5), values[name], values);
4621 // quoted values are required for strings in compiled templates,
4622 // but for non compiled we need to strip them
4623 // quoted reversed for jsmin
4624 var re = /^\s*['"](.*)["']\s*$/;
4625 args = args.split(',');
4626 for(var i = 0, len = args.length; i < len; i++){
4627 args[i] = args[i].replace(re, "$1");
4629 args = [values[name]].concat(args);
4631 args = [values[name]];
4633 return fm[format].apply(fm, args);
4636 return values[name] !== undefined ? values[name] : "";
4639 return this.html.replace(this.re, fn);
4657 this.loading = true;
4658 this.compiled = false;
4660 var cx = new Roo.data.Connection();
4664 success : function (response) {
4666 _t.html = response.responseText;
4670 failure : function(response) {
4671 Roo.log("Template failed to load from " + _t.url);
4678 * Sets the HTML used as the template and optionally compiles it.
4679 * @param {String} html
4680 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4681 * @return {Roo.Template} this
4683 set : function(html, compile){
4685 this.compiled = null;
4693 * True to disable format functions (defaults to false)
4696 disableFormats : false,
4699 * The regular expression used to match template variables
4703 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4706 * Compiles the template into an internal function, eliminating the RegEx overhead.
4707 * @return {Roo.Template} this
4709 compile : function(){
4710 var fm = Roo.util.Format;
4711 var useF = this.disableFormats !== true;
4712 var sep = Roo.isGecko ? "+" : ",";
4713 var fn = function(m, name, format, args){
4715 args = args ? ',' + args : "";
4716 if(format.substr(0, 5) != "this."){
4717 format = "fm." + format + '(';
4719 format = 'this.call("'+ format.substr(5) + '", ';
4723 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4725 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4728 // branched to use + in gecko and [].join() in others
4730 body = "this.compiled = function(values){ return '" +
4731 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4734 body = ["this.compiled = function(values){ return ['"];
4735 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4736 body.push("'].join('');};");
4737 body = body.join('');
4747 // private function used to call members
4748 call : function(fnName, value, allValues){
4749 return this[fnName](value, allValues);
4753 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4754 * @param {String/HTMLElement/Roo.Element} el The context element
4755 * @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'})
4756 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4757 * @return {HTMLElement/Roo.Element} The new node or Element
4759 insertFirst: function(el, values, returnElement){
4760 return this.doInsert('afterBegin', el, values, returnElement);
4764 * Applies the supplied values to the template and inserts the new node(s) before el.
4765 * @param {String/HTMLElement/Roo.Element} el The context element
4766 * @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'})
4767 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4768 * @return {HTMLElement/Roo.Element} The new node or Element
4770 insertBefore: function(el, values, returnElement){
4771 return this.doInsert('beforeBegin', el, values, returnElement);
4775 * Applies the supplied values to the template and inserts the new node(s) after el.
4776 * @param {String/HTMLElement/Roo.Element} el The context element
4777 * @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'})
4778 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4779 * @return {HTMLElement/Roo.Element} The new node or Element
4781 insertAfter : function(el, values, returnElement){
4782 return this.doInsert('afterEnd', el, values, returnElement);
4786 * Applies the supplied values to the template and appends the new node(s) to el.
4787 * @param {String/HTMLElement/Roo.Element} el The context element
4788 * @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'})
4789 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4790 * @return {HTMLElement/Roo.Element} The new node or Element
4792 append : function(el, values, returnElement){
4793 return this.doInsert('beforeEnd', el, values, returnElement);
4796 doInsert : function(where, el, values, returnEl){
4797 el = Roo.getDom(el);
4798 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4799 return returnEl ? Roo.get(newNode, true) : newNode;
4803 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4804 * @param {String/HTMLElement/Roo.Element} el The context element
4805 * @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'})
4806 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4807 * @return {HTMLElement/Roo.Element} The new node or Element
4809 overwrite : function(el, values, returnElement){
4810 el = Roo.getDom(el);
4811 el.innerHTML = this.applyTemplate(values);
4812 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4816 * Alias for {@link #applyTemplate}
4819 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4822 Roo.DomHelper.Template = Roo.Template;
4825 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4826 * @param {String/HTMLElement} el A DOM element or its id
4827 * @returns {Roo.Template} The created template
4830 Roo.Template.from = function(el){
4831 el = Roo.getDom(el);
4832 return new Roo.Template(el.value || el.innerHTML);
4835 * Ext JS Library 1.1.1
4836 * Copyright(c) 2006-2007, Ext JS, LLC.
4838 * Originally Released Under LGPL - original licence link has changed is not relivant.
4841 * <script type="text/javascript">
4846 * This is code is also distributed under MIT license for use
4847 * with jQuery and prototype JavaScript libraries.
4850 * @class Roo.DomQuery
4851 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).
4853 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>
4856 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.
4858 <h4>Element Selectors:</h4>
4860 <li> <b>*</b> any element</li>
4861 <li> <b>E</b> an element with the tag E</li>
4862 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4863 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4864 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4865 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4867 <h4>Attribute Selectors:</h4>
4868 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4870 <li> <b>E[foo]</b> has an attribute "foo"</li>
4871 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4872 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4873 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4874 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4875 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4876 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4878 <h4>Pseudo Classes:</h4>
4880 <li> <b>E:first-child</b> E is the first child of its parent</li>
4881 <li> <b>E:last-child</b> E is the last child of its parent</li>
4882 <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>
4883 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4884 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4885 <li> <b>E:only-child</b> E is the only child of its parent</li>
4886 <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>
4887 <li> <b>E:first</b> the first E in the resultset</li>
4888 <li> <b>E:last</b> the last E in the resultset</li>
4889 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4890 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4891 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4892 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4893 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4894 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4895 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4896 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4897 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4899 <h4>CSS Value Selectors:</h4>
4901 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4902 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4903 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4904 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4905 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4906 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4910 Roo.DomQuery = function(){
4911 var cache = {}, simpleCache = {}, valueCache = {};
4912 var nonSpace = /\S/;
4913 var trimRe = /^\s+|\s+$/g;
4914 var tplRe = /\{(\d+)\}/g;
4915 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4916 var tagTokenRe = /^(#)?([\w-\*]+)/;
4917 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4919 function child(p, index){
4921 var n = p.firstChild;
4923 if(n.nodeType == 1){
4934 while((n = n.nextSibling) && n.nodeType != 1);
4939 while((n = n.previousSibling) && n.nodeType != 1);
4943 function children(d){
4944 var n = d.firstChild, ni = -1;
4946 var nx = n.nextSibling;
4947 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4957 function byClassName(c, a, v){
4961 var r = [], ri = -1, cn;
4962 for(var i = 0, ci; ci = c[i]; i++){
4963 if((' '+ci.className+' ').indexOf(v) != -1){
4970 function attrValue(n, attr){
4971 if(!n.tagName && typeof n.length != "undefined"){
4980 if(attr == "class" || attr == "className"){
4983 return n.getAttribute(attr) || n[attr];
4987 function getNodes(ns, mode, tagName){
4988 var result = [], ri = -1, cs;
4992 tagName = tagName || "*";
4993 if(typeof ns.getElementsByTagName != "undefined"){
4997 for(var i = 0, ni; ni = ns[i]; i++){
4998 cs = ni.getElementsByTagName(tagName);
4999 for(var j = 0, ci; ci = cs[j]; j++){
5003 }else if(mode == "/" || mode == ">"){
5004 var utag = tagName.toUpperCase();
5005 for(var i = 0, ni, cn; ni = ns[i]; i++){
5006 cn = ni.children || ni.childNodes;
5007 for(var j = 0, cj; cj = cn[j]; j++){
5008 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5013 }else if(mode == "+"){
5014 var utag = tagName.toUpperCase();
5015 for(var i = 0, n; n = ns[i]; i++){
5016 while((n = n.nextSibling) && n.nodeType != 1);
5017 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5021 }else if(mode == "~"){
5022 for(var i = 0, n; n = ns[i]; i++){
5023 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5032 function concat(a, b){
5036 for(var i = 0, l = b.length; i < l; i++){
5042 function byTag(cs, tagName){
5043 if(cs.tagName || cs == document){
5049 var r = [], ri = -1;
5050 tagName = tagName.toLowerCase();
5051 for(var i = 0, ci; ci = cs[i]; i++){
5052 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5059 function byId(cs, attr, id){
5060 if(cs.tagName || cs == document){
5066 var r = [], ri = -1;
5067 for(var i = 0,ci; ci = cs[i]; i++){
5068 if(ci && ci.id == id){
5076 function byAttribute(cs, attr, value, op, custom){
5077 var r = [], ri = -1, st = custom=="{";
5078 var f = Roo.DomQuery.operators[op];
5079 for(var i = 0, ci; ci = cs[i]; i++){
5082 a = Roo.DomQuery.getStyle(ci, attr);
5084 else if(attr == "class" || attr == "className"){
5086 }else if(attr == "for"){
5088 }else if(attr == "href"){
5089 a = ci.getAttribute("href", 2);
5091 a = ci.getAttribute(attr);
5093 if((f && f(a, value)) || (!f && a)){
5100 function byPseudo(cs, name, value){
5101 return Roo.DomQuery.pseudos[name](cs, value);
5104 // This is for IE MSXML which does not support expandos.
5105 // IE runs the same speed using setAttribute, however FF slows way down
5106 // and Safari completely fails so they need to continue to use expandos.
5107 var isIE = window.ActiveXObject ? true : false;
5109 // this eval is stop the compressor from
5110 // renaming the variable to something shorter
5112 /** eval:var:batch */
5117 function nodupIEXml(cs){
5119 cs[0].setAttribute("_nodup", d);
5121 for(var i = 1, len = cs.length; i < len; i++){
5123 if(!c.getAttribute("_nodup") != d){
5124 c.setAttribute("_nodup", d);
5128 for(var i = 0, len = cs.length; i < len; i++){
5129 cs[i].removeAttribute("_nodup");
5138 var len = cs.length, c, i, r = cs, cj, ri = -1;
5139 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5142 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5143 return nodupIEXml(cs);
5147 for(i = 1; c = cs[i]; i++){
5152 for(var j = 0; j < i; j++){
5155 for(j = i+1; cj = cs[j]; j++){
5167 function quickDiffIEXml(c1, c2){
5169 for(var i = 0, len = c1.length; i < len; i++){
5170 c1[i].setAttribute("_qdiff", d);
5173 for(var i = 0, len = c2.length; i < len; i++){
5174 if(c2[i].getAttribute("_qdiff") != d){
5175 r[r.length] = c2[i];
5178 for(var i = 0, len = c1.length; i < len; i++){
5179 c1[i].removeAttribute("_qdiff");
5184 function quickDiff(c1, c2){
5185 var len1 = c1.length;
5189 if(isIE && c1[0].selectSingleNode){
5190 return quickDiffIEXml(c1, c2);
5193 for(var i = 0; i < len1; i++){
5197 for(var i = 0, len = c2.length; i < len; i++){
5198 if(c2[i]._qdiff != d){
5199 r[r.length] = c2[i];
5205 function quickId(ns, mode, root, id){
5207 var d = root.ownerDocument || root;
5208 return d.getElementById(id);
5210 ns = getNodes(ns, mode, "*");
5211 return byId(ns, null, id);
5215 getStyle : function(el, name){
5216 return Roo.fly(el).getStyle(name);
5219 * Compiles a selector/xpath query into a reusable function. The returned function
5220 * takes one parameter "root" (optional), which is the context node from where the query should start.
5221 * @param {String} selector The selector/xpath query
5222 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5223 * @return {Function}
5225 compile : function(path, type){
5226 type = type || "select";
5228 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5229 var q = path, mode, lq;
5230 var tk = Roo.DomQuery.matchers;
5231 var tklen = tk.length;
5234 // accept leading mode switch
5235 var lmode = q.match(modeRe);
5236 if(lmode && lmode[1]){
5237 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5238 q = q.replace(lmode[1], "");
5240 // strip leading slashes
5241 while(path.substr(0, 1)=="/"){
5242 path = path.substr(1);
5245 while(q && lq != q){
5247 var tm = q.match(tagTokenRe);
5248 if(type == "select"){
5251 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5253 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5255 q = q.replace(tm[0], "");
5256 }else if(q.substr(0, 1) != '@'){
5257 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5262 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5264 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5266 q = q.replace(tm[0], "");
5269 while(!(mm = q.match(modeRe))){
5270 var matched = false;
5271 for(var j = 0; j < tklen; j++){
5273 var m = q.match(t.re);
5275 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5278 q = q.replace(m[0], "");
5283 // prevent infinite loop on bad selector
5285 throw 'Error parsing selector, parsing failed at "' + q + '"';
5289 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5290 q = q.replace(mm[1], "");
5293 fn[fn.length] = "return nodup(n);\n}";
5296 * list of variables that need from compression as they are used by eval.
5306 * eval:var:byClassName
5308 * eval:var:byAttribute
5309 * eval:var:attrValue
5317 * Selects a group of elements.
5318 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5319 * @param {Node} root (optional) The start of the query (defaults to document).
5322 select : function(path, root, type){
5323 if(!root || root == document){
5326 if(typeof root == "string"){
5327 root = document.getElementById(root);
5329 var paths = path.split(",");
5331 for(var i = 0, len = paths.length; i < len; i++){
5332 var p = paths[i].replace(trimRe, "");
5334 cache[p] = Roo.DomQuery.compile(p);
5336 throw p + " is not a valid selector";
5339 var result = cache[p](root);
5340 if(result && result != document){
5341 results = results.concat(result);
5344 if(paths.length > 1){
5345 return nodup(results);
5351 * Selects a single element.
5352 * @param {String} selector The selector/xpath query
5353 * @param {Node} root (optional) The start of the query (defaults to document).
5356 selectNode : function(path, root){
5357 return Roo.DomQuery.select(path, root)[0];
5361 * Selects the value of a node, optionally replacing null with the defaultValue.
5362 * @param {String} selector The selector/xpath query
5363 * @param {Node} root (optional) The start of the query (defaults to document).
5364 * @param {String} defaultValue
5366 selectValue : function(path, root, defaultValue){
5367 path = path.replace(trimRe, "");
5368 if(!valueCache[path]){
5369 valueCache[path] = Roo.DomQuery.compile(path, "select");
5371 var n = valueCache[path](root);
5372 n = n[0] ? n[0] : n;
5373 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5374 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5378 * Selects the value of a node, parsing integers and floats.
5379 * @param {String} selector The selector/xpath query
5380 * @param {Node} root (optional) The start of the query (defaults to document).
5381 * @param {Number} defaultValue
5384 selectNumber : function(path, root, defaultValue){
5385 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5386 return parseFloat(v);
5390 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5391 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5392 * @param {String} selector The simple selector to test
5395 is : function(el, ss){
5396 if(typeof el == "string"){
5397 el = document.getElementById(el);
5399 var isArray = (el instanceof Array);
5400 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5401 return isArray ? (result.length == el.length) : (result.length > 0);
5405 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5406 * @param {Array} el An array of elements to filter
5407 * @param {String} selector The simple selector to test
5408 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5409 * the selector instead of the ones that match
5412 filter : function(els, ss, nonMatches){
5413 ss = ss.replace(trimRe, "");
5414 if(!simpleCache[ss]){
5415 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5417 var result = simpleCache[ss](els);
5418 return nonMatches ? quickDiff(result, els) : result;
5422 * Collection of matching regular expressions and code snippets.
5426 select: 'n = byClassName(n, null, " {1} ");'
5428 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5429 select: 'n = byPseudo(n, "{1}", "{2}");'
5431 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5432 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5435 select: 'n = byId(n, null, "{1}");'
5438 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5443 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5444 * 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, > <.
5447 "=" : function(a, v){
5450 "!=" : function(a, v){
5453 "^=" : function(a, v){
5454 return a && a.substr(0, v.length) == v;
5456 "$=" : function(a, v){
5457 return a && a.substr(a.length-v.length) == v;
5459 "*=" : function(a, v){
5460 return a && a.indexOf(v) !== -1;
5462 "%=" : function(a, v){
5463 return (a % v) == 0;
5465 "|=" : function(a, v){
5466 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5468 "~=" : function(a, v){
5469 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5474 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5475 * and the argument (if any) supplied in the selector.
5478 "first-child" : function(c){
5479 var r = [], ri = -1, n;
5480 for(var i = 0, ci; ci = n = c[i]; i++){
5481 while((n = n.previousSibling) && n.nodeType != 1);
5489 "last-child" : function(c){
5490 var r = [], ri = -1, n;
5491 for(var i = 0, ci; ci = n = c[i]; i++){
5492 while((n = n.nextSibling) && n.nodeType != 1);
5500 "nth-child" : function(c, a) {
5501 var r = [], ri = -1;
5502 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5503 var f = (m[1] || 1) - 0, l = m[2] - 0;
5504 for(var i = 0, n; n = c[i]; i++){
5505 var pn = n.parentNode;
5506 if (batch != pn._batch) {
5508 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5509 if(cn.nodeType == 1){
5516 if (l == 0 || n.nodeIndex == l){
5519 } else if ((n.nodeIndex + l) % f == 0){
5527 "only-child" : function(c){
5528 var r = [], ri = -1;;
5529 for(var i = 0, ci; ci = c[i]; i++){
5530 if(!prev(ci) && !next(ci)){
5537 "empty" : function(c){
5538 var r = [], ri = -1;
5539 for(var i = 0, ci; ci = c[i]; i++){
5540 var cns = ci.childNodes, j = 0, cn, empty = true;
5543 if(cn.nodeType == 1 || cn.nodeType == 3){
5555 "contains" : function(c, v){
5556 var r = [], ri = -1;
5557 for(var i = 0, ci; ci = c[i]; i++){
5558 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5565 "nodeValue" : function(c, v){
5566 var r = [], ri = -1;
5567 for(var i = 0, ci; ci = c[i]; i++){
5568 if(ci.firstChild && ci.firstChild.nodeValue == v){
5575 "checked" : function(c){
5576 var r = [], ri = -1;
5577 for(var i = 0, ci; ci = c[i]; i++){
5578 if(ci.checked == true){
5585 "not" : function(c, ss){
5586 return Roo.DomQuery.filter(c, ss, true);
5589 "odd" : function(c){
5590 return this["nth-child"](c, "odd");
5593 "even" : function(c){
5594 return this["nth-child"](c, "even");
5597 "nth" : function(c, a){
5598 return c[a-1] || [];
5601 "first" : function(c){
5605 "last" : function(c){
5606 return c[c.length-1] || [];
5609 "has" : function(c, ss){
5610 var s = Roo.DomQuery.select;
5611 var r = [], ri = -1;
5612 for(var i = 0, ci; ci = c[i]; i++){
5613 if(s(ss, ci).length > 0){
5620 "next" : function(c, ss){
5621 var is = Roo.DomQuery.is;
5622 var r = [], ri = -1;
5623 for(var i = 0, ci; ci = c[i]; i++){
5632 "prev" : function(c, ss){
5633 var is = Roo.DomQuery.is;
5634 var r = [], ri = -1;
5635 for(var i = 0, ci; ci = c[i]; i++){
5648 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5649 * @param {String} path The selector/xpath query
5650 * @param {Node} root (optional) The start of the query (defaults to document).
5655 Roo.query = Roo.DomQuery.select;
5658 * Ext JS Library 1.1.1
5659 * Copyright(c) 2006-2007, Ext JS, LLC.
5661 * Originally Released Under LGPL - original licence link has changed is not relivant.
5664 * <script type="text/javascript">
5668 * @class Roo.util.Observable
5669 * Base class that provides a common interface for publishing events. Subclasses are expected to
5670 * to have a property "events" with all the events defined.<br>
5673 Employee = function(name){
5680 Roo.extend(Employee, Roo.util.Observable);
5682 * @param {Object} config properties to use (incuding events / listeners)
5685 Roo.util.Observable = function(cfg){
5688 this.addEvents(cfg.events || {});
5690 delete cfg.events; // make sure
5693 Roo.apply(this, cfg);
5696 this.on(this.listeners);
5697 delete this.listeners;
5700 Roo.util.Observable.prototype = {
5702 * @cfg {Object} listeners list of events and functions to call for this object,
5706 'click' : function(e) {
5716 * Fires the specified event with the passed parameters (minus the event name).
5717 * @param {String} eventName
5718 * @param {Object...} args Variable number of parameters are passed to handlers
5719 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5721 fireEvent : function(){
5722 var ce = this.events[arguments[0].toLowerCase()];
5723 if(typeof ce == "object"){
5724 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5731 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5734 * Appends an event handler to this component
5735 * @param {String} eventName The type of event to listen for
5736 * @param {Function} handler The method the event invokes
5737 * @param {Object} scope (optional) The scope in which to execute the handler
5738 * function. The handler function's "this" context.
5739 * @param {Object} options (optional) An object containing handler configuration
5740 * properties. This may contain any of the following properties:<ul>
5741 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5742 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5743 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5744 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5745 * by the specified number of milliseconds. If the event fires again within that time, the original
5746 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5749 * <b>Combining Options</b><br>
5750 * Using the options argument, it is possible to combine different types of listeners:<br>
5752 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5754 el.on('click', this.onClick, this, {
5761 * <b>Attaching multiple handlers in 1 call</b><br>
5762 * The method also allows for a single argument to be passed which is a config object containing properties
5763 * which specify multiple handlers.
5772 fn: this.onMouseOver,
5776 fn: this.onMouseOut,
5782 * Or a shorthand syntax which passes the same scope object to all handlers:
5785 'click': this.onClick,
5786 'mouseover': this.onMouseOver,
5787 'mouseout': this.onMouseOut,
5792 addListener : function(eventName, fn, scope, o){
5793 if(typeof eventName == "object"){
5796 if(this.filterOptRe.test(e)){
5799 if(typeof o[e] == "function"){
5801 this.addListener(e, o[e], o.scope, o);
5803 // individual options
5804 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5809 o = (!o || typeof o == "boolean") ? {} : o;
5810 eventName = eventName.toLowerCase();
5811 var ce = this.events[eventName] || true;
5812 if(typeof ce == "boolean"){
5813 ce = new Roo.util.Event(this, eventName);
5814 this.events[eventName] = ce;
5816 ce.addListener(fn, scope, o);
5820 * Removes a listener
5821 * @param {String} eventName The type of event to listen for
5822 * @param {Function} handler The handler to remove
5823 * @param {Object} scope (optional) The scope (this object) for the handler
5825 removeListener : function(eventName, fn, scope){
5826 var ce = this.events[eventName.toLowerCase()];
5827 if(typeof ce == "object"){
5828 ce.removeListener(fn, scope);
5833 * Removes all listeners for this object
5835 purgeListeners : function(){
5836 for(var evt in this.events){
5837 if(typeof this.events[evt] == "object"){
5838 this.events[evt].clearListeners();
5843 relayEvents : function(o, events){
5844 var createHandler = function(ename){
5846 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5849 for(var i = 0, len = events.length; i < len; i++){
5850 var ename = events[i];
5851 if(!this.events[ename]){ this.events[ename] = true; };
5852 o.on(ename, createHandler(ename), this);
5857 * Used to define events on this Observable
5858 * @param {Object} object The object with the events defined
5860 addEvents : function(o){
5864 Roo.applyIf(this.events, o);
5868 * Checks to see if this object has any listeners for a specified event
5869 * @param {String} eventName The name of the event to check for
5870 * @return {Boolean} True if the event is being listened for, else false
5872 hasListener : function(eventName){
5873 var e = this.events[eventName];
5874 return typeof e == "object" && e.listeners.length > 0;
5878 * Appends an event handler to this element (shorthand for addListener)
5879 * @param {String} eventName The type of event to listen for
5880 * @param {Function} handler The method the event invokes
5881 * @param {Object} scope (optional) The scope in which to execute the handler
5882 * function. The handler function's "this" context.
5883 * @param {Object} options (optional)
5886 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5888 * Removes a listener (shorthand for removeListener)
5889 * @param {String} eventName The type of event to listen for
5890 * @param {Function} handler The handler to remove
5891 * @param {Object} scope (optional) The scope (this object) for the handler
5894 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5897 * Starts capture on the specified Observable. All events will be passed
5898 * to the supplied function with the event name + standard signature of the event
5899 * <b>before</b> the event is fired. If the supplied function returns false,
5900 * the event will not fire.
5901 * @param {Observable} o The Observable to capture
5902 * @param {Function} fn The function to call
5903 * @param {Object} scope (optional) The scope (this object) for the fn
5906 Roo.util.Observable.capture = function(o, fn, scope){
5907 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5911 * Removes <b>all</b> added captures from the Observable.
5912 * @param {Observable} o The Observable to release
5915 Roo.util.Observable.releaseCapture = function(o){
5916 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5921 var createBuffered = function(h, o, scope){
5922 var task = new Roo.util.DelayedTask();
5924 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5928 var createSingle = function(h, e, fn, scope){
5930 e.removeListener(fn, scope);
5931 return h.apply(scope, arguments);
5935 var createDelayed = function(h, o, scope){
5937 var args = Array.prototype.slice.call(arguments, 0);
5938 setTimeout(function(){
5939 h.apply(scope, args);
5944 Roo.util.Event = function(obj, name){
5947 this.listeners = [];
5950 Roo.util.Event.prototype = {
5951 addListener : function(fn, scope, options){
5952 var o = options || {};
5953 scope = scope || this.obj;
5954 if(!this.isListening(fn, scope)){
5955 var l = {fn: fn, scope: scope, options: o};
5958 h = createDelayed(h, o, scope);
5961 h = createSingle(h, this, fn, scope);
5964 h = createBuffered(h, o, scope);
5967 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5968 this.listeners.push(l);
5970 this.listeners = this.listeners.slice(0);
5971 this.listeners.push(l);
5976 findListener : function(fn, scope){
5977 scope = scope || this.obj;
5978 var ls = this.listeners;
5979 for(var i = 0, len = ls.length; i < len; i++){
5981 if(l.fn == fn && l.scope == scope){
5988 isListening : function(fn, scope){
5989 return this.findListener(fn, scope) != -1;
5992 removeListener : function(fn, scope){
5994 if((index = this.findListener(fn, scope)) != -1){
5996 this.listeners.splice(index, 1);
5998 this.listeners = this.listeners.slice(0);
5999 this.listeners.splice(index, 1);
6006 clearListeners : function(){
6007 this.listeners = [];
6011 var ls = this.listeners, scope, len = ls.length;
6014 var args = Array.prototype.slice.call(arguments, 0);
6015 for(var i = 0; i < len; i++){
6017 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6018 this.firing = false;
6022 this.firing = false;
6029 * Ext JS Library 1.1.1
6030 * Copyright(c) 2006-2007, Ext JS, LLC.
6032 * Originally Released Under LGPL - original licence link has changed is not relivant.
6035 * <script type="text/javascript">
6039 * @class Roo.EventManager
6040 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6041 * several useful events directly.
6042 * See {@link Roo.EventObject} for more details on normalized event objects.
6045 Roo.EventManager = function(){
6046 var docReadyEvent, docReadyProcId, docReadyState = false;
6047 var resizeEvent, resizeTask, textEvent, textSize;
6048 var E = Roo.lib.Event;
6049 var D = Roo.lib.Dom;
6054 var fireDocReady = function(){
6056 docReadyState = true;
6059 clearInterval(docReadyProcId);
6061 if(Roo.isGecko || Roo.isOpera) {
6062 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6065 var defer = document.getElementById("ie-deferred-loader");
6067 defer.onreadystatechange = null;
6068 defer.parentNode.removeChild(defer);
6072 docReadyEvent.fire();
6073 docReadyEvent.clearListeners();
6078 var initDocReady = function(){
6079 docReadyEvent = new Roo.util.Event();
6080 if(Roo.isGecko || Roo.isOpera) {
6081 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6083 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6084 var defer = document.getElementById("ie-deferred-loader");
6085 defer.onreadystatechange = function(){
6086 if(this.readyState == "complete"){
6090 }else if(Roo.isSafari){
6091 docReadyProcId = setInterval(function(){
6092 var rs = document.readyState;
6093 if(rs == "complete") {
6098 // no matter what, make sure it fires on load
6099 E.on(window, "load", fireDocReady);
6102 var createBuffered = function(h, o){
6103 var task = new Roo.util.DelayedTask(h);
6105 // create new event object impl so new events don't wipe out properties
6106 e = new Roo.EventObjectImpl(e);
6107 task.delay(o.buffer, h, null, [e]);
6111 var createSingle = function(h, el, ename, fn){
6113 Roo.EventManager.removeListener(el, ename, fn);
6118 var createDelayed = function(h, o){
6120 // create new event object impl so new events don't wipe out properties
6121 e = new Roo.EventObjectImpl(e);
6122 setTimeout(function(){
6127 var transitionEndVal = false;
6129 var transitionEnd = function()
6131 if (transitionEndVal) {
6132 return transitionEndVal;
6134 var el = document.createElement('div');
6136 var transEndEventNames = {
6137 WebkitTransition : 'webkitTransitionEnd',
6138 MozTransition : 'transitionend',
6139 OTransition : 'oTransitionEnd otransitionend',
6140 transition : 'transitionend'
6143 for (var name in transEndEventNames) {
6144 if (el.style[name] !== undefined) {
6145 transitionEndVal = transEndEventNames[name];
6146 return transitionEndVal ;
6152 var listen = function(element, ename, opt, fn, scope){
6153 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6154 fn = fn || o.fn; scope = scope || o.scope;
6155 var el = Roo.getDom(element);
6159 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6162 if (ename == 'transitionend') {
6163 ename = transitionEnd();
6165 var h = function(e){
6166 e = Roo.EventObject.setEvent(e);
6169 t = e.getTarget(o.delegate, el);
6176 if(o.stopEvent === true){
6179 if(o.preventDefault === true){
6182 if(o.stopPropagation === true){
6183 e.stopPropagation();
6186 if(o.normalized === false){
6190 fn.call(scope || el, e, t, o);
6193 h = createDelayed(h, o);
6196 h = createSingle(h, el, ename, fn);
6199 h = createBuffered(h, o);
6201 fn._handlers = fn._handlers || [];
6204 fn._handlers.push([Roo.id(el), ename, h]);
6209 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6210 el.addEventListener("DOMMouseScroll", h, false);
6211 E.on(window, 'unload', function(){
6212 el.removeEventListener("DOMMouseScroll", h, false);
6215 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6216 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6221 var stopListening = function(el, ename, fn){
6222 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6224 for(var i = 0, len = hds.length; i < len; i++){
6226 if(h[0] == id && h[1] == ename){
6233 E.un(el, ename, hd);
6234 el = Roo.getDom(el);
6235 if(ename == "mousewheel" && el.addEventListener){
6236 el.removeEventListener("DOMMouseScroll", hd, false);
6238 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6239 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6243 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6250 * @scope Roo.EventManager
6255 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6256 * object with a Roo.EventObject
6257 * @param {Function} fn The method the event invokes
6258 * @param {Object} scope An object that becomes the scope of the handler
6259 * @param {boolean} override If true, the obj passed in becomes
6260 * the execution scope of the listener
6261 * @return {Function} The wrapped function
6264 wrap : function(fn, scope, override){
6266 Roo.EventObject.setEvent(e);
6267 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6272 * Appends an event handler to an element (shorthand for addListener)
6273 * @param {String/HTMLElement} element The html element or id to assign the
6274 * @param {String} eventName The type of event to listen for
6275 * @param {Function} handler The method the event invokes
6276 * @param {Object} scope (optional) The scope in which to execute the handler
6277 * function. The handler function's "this" context.
6278 * @param {Object} options (optional) An object containing handler configuration
6279 * properties. This may contain any of the following properties:<ul>
6280 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6281 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6282 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6283 * <li>preventDefault {Boolean} True to prevent the default action</li>
6284 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6285 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6286 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6287 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6288 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6289 * by the specified number of milliseconds. If the event fires again within that time, the original
6290 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6293 * <b>Combining Options</b><br>
6294 * Using the options argument, it is possible to combine different types of listeners:<br>
6296 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6298 el.on('click', this.onClick, this, {
6305 * <b>Attaching multiple handlers in 1 call</b><br>
6306 * The method also allows for a single argument to be passed which is a config object containing properties
6307 * which specify multiple handlers.
6317 fn: this.onMouseOver
6326 * Or a shorthand syntax:<br>
6329 'click' : this.onClick,
6330 'mouseover' : this.onMouseOver,
6331 'mouseout' : this.onMouseOut
6335 addListener : function(element, eventName, fn, scope, options){
6336 if(typeof eventName == "object"){
6342 if(typeof o[e] == "function"){
6344 listen(element, e, o, o[e], o.scope);
6346 // individual options
6347 listen(element, e, o[e]);
6352 return listen(element, eventName, options, fn, scope);
6356 * Removes an event handler
6358 * @param {String/HTMLElement} element The id or html element to remove the
6360 * @param {String} eventName The type of event
6361 * @param {Function} fn
6362 * @return {Boolean} True if a listener was actually removed
6364 removeListener : function(element, eventName, fn){
6365 return stopListening(element, eventName, fn);
6369 * Fires when the document is ready (before onload and before images are loaded). Can be
6370 * accessed shorthanded Roo.onReady().
6371 * @param {Function} fn The method the event invokes
6372 * @param {Object} scope An object that becomes the scope of the handler
6373 * @param {boolean} options
6375 onDocumentReady : function(fn, scope, options){
6376 if(docReadyState){ // if it already fired
6377 docReadyEvent.addListener(fn, scope, options);
6378 docReadyEvent.fire();
6379 docReadyEvent.clearListeners();
6385 docReadyEvent.addListener(fn, scope, options);
6389 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6390 * @param {Function} fn The method the event invokes
6391 * @param {Object} scope An object that becomes the scope of the handler
6392 * @param {boolean} options
6394 onWindowResize : function(fn, scope, options){
6396 resizeEvent = new Roo.util.Event();
6397 resizeTask = new Roo.util.DelayedTask(function(){
6398 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6400 E.on(window, "resize", function(){
6402 resizeTask.delay(50);
6404 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6408 resizeEvent.addListener(fn, scope, options);
6412 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6413 * @param {Function} fn The method the event invokes
6414 * @param {Object} scope An object that becomes the scope of the handler
6415 * @param {boolean} options
6417 onTextResize : function(fn, scope, options){
6419 textEvent = new Roo.util.Event();
6420 var textEl = new Roo.Element(document.createElement('div'));
6421 textEl.dom.className = 'x-text-resize';
6422 textEl.dom.innerHTML = 'X';
6423 textEl.appendTo(document.body);
6424 textSize = textEl.dom.offsetHeight;
6425 setInterval(function(){
6426 if(textEl.dom.offsetHeight != textSize){
6427 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6429 }, this.textResizeInterval);
6431 textEvent.addListener(fn, scope, options);
6435 * Removes the passed window resize listener.
6436 * @param {Function} fn The method the event invokes
6437 * @param {Object} scope The scope of handler
6439 removeResizeListener : function(fn, scope){
6441 resizeEvent.removeListener(fn, scope);
6446 fireResize : function(){
6448 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6452 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6456 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6458 textResizeInterval : 50
6463 * @scopeAlias pub=Roo.EventManager
6467 * Appends an event handler to an element (shorthand for addListener)
6468 * @param {String/HTMLElement} element The html element or id to assign the
6469 * @param {String} eventName The type of event to listen for
6470 * @param {Function} handler The method the event invokes
6471 * @param {Object} scope (optional) The scope in which to execute the handler
6472 * function. The handler function's "this" context.
6473 * @param {Object} options (optional) An object containing handler configuration
6474 * properties. This may contain any of the following properties:<ul>
6475 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6476 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6477 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6478 * <li>preventDefault {Boolean} True to prevent the default action</li>
6479 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6480 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6481 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6482 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6483 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6484 * by the specified number of milliseconds. If the event fires again within that time, the original
6485 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6488 * <b>Combining Options</b><br>
6489 * Using the options argument, it is possible to combine different types of listeners:<br>
6491 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6493 el.on('click', this.onClick, this, {
6500 * <b>Attaching multiple handlers in 1 call</b><br>
6501 * The method also allows for a single argument to be passed which is a config object containing properties
6502 * which specify multiple handlers.
6512 fn: this.onMouseOver
6521 * Or a shorthand syntax:<br>
6524 'click' : this.onClick,
6525 'mouseover' : this.onMouseOver,
6526 'mouseout' : this.onMouseOut
6530 pub.on = pub.addListener;
6531 pub.un = pub.removeListener;
6533 pub.stoppedMouseDownEvent = new Roo.util.Event();
6537 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6538 * @param {Function} fn The method the event invokes
6539 * @param {Object} scope An object that becomes the scope of the handler
6540 * @param {boolean} override If true, the obj passed in becomes
6541 * the execution scope of the listener
6545 Roo.onReady = Roo.EventManager.onDocumentReady;
6547 Roo.onReady(function(){
6548 var bd = Roo.get(document.body);
6553 : Roo.isGecko ? "roo-gecko"
6554 : Roo.isOpera ? "roo-opera"
6555 : Roo.isSafari ? "roo-safari" : ""];
6558 cls.push("roo-mac");
6561 cls.push("roo-linux");
6563 if(Roo.isBorderBox){
6564 cls.push('roo-border-box');
6566 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6567 var p = bd.dom.parentNode;
6569 p.className += ' roo-strict';
6572 bd.addClass(cls.join(' '));
6576 * @class Roo.EventObject
6577 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6578 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6581 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6583 var target = e.getTarget();
6586 var myDiv = Roo.get("myDiv");
6587 myDiv.on("click", handleClick);
6589 Roo.EventManager.on("myDiv", 'click', handleClick);
6590 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6594 Roo.EventObject = function(){
6596 var E = Roo.lib.Event;
6598 // safari keypress events for special keys return bad keycodes
6601 63235 : 39, // right
6604 63276 : 33, // page up
6605 63277 : 34, // page down
6606 63272 : 46, // delete
6611 // normalize button clicks
6612 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6613 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6615 Roo.EventObjectImpl = function(e){
6617 this.setEvent(e.browserEvent || e);
6620 Roo.EventObjectImpl.prototype = {
6622 * Used to fix doc tools.
6623 * @scope Roo.EventObject.prototype
6629 /** The normal browser event */
6630 browserEvent : null,
6631 /** The button pressed in a mouse event */
6633 /** True if the shift key was down during the event */
6635 /** True if the control key was down during the event */
6637 /** True if the alt key was down during the event */
6696 setEvent : function(e){
6697 if(e == this || (e && e.browserEvent)){ // already wrapped
6700 this.browserEvent = e;
6702 // normalize buttons
6703 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6704 if(e.type == 'click' && this.button == -1){
6708 this.shiftKey = e.shiftKey;
6709 // mac metaKey behaves like ctrlKey
6710 this.ctrlKey = e.ctrlKey || e.metaKey;
6711 this.altKey = e.altKey;
6712 // in getKey these will be normalized for the mac
6713 this.keyCode = e.keyCode;
6714 // keyup warnings on firefox.
6715 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6716 // cache the target for the delayed and or buffered events
6717 this.target = E.getTarget(e);
6719 this.xy = E.getXY(e);
6722 this.shiftKey = false;
6723 this.ctrlKey = false;
6724 this.altKey = false;
6734 * Stop the event (preventDefault and stopPropagation)
6736 stopEvent : function(){
6737 if(this.browserEvent){
6738 if(this.browserEvent.type == 'mousedown'){
6739 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6741 E.stopEvent(this.browserEvent);
6746 * Prevents the browsers default handling of the event.
6748 preventDefault : function(){
6749 if(this.browserEvent){
6750 E.preventDefault(this.browserEvent);
6755 isNavKeyPress : function(){
6756 var k = this.keyCode;
6757 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6758 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6761 isSpecialKey : function(){
6762 var k = this.keyCode;
6763 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6764 (k == 16) || (k == 17) ||
6765 (k >= 18 && k <= 20) ||
6766 (k >= 33 && k <= 35) ||
6767 (k >= 36 && k <= 39) ||
6768 (k >= 44 && k <= 45);
6771 * Cancels bubbling of the event.
6773 stopPropagation : function(){
6774 if(this.browserEvent){
6775 if(this.type == 'mousedown'){
6776 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6778 E.stopPropagation(this.browserEvent);
6783 * Gets the key code for the event.
6786 getCharCode : function(){
6787 return this.charCode || this.keyCode;
6791 * Returns a normalized keyCode for the event.
6792 * @return {Number} The key code
6794 getKey : function(){
6795 var k = this.keyCode || this.charCode;
6796 return Roo.isSafari ? (safariKeys[k] || k) : k;
6800 * Gets the x coordinate of the event.
6803 getPageX : function(){
6808 * Gets the y coordinate of the event.
6811 getPageY : function(){
6816 * Gets the time of the event.
6819 getTime : function(){
6820 if(this.browserEvent){
6821 return E.getTime(this.browserEvent);
6827 * Gets the page coordinates of the event.
6828 * @return {Array} The xy values like [x, y]
6835 * Gets the target for the event.
6836 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6837 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6838 search as a number or element (defaults to 10 || document.body)
6839 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6840 * @return {HTMLelement}
6842 getTarget : function(selector, maxDepth, returnEl){
6843 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6846 * Gets the related target.
6847 * @return {HTMLElement}
6849 getRelatedTarget : function(){
6850 if(this.browserEvent){
6851 return E.getRelatedTarget(this.browserEvent);
6857 * Normalizes mouse wheel delta across browsers
6858 * @return {Number} The delta
6860 getWheelDelta : function(){
6861 var e = this.browserEvent;
6863 if(e.wheelDelta){ /* IE/Opera. */
6864 delta = e.wheelDelta/120;
6865 }else if(e.detail){ /* Mozilla case. */
6866 delta = -e.detail/3;
6872 * Returns true if the control, meta, shift or alt key was pressed during this event.
6875 hasModifier : function(){
6876 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6880 * Returns true if the target of this event equals el or is a child of el
6881 * @param {String/HTMLElement/Element} el
6882 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6885 within : function(el, related){
6886 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6887 return t && Roo.fly(el).contains(t);
6890 getPoint : function(){
6891 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6895 return new Roo.EventObjectImpl();
6900 * Ext JS Library 1.1.1
6901 * Copyright(c) 2006-2007, Ext JS, LLC.
6903 * Originally Released Under LGPL - original licence link has changed is not relivant.
6906 * <script type="text/javascript">
6910 // was in Composite Element!??!?!
6913 var D = Roo.lib.Dom;
6914 var E = Roo.lib.Event;
6915 var A = Roo.lib.Anim;
6917 // local style camelizing for speed
6919 var camelRe = /(-[a-z])/gi;
6920 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6921 var view = document.defaultView;
6924 * @class Roo.Element
6925 * Represents an Element in the DOM.<br><br>
6928 var el = Roo.get("my-div");
6931 var el = getEl("my-div");
6933 // or with a DOM element
6934 var el = Roo.get(myDivElement);
6936 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6937 * each call instead of constructing a new one.<br><br>
6938 * <b>Animations</b><br />
6939 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6940 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6942 Option Default Description
6943 --------- -------- ---------------------------------------------
6944 duration .35 The duration of the animation in seconds
6945 easing easeOut The YUI easing method
6946 callback none A function to execute when the anim completes
6947 scope this The scope (this) of the callback function
6949 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6950 * manipulate the animation. Here's an example:
6952 var el = Roo.get("my-div");
6957 // default animation
6958 el.setWidth(100, true);
6960 // animation with some options set
6967 // using the "anim" property to get the Anim object
6973 el.setWidth(100, opt);
6975 if(opt.anim.isAnimated()){
6979 * <b> Composite (Collections of) Elements</b><br />
6980 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6981 * @constructor Create a new Element directly.
6982 * @param {String/HTMLElement} element
6983 * @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).
6985 Roo.Element = function(element, forceNew){
6986 var dom = typeof element == "string" ?
6987 document.getElementById(element) : element;
6988 if(!dom){ // invalid id/element
6992 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6993 return Roo.Element.cache[id];
7003 * The DOM element ID
7006 this.id = id || Roo.id(dom);
7009 var El = Roo.Element;
7013 * The element's default display mode (defaults to "")
7016 originalDisplay : "",
7020 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7025 * Sets the element's visibility mode. When setVisible() is called it
7026 * will use this to determine whether to set the visibility or the display property.
7027 * @param visMode Element.VISIBILITY or Element.DISPLAY
7028 * @return {Roo.Element} this
7030 setVisibilityMode : function(visMode){
7031 this.visibilityMode = visMode;
7035 * Convenience method for setVisibilityMode(Element.DISPLAY)
7036 * @param {String} display (optional) What to set display to when visible
7037 * @return {Roo.Element} this
7039 enableDisplayMode : function(display){
7040 this.setVisibilityMode(El.DISPLAY);
7041 if(typeof display != "undefined") this.originalDisplay = display;
7046 * 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)
7047 * @param {String} selector The simple selector to test
7048 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7049 search as a number or element (defaults to 10 || document.body)
7050 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7051 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7053 findParent : function(simpleSelector, maxDepth, returnEl){
7054 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7055 maxDepth = maxDepth || 50;
7056 if(typeof maxDepth != "number"){
7057 stopEl = Roo.getDom(maxDepth);
7060 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7061 if(dq.is(p, simpleSelector)){
7062 return returnEl ? Roo.get(p) : p;
7072 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7073 * @param {String} selector The simple selector to test
7074 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7075 search as a number or element (defaults to 10 || document.body)
7076 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7077 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7079 findParentNode : function(simpleSelector, maxDepth, returnEl){
7080 var p = Roo.fly(this.dom.parentNode, '_internal');
7081 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7085 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7086 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7087 * @param {String} selector The simple selector to test
7088 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7089 search as a number or element (defaults to 10 || document.body)
7090 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7092 up : function(simpleSelector, maxDepth){
7093 return this.findParentNode(simpleSelector, maxDepth, true);
7099 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7100 * @param {String} selector The simple selector to test
7101 * @return {Boolean} True if this element matches the selector, else false
7103 is : function(simpleSelector){
7104 return Roo.DomQuery.is(this.dom, simpleSelector);
7108 * Perform animation on this element.
7109 * @param {Object} args The YUI animation control args
7110 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7111 * @param {Function} onComplete (optional) Function to call when animation completes
7112 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7113 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7114 * @return {Roo.Element} this
7116 animate : function(args, duration, onComplete, easing, animType){
7117 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7122 * @private Internal animation call
7124 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7125 animType = animType || 'run';
7127 var anim = Roo.lib.Anim[animType](
7129 (opt.duration || defaultDur) || .35,
7130 (opt.easing || defaultEase) || 'easeOut',
7132 Roo.callback(cb, this);
7133 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7141 // private legacy anim prep
7142 preanim : function(a, i){
7143 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7147 * Removes worthless text nodes
7148 * @param {Boolean} forceReclean (optional) By default the element
7149 * keeps track if it has been cleaned already so
7150 * you can call this over and over. However, if you update the element and
7151 * need to force a reclean, you can pass true.
7153 clean : function(forceReclean){
7154 if(this.isCleaned && forceReclean !== true){
7158 var d = this.dom, n = d.firstChild, ni = -1;
7160 var nx = n.nextSibling;
7161 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7168 this.isCleaned = true;
7173 calcOffsetsTo : function(el){
7176 var restorePos = false;
7177 if(el.getStyle('position') == 'static'){
7178 el.position('relative');
7183 while(op && op != d && op.tagName != 'HTML'){
7186 op = op.offsetParent;
7189 el.position('static');
7195 * Scrolls this element into view within the passed container.
7196 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7197 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7198 * @return {Roo.Element} this
7200 scrollIntoView : function(container, hscroll){
7201 var c = Roo.getDom(container) || document.body;
7204 var o = this.calcOffsetsTo(c),
7207 b = t+el.offsetHeight,
7208 r = l+el.offsetWidth;
7210 var ch = c.clientHeight;
7211 var ct = parseInt(c.scrollTop, 10);
7212 var cl = parseInt(c.scrollLeft, 10);
7214 var cr = cl + c.clientWidth;
7222 if(hscroll !== false){
7226 c.scrollLeft = r-c.clientWidth;
7233 scrollChildIntoView : function(child, hscroll){
7234 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7238 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7239 * the new height may not be available immediately.
7240 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7241 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7242 * @param {Function} onComplete (optional) Function to call when animation completes
7243 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7244 * @return {Roo.Element} this
7246 autoHeight : function(animate, duration, onComplete, easing){
7247 var oldHeight = this.getHeight();
7249 this.setHeight(1); // force clipping
7250 setTimeout(function(){
7251 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7253 this.setHeight(height);
7255 if(typeof onComplete == "function"){
7259 this.setHeight(oldHeight); // restore original height
7260 this.setHeight(height, animate, duration, function(){
7262 if(typeof onComplete == "function") onComplete();
7263 }.createDelegate(this), easing);
7265 }.createDelegate(this), 0);
7270 * Returns true if this element is an ancestor of the passed element
7271 * @param {HTMLElement/String} el The element to check
7272 * @return {Boolean} True if this element is an ancestor of el, else false
7274 contains : function(el){
7275 if(!el){return false;}
7276 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7280 * Checks whether the element is currently visible using both visibility and display properties.
7281 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7282 * @return {Boolean} True if the element is currently visible, else false
7284 isVisible : function(deep) {
7285 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7286 if(deep !== true || !vis){
7289 var p = this.dom.parentNode;
7290 while(p && p.tagName.toLowerCase() != "body"){
7291 if(!Roo.fly(p, '_isVisible').isVisible()){
7300 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7301 * @param {String} selector The CSS selector
7302 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7303 * @return {CompositeElement/CompositeElementLite} The composite element
7305 select : function(selector, unique){
7306 return El.select(selector, unique, this.dom);
7310 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7311 * @param {String} selector The CSS selector
7312 * @return {Array} An array of the matched nodes
7314 query : function(selector, unique){
7315 return Roo.DomQuery.select(selector, this.dom);
7319 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7320 * @param {String} selector The CSS selector
7321 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7322 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7324 child : function(selector, returnDom){
7325 var n = Roo.DomQuery.selectNode(selector, this.dom);
7326 return returnDom ? n : Roo.get(n);
7330 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7331 * @param {String} selector The CSS selector
7332 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7333 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7335 down : function(selector, returnDom){
7336 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7337 return returnDom ? n : Roo.get(n);
7341 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7342 * @param {String} group The group the DD object is member of
7343 * @param {Object} config The DD config object
7344 * @param {Object} overrides An object containing methods to override/implement on the DD object
7345 * @return {Roo.dd.DD} The DD object
7347 initDD : function(group, config, overrides){
7348 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7349 return Roo.apply(dd, overrides);
7353 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7354 * @param {String} group The group the DDProxy object is member of
7355 * @param {Object} config The DDProxy config object
7356 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7357 * @return {Roo.dd.DDProxy} The DDProxy object
7359 initDDProxy : function(group, config, overrides){
7360 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7361 return Roo.apply(dd, overrides);
7365 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7366 * @param {String} group The group the DDTarget object is member of
7367 * @param {Object} config The DDTarget config object
7368 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7369 * @return {Roo.dd.DDTarget} The DDTarget object
7371 initDDTarget : function(group, config, overrides){
7372 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7373 return Roo.apply(dd, overrides);
7377 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7378 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7379 * @param {Boolean} visible Whether the element is visible
7380 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7381 * @return {Roo.Element} this
7383 setVisible : function(visible, animate){
7385 if(this.visibilityMode == El.DISPLAY){
7386 this.setDisplayed(visible);
7389 this.dom.style.visibility = visible ? "visible" : "hidden";
7392 // closure for composites
7394 var visMode = this.visibilityMode;
7396 this.setOpacity(.01);
7397 this.setVisible(true);
7399 this.anim({opacity: { to: (visible?1:0) }},
7400 this.preanim(arguments, 1),
7401 null, .35, 'easeIn', function(){
7403 if(visMode == El.DISPLAY){
7404 dom.style.display = "none";
7406 dom.style.visibility = "hidden";
7408 Roo.get(dom).setOpacity(1);
7416 * Returns true if display is not "none"
7419 isDisplayed : function() {
7420 return this.getStyle("display") != "none";
7424 * Toggles the element's visibility or display, depending on visibility mode.
7425 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7426 * @return {Roo.Element} this
7428 toggle : function(animate){
7429 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7434 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7435 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7436 * @return {Roo.Element} this
7438 setDisplayed : function(value) {
7439 if(typeof value == "boolean"){
7440 value = value ? this.originalDisplay : "none";
7442 this.setStyle("display", value);
7447 * Tries to focus the element. Any exceptions are caught and ignored.
7448 * @return {Roo.Element} this
7450 focus : function() {
7458 * Tries to blur the element. Any exceptions are caught and ignored.
7459 * @return {Roo.Element} this
7469 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7470 * @param {String/Array} className The CSS class to add, or an array of classes
7471 * @return {Roo.Element} this
7473 addClass : function(className){
7474 if(className instanceof Array){
7475 for(var i = 0, len = className.length; i < len; i++) {
7476 this.addClass(className[i]);
7479 if(className && !this.hasClass(className)){
7480 this.dom.className = this.dom.className + " " + className;
7487 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7488 * @param {String/Array} className The CSS class to add, or an array of classes
7489 * @return {Roo.Element} this
7491 radioClass : function(className){
7492 var siblings = this.dom.parentNode.childNodes;
7493 for(var i = 0; i < siblings.length; i++) {
7494 var s = siblings[i];
7495 if(s.nodeType == 1){
7496 Roo.get(s).removeClass(className);
7499 this.addClass(className);
7504 * Removes one or more CSS classes from the element.
7505 * @param {String/Array} className The CSS class to remove, or an array of classes
7506 * @return {Roo.Element} this
7508 removeClass : function(className){
7509 if(!className || !this.dom.className){
7512 if(className instanceof Array){
7513 for(var i = 0, len = className.length; i < len; i++) {
7514 this.removeClass(className[i]);
7517 if(this.hasClass(className)){
7518 var re = this.classReCache[className];
7520 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7521 this.classReCache[className] = re;
7523 this.dom.className =
7524 this.dom.className.replace(re, " ");
7534 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7535 * @param {String} className The CSS class to toggle
7536 * @return {Roo.Element} this
7538 toggleClass : function(className){
7539 if(this.hasClass(className)){
7540 this.removeClass(className);
7542 this.addClass(className);
7548 * Checks if the specified CSS class exists on this element's DOM node.
7549 * @param {String} className The CSS class to check for
7550 * @return {Boolean} True if the class exists, else false
7552 hasClass : function(className){
7553 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7557 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7558 * @param {String} oldClassName The CSS class to replace
7559 * @param {String} newClassName The replacement CSS class
7560 * @return {Roo.Element} this
7562 replaceClass : function(oldClassName, newClassName){
7563 this.removeClass(oldClassName);
7564 this.addClass(newClassName);
7569 * Returns an object with properties matching the styles requested.
7570 * For example, el.getStyles('color', 'font-size', 'width') might return
7571 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7572 * @param {String} style1 A style name
7573 * @param {String} style2 A style name
7574 * @param {String} etc.
7575 * @return {Object} The style object
7577 getStyles : function(){
7578 var a = arguments, len = a.length, r = {};
7579 for(var i = 0; i < len; i++){
7580 r[a[i]] = this.getStyle(a[i]);
7586 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7587 * @param {String} property The style property whose value is returned.
7588 * @return {String} The current value of the style property for this element.
7590 getStyle : function(){
7591 return view && view.getComputedStyle ?
7593 var el = this.dom, v, cs, camel;
7594 if(prop == 'float'){
7597 if(el.style && (v = el.style[prop])){
7600 if(cs = view.getComputedStyle(el, "")){
7601 if(!(camel = propCache[prop])){
7602 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7609 var el = this.dom, v, cs, camel;
7610 if(prop == 'opacity'){
7611 if(typeof el.style.filter == 'string'){
7612 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7614 var fv = parseFloat(m[1]);
7616 return fv ? fv / 100 : 0;
7621 }else if(prop == 'float'){
7622 prop = "styleFloat";
7624 if(!(camel = propCache[prop])){
7625 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7627 if(v = el.style[camel]){
7630 if(cs = el.currentStyle){
7638 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7639 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7640 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7641 * @return {Roo.Element} this
7643 setStyle : function(prop, value){
7644 if(typeof prop == "string"){
7646 if (prop == 'float') {
7647 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7652 if(!(camel = propCache[prop])){
7653 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7656 if(camel == 'opacity') {
7657 this.setOpacity(value);
7659 this.dom.style[camel] = value;
7662 for(var style in prop){
7663 if(typeof prop[style] != "function"){
7664 this.setStyle(style, prop[style]);
7672 * More flexible version of {@link #setStyle} for setting style properties.
7673 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7674 * a function which returns such a specification.
7675 * @return {Roo.Element} this
7677 applyStyles : function(style){
7678 Roo.DomHelper.applyStyles(this.dom, style);
7683 * 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).
7684 * @return {Number} The X position of the element
7687 return D.getX(this.dom);
7691 * 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).
7692 * @return {Number} The Y position of the element
7695 return D.getY(this.dom);
7699 * 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).
7700 * @return {Array} The XY position of the element
7703 return D.getXY(this.dom);
7707 * 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).
7708 * @param {Number} The X position of the element
7709 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7710 * @return {Roo.Element} this
7712 setX : function(x, animate){
7714 D.setX(this.dom, x);
7716 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7722 * 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).
7723 * @param {Number} The Y position of the element
7724 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7725 * @return {Roo.Element} this
7727 setY : function(y, animate){
7729 D.setY(this.dom, y);
7731 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7737 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7738 * @param {String} left The left CSS property value
7739 * @return {Roo.Element} this
7741 setLeft : function(left){
7742 this.setStyle("left", this.addUnits(left));
7747 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7748 * @param {String} top The top CSS property value
7749 * @return {Roo.Element} this
7751 setTop : function(top){
7752 this.setStyle("top", this.addUnits(top));
7757 * Sets the element's CSS right style.
7758 * @param {String} right The right CSS property value
7759 * @return {Roo.Element} this
7761 setRight : function(right){
7762 this.setStyle("right", this.addUnits(right));
7767 * Sets the element's CSS bottom style.
7768 * @param {String} bottom The bottom CSS property value
7769 * @return {Roo.Element} this
7771 setBottom : function(bottom){
7772 this.setStyle("bottom", this.addUnits(bottom));
7777 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7778 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7779 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7780 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7781 * @return {Roo.Element} this
7783 setXY : function(pos, animate){
7785 D.setXY(this.dom, pos);
7787 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7793 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7794 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7795 * @param {Number} x X value for new position (coordinates are page-based)
7796 * @param {Number} y Y value for new position (coordinates are page-based)
7797 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7798 * @return {Roo.Element} this
7800 setLocation : function(x, y, animate){
7801 this.setXY([x, y], this.preanim(arguments, 2));
7806 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7807 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7808 * @param {Number} x X value for new position (coordinates are page-based)
7809 * @param {Number} y Y value for new position (coordinates are page-based)
7810 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7811 * @return {Roo.Element} this
7813 moveTo : function(x, y, animate){
7814 this.setXY([x, y], this.preanim(arguments, 2));
7819 * Returns the region of the given element.
7820 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7821 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7823 getRegion : function(){
7824 return D.getRegion(this.dom);
7828 * Returns the offset height of the element
7829 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7830 * @return {Number} The element's height
7832 getHeight : function(contentHeight){
7833 var h = this.dom.offsetHeight || 0;
7834 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7838 * Returns the offset width of the element
7839 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7840 * @return {Number} The element's width
7842 getWidth : function(contentWidth){
7843 var w = this.dom.offsetWidth || 0;
7844 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7848 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7849 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7850 * if a height has not been set using CSS.
7853 getComputedHeight : function(){
7854 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7856 h = parseInt(this.getStyle('height'), 10) || 0;
7857 if(!this.isBorderBox()){
7858 h += this.getFrameWidth('tb');
7865 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7866 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7867 * if a width has not been set using CSS.
7870 getComputedWidth : function(){
7871 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7873 w = parseInt(this.getStyle('width'), 10) || 0;
7874 if(!this.isBorderBox()){
7875 w += this.getFrameWidth('lr');
7882 * Returns the size of the element.
7883 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7884 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7886 getSize : function(contentSize){
7887 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7891 * Returns the width and height of the viewport.
7892 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7894 getViewSize : function(){
7895 var d = this.dom, doc = document, aw = 0, ah = 0;
7896 if(d == doc || d == doc.body){
7897 return {width : D.getViewWidth(), height: D.getViewHeight()};
7900 width : d.clientWidth,
7901 height: d.clientHeight
7907 * Returns the value of the "value" attribute
7908 * @param {Boolean} asNumber true to parse the value as a number
7909 * @return {String/Number}
7911 getValue : function(asNumber){
7912 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7916 adjustWidth : function(width){
7917 if(typeof width == "number"){
7918 if(this.autoBoxAdjust && !this.isBorderBox()){
7919 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7929 adjustHeight : function(height){
7930 if(typeof height == "number"){
7931 if(this.autoBoxAdjust && !this.isBorderBox()){
7932 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7942 * Set the width of the element
7943 * @param {Number} width The new width
7944 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7945 * @return {Roo.Element} this
7947 setWidth : function(width, animate){
7948 width = this.adjustWidth(width);
7950 this.dom.style.width = this.addUnits(width);
7952 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7958 * Set the height of the element
7959 * @param {Number} height The new height
7960 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7961 * @return {Roo.Element} this
7963 setHeight : function(height, animate){
7964 height = this.adjustHeight(height);
7966 this.dom.style.height = this.addUnits(height);
7968 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7974 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7975 * @param {Number} width The new width
7976 * @param {Number} height The new height
7977 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7978 * @return {Roo.Element} this
7980 setSize : function(width, height, animate){
7981 if(typeof width == "object"){ // in case of object from getSize()
7982 height = width.height; width = width.width;
7984 width = this.adjustWidth(width); height = this.adjustHeight(height);
7986 this.dom.style.width = this.addUnits(width);
7987 this.dom.style.height = this.addUnits(height);
7989 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7995 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7996 * @param {Number} x X value for new position (coordinates are page-based)
7997 * @param {Number} y Y value for new position (coordinates are page-based)
7998 * @param {Number} width The new width
7999 * @param {Number} height The new height
8000 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8001 * @return {Roo.Element} this
8003 setBounds : function(x, y, width, height, animate){
8005 this.setSize(width, height);
8006 this.setLocation(x, y);
8008 width = this.adjustWidth(width); height = this.adjustHeight(height);
8009 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8010 this.preanim(arguments, 4), 'motion');
8016 * 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.
8017 * @param {Roo.lib.Region} region The region to fill
8018 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8019 * @return {Roo.Element} this
8021 setRegion : function(region, animate){
8022 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8027 * Appends an event handler
8029 * @param {String} eventName The type of event to append
8030 * @param {Function} fn The method the event invokes
8031 * @param {Object} scope (optional) The scope (this object) of the fn
8032 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8034 addListener : function(eventName, fn, scope, options){
8036 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8041 * Removes an event handler from this element
8042 * @param {String} eventName the type of event to remove
8043 * @param {Function} fn the method the event invokes
8044 * @return {Roo.Element} this
8046 removeListener : function(eventName, fn){
8047 Roo.EventManager.removeListener(this.dom, eventName, fn);
8052 * Removes all previous added listeners from this element
8053 * @return {Roo.Element} this
8055 removeAllListeners : function(){
8056 E.purgeElement(this.dom);
8060 relayEvent : function(eventName, observable){
8061 this.on(eventName, function(e){
8062 observable.fireEvent(eventName, e);
8067 * Set the opacity of the element
8068 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8069 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8070 * @return {Roo.Element} this
8072 setOpacity : function(opacity, animate){
8074 var s = this.dom.style;
8077 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8078 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8080 s.opacity = opacity;
8083 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8089 * Gets the left X coordinate
8090 * @param {Boolean} local True to get the local css position instead of page coordinate
8093 getLeft : function(local){
8097 return parseInt(this.getStyle("left"), 10) || 0;
8102 * Gets the right X coordinate of the element (element X position + element width)
8103 * @param {Boolean} local True to get the local css position instead of page coordinate
8106 getRight : function(local){
8108 return this.getX() + this.getWidth();
8110 return (this.getLeft(true) + this.getWidth()) || 0;
8115 * Gets the top Y coordinate
8116 * @param {Boolean} local True to get the local css position instead of page coordinate
8119 getTop : function(local) {
8123 return parseInt(this.getStyle("top"), 10) || 0;
8128 * Gets the bottom Y coordinate of the element (element Y position + element height)
8129 * @param {Boolean} local True to get the local css position instead of page coordinate
8132 getBottom : function(local){
8134 return this.getY() + this.getHeight();
8136 return (this.getTop(true) + this.getHeight()) || 0;
8141 * Initializes positioning on this element. If a desired position is not passed, it will make the
8142 * the element positioned relative IF it is not already positioned.
8143 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8144 * @param {Number} zIndex (optional) The zIndex to apply
8145 * @param {Number} x (optional) Set the page X position
8146 * @param {Number} y (optional) Set the page Y position
8148 position : function(pos, zIndex, x, y){
8150 if(this.getStyle('position') == 'static'){
8151 this.setStyle('position', 'relative');
8154 this.setStyle("position", pos);
8157 this.setStyle("z-index", zIndex);
8159 if(x !== undefined && y !== undefined){
8161 }else if(x !== undefined){
8163 }else if(y !== undefined){
8169 * Clear positioning back to the default when the document was loaded
8170 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8171 * @return {Roo.Element} this
8173 clearPositioning : function(value){
8181 "position" : "static"
8187 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8188 * snapshot before performing an update and then restoring the element.
8191 getPositioning : function(){
8192 var l = this.getStyle("left");
8193 var t = this.getStyle("top");
8195 "position" : this.getStyle("position"),
8197 "right" : l ? "" : this.getStyle("right"),
8199 "bottom" : t ? "" : this.getStyle("bottom"),
8200 "z-index" : this.getStyle("z-index")
8205 * Gets the width of the border(s) for the specified side(s)
8206 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8207 * passing lr would get the border (l)eft width + the border (r)ight width.
8208 * @return {Number} The width of the sides passed added together
8210 getBorderWidth : function(side){
8211 return this.addStyles(side, El.borders);
8215 * Gets the width of the padding(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 padding (l)eft + the padding (r)ight.
8218 * @return {Number} The padding of the sides passed added together
8220 getPadding : function(side){
8221 return this.addStyles(side, El.paddings);
8225 * Set positioning with an object returned by getPositioning().
8226 * @param {Object} posCfg
8227 * @return {Roo.Element} this
8229 setPositioning : function(pc){
8230 this.applyStyles(pc);
8231 if(pc.right == "auto"){
8232 this.dom.style.right = "";
8234 if(pc.bottom == "auto"){
8235 this.dom.style.bottom = "";
8241 fixDisplay : function(){
8242 if(this.getStyle("display") == "none"){
8243 this.setStyle("visibility", "hidden");
8244 this.setStyle("display", this.originalDisplay); // first try reverting to default
8245 if(this.getStyle("display") == "none"){ // if that fails, default to block
8246 this.setStyle("display", "block");
8252 * Quick set left and top adding default units
8253 * @param {String} left The left CSS property value
8254 * @param {String} top The top CSS property value
8255 * @return {Roo.Element} this
8257 setLeftTop : function(left, top){
8258 this.dom.style.left = this.addUnits(left);
8259 this.dom.style.top = this.addUnits(top);
8264 * Move this element relative to its current position.
8265 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8266 * @param {Number} distance How far to move the element in pixels
8267 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8268 * @return {Roo.Element} this
8270 move : function(direction, distance, animate){
8271 var xy = this.getXY();
8272 direction = direction.toLowerCase();
8276 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8280 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8285 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8290 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8297 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8298 * @return {Roo.Element} this
8301 if(!this.isClipped){
8302 this.isClipped = true;
8303 this.originalClip = {
8304 "o": this.getStyle("overflow"),
8305 "x": this.getStyle("overflow-x"),
8306 "y": this.getStyle("overflow-y")
8308 this.setStyle("overflow", "hidden");
8309 this.setStyle("overflow-x", "hidden");
8310 this.setStyle("overflow-y", "hidden");
8316 * Return clipping (overflow) to original clipping before clip() was called
8317 * @return {Roo.Element} this
8319 unclip : function(){
8321 this.isClipped = false;
8322 var o = this.originalClip;
8323 if(o.o){this.setStyle("overflow", o.o);}
8324 if(o.x){this.setStyle("overflow-x", o.x);}
8325 if(o.y){this.setStyle("overflow-y", o.y);}
8332 * Gets the x,y coordinates specified by the anchor position on the element.
8333 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8334 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8335 * {width: (target width), height: (target height)} (defaults to the element's current size)
8336 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8337 * @return {Array} [x, y] An array containing the element's x and y coordinates
8339 getAnchorXY : function(anchor, local, s){
8340 //Passing a different size is useful for pre-calculating anchors,
8341 //especially for anchored animations that change the el size.
8343 var w, h, vp = false;
8346 if(d == document.body || d == document){
8348 w = D.getViewWidth(); h = D.getViewHeight();
8350 w = this.getWidth(); h = this.getHeight();
8353 w = s.width; h = s.height;
8355 var x = 0, y = 0, r = Math.round;
8356 switch((anchor || "tl").toLowerCase()){
8398 var sc = this.getScroll();
8399 return [x + sc.left, y + sc.top];
8401 //Add the element's offset xy
8402 var o = this.getXY();
8403 return [x+o[0], y+o[1]];
8407 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8408 * supported position values.
8409 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8410 * @param {String} position The position to align to.
8411 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8412 * @return {Array} [x, y]
8414 getAlignToXY : function(el, p, o){
8418 throw "Element.alignTo with an element that doesn't exist";
8420 var c = false; //constrain to viewport
8421 var p1 = "", p2 = "";
8428 }else if(p.indexOf("-") == -1){
8431 p = p.toLowerCase();
8432 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8434 throw "Element.alignTo with an invalid alignment " + p;
8436 p1 = m[1]; p2 = m[2]; c = !!m[3];
8438 //Subtract the aligned el's internal xy from the target's offset xy
8439 //plus custom offset to get the aligned el's new offset xy
8440 var a1 = this.getAnchorXY(p1, true);
8441 var a2 = el.getAnchorXY(p2, false);
8442 var x = a2[0] - a1[0] + o[0];
8443 var y = a2[1] - a1[1] + o[1];
8445 //constrain the aligned el to viewport if necessary
8446 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8447 // 5px of margin for ie
8448 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8450 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8451 //perpendicular to the vp border, allow the aligned el to slide on that border,
8452 //otherwise swap the aligned el to the opposite border of the target.
8453 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8454 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8455 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8456 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8459 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8460 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8462 if((x+w) > dw + scrollX){
8463 x = swapX ? r.left-w : dw+scrollX-w;
8466 x = swapX ? r.right : scrollX;
8468 if((y+h) > dh + scrollY){
8469 y = swapY ? r.top-h : dh+scrollY-h;
8472 y = swapY ? r.bottom : scrollY;
8479 getConstrainToXY : function(){
8480 var os = {top:0, left:0, bottom:0, right: 0};
8482 return function(el, local, offsets, proposedXY){
8484 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8486 var vw, vh, vx = 0, vy = 0;
8487 if(el.dom == document.body || el.dom == document){
8488 vw = Roo.lib.Dom.getViewWidth();
8489 vh = Roo.lib.Dom.getViewHeight();
8491 vw = el.dom.clientWidth;
8492 vh = el.dom.clientHeight;
8494 var vxy = el.getXY();
8500 var s = el.getScroll();
8502 vx += offsets.left + s.left;
8503 vy += offsets.top + s.top;
8505 vw -= offsets.right;
8506 vh -= offsets.bottom;
8511 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8512 var x = xy[0], y = xy[1];
8513 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8515 // only move it if it needs it
8518 // first validate right/bottom
8527 // then make sure top/left isn't negative
8536 return moved ? [x, y] : false;
8541 adjustForConstraints : function(xy, parent, offsets){
8542 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8546 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8547 * document it aligns it to the viewport.
8548 * The position parameter is optional, and can be specified in any one of the following formats:
8550 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8551 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8552 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8553 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8554 * <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
8555 * element's anchor point, and the second value is used as the target's anchor point.</li>
8557 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8558 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8559 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8560 * that specified in order to enforce the viewport constraints.
8561 * Following are all of the supported anchor positions:
8564 ----- -----------------------------
8565 tl The top left corner (default)
8566 t The center of the top edge
8567 tr The top right corner
8568 l The center of the left edge
8569 c In the center of the element
8570 r The center of the right edge
8571 bl The bottom left corner
8572 b The center of the bottom edge
8573 br The bottom right corner
8577 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8578 el.alignTo("other-el");
8580 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8581 el.alignTo("other-el", "tr?");
8583 // align the bottom right corner of el with the center left edge of other-el
8584 el.alignTo("other-el", "br-l?");
8586 // align the center of el with the bottom left corner of other-el and
8587 // adjust the x position by -6 pixels (and the y position by 0)
8588 el.alignTo("other-el", "c-bl", [-6, 0]);
8590 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8591 * @param {String} position The position to align to.
8592 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8593 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8594 * @return {Roo.Element} this
8596 alignTo : function(element, position, offsets, animate){
8597 var xy = this.getAlignToXY(element, position, offsets);
8598 this.setXY(xy, this.preanim(arguments, 3));
8603 * Anchors an element to another element and realigns it when the window is resized.
8604 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8605 * @param {String} position The position to align to.
8606 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8607 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8608 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8609 * is a number, it is used as the buffer delay (defaults to 50ms).
8610 * @param {Function} callback The function to call after the animation finishes
8611 * @return {Roo.Element} this
8613 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8614 var action = function(){
8615 this.alignTo(el, alignment, offsets, animate);
8616 Roo.callback(callback, this);
8618 Roo.EventManager.onWindowResize(action, this);
8619 var tm = typeof monitorScroll;
8620 if(tm != 'undefined'){
8621 Roo.EventManager.on(window, 'scroll', action, this,
8622 {buffer: tm == 'number' ? monitorScroll : 50});
8624 action.call(this); // align immediately
8628 * Clears any opacity settings from this element. Required in some cases for IE.
8629 * @return {Roo.Element} this
8631 clearOpacity : function(){
8632 if (window.ActiveXObject) {
8633 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8634 this.dom.style.filter = "";
8637 this.dom.style.opacity = "";
8638 this.dom.style["-moz-opacity"] = "";
8639 this.dom.style["-khtml-opacity"] = "";
8645 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8646 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8647 * @return {Roo.Element} this
8649 hide : function(animate){
8650 this.setVisible(false, this.preanim(arguments, 0));
8655 * Show 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 show : function(animate){
8660 this.setVisible(true, this.preanim(arguments, 0));
8665 * @private Test if size has a unit, otherwise appends the default
8667 addUnits : function(size){
8668 return Roo.Element.addUnits(size, this.defaultUnit);
8672 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8673 * @return {Roo.Element} this
8675 beginMeasure : function(){
8677 if(el.offsetWidth || el.offsetHeight){
8678 return this; // offsets work already
8681 var p = this.dom, b = document.body; // start with this element
8682 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8683 var pe = Roo.get(p);
8684 if(pe.getStyle('display') == 'none'){
8685 changed.push({el: p, visibility: pe.getStyle("visibility")});
8686 p.style.visibility = "hidden";
8687 p.style.display = "block";
8691 this._measureChanged = changed;
8697 * Restores displays to before beginMeasure was called
8698 * @return {Roo.Element} this
8700 endMeasure : function(){
8701 var changed = this._measureChanged;
8703 for(var i = 0, len = changed.length; i < len; i++) {
8705 r.el.style.visibility = r.visibility;
8706 r.el.style.display = "none";
8708 this._measureChanged = null;
8714 * Update the innerHTML of this element, optionally searching for and processing scripts
8715 * @param {String} html The new HTML
8716 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8717 * @param {Function} callback For async script loading you can be noticed when the update completes
8718 * @return {Roo.Element} this
8720 update : function(html, loadScripts, callback){
8721 if(typeof html == "undefined"){
8724 if(loadScripts !== true){
8725 this.dom.innerHTML = html;
8726 if(typeof callback == "function"){
8734 html += '<span id="' + id + '"></span>';
8736 E.onAvailable(id, function(){
8737 var hd = document.getElementsByTagName("head")[0];
8738 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8739 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8740 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8743 while(match = re.exec(html)){
8744 var attrs = match[1];
8745 var srcMatch = attrs ? attrs.match(srcRe) : false;
8746 if(srcMatch && srcMatch[2]){
8747 var s = document.createElement("script");
8748 s.src = srcMatch[2];
8749 var typeMatch = attrs.match(typeRe);
8750 if(typeMatch && typeMatch[2]){
8751 s.type = typeMatch[2];
8754 }else if(match[2] && match[2].length > 0){
8755 if(window.execScript) {
8756 window.execScript(match[2]);
8764 window.eval(match[2]);
8768 var el = document.getElementById(id);
8769 if(el){el.parentNode.removeChild(el);}
8770 if(typeof callback == "function"){
8774 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8779 * Direct access to the UpdateManager update() method (takes the same parameters).
8780 * @param {String/Function} url The url for this request or a function to call to get the url
8781 * @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}
8782 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8783 * @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.
8784 * @return {Roo.Element} this
8787 var um = this.getUpdateManager();
8788 um.update.apply(um, arguments);
8793 * Gets this element's UpdateManager
8794 * @return {Roo.UpdateManager} The UpdateManager
8796 getUpdateManager : function(){
8797 if(!this.updateManager){
8798 this.updateManager = new Roo.UpdateManager(this);
8800 return this.updateManager;
8804 * Disables text selection for this element (normalized across browsers)
8805 * @return {Roo.Element} this
8807 unselectable : function(){
8808 this.dom.unselectable = "on";
8809 this.swallowEvent("selectstart", true);
8810 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8811 this.addClass("x-unselectable");
8816 * Calculates the x, y to center this element on the screen
8817 * @return {Array} The x, y values [x, y]
8819 getCenterXY : function(){
8820 return this.getAlignToXY(document, 'c-c');
8824 * Centers the Element in either the viewport, or another Element.
8825 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8827 center : function(centerIn){
8828 this.alignTo(centerIn || document, 'c-c');
8833 * Tests various css rules/browsers to determine if this element uses a border box
8836 isBorderBox : function(){
8837 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8841 * Return a box {x, y, width, height} that can be used to set another elements
8842 * size/location to match this element.
8843 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8844 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8845 * @return {Object} box An object in the format {x, y, width, height}
8847 getBox : function(contentBox, local){
8852 var left = parseInt(this.getStyle("left"), 10) || 0;
8853 var top = parseInt(this.getStyle("top"), 10) || 0;
8856 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8858 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8860 var l = this.getBorderWidth("l")+this.getPadding("l");
8861 var r = this.getBorderWidth("r")+this.getPadding("r");
8862 var t = this.getBorderWidth("t")+this.getPadding("t");
8863 var b = this.getBorderWidth("b")+this.getPadding("b");
8864 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)};
8866 bx.right = bx.x + bx.width;
8867 bx.bottom = bx.y + bx.height;
8872 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8873 for more information about the sides.
8874 * @param {String} sides
8877 getFrameWidth : function(sides, onlyContentBox){
8878 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8882 * 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.
8883 * @param {Object} box The box to fill {x, y, width, height}
8884 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8885 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8886 * @return {Roo.Element} this
8888 setBox : function(box, adjust, animate){
8889 var w = box.width, h = box.height;
8890 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8891 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8892 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8894 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8899 * Forces the browser to repaint this element
8900 * @return {Roo.Element} this
8902 repaint : function(){
8904 this.addClass("x-repaint");
8905 setTimeout(function(){
8906 Roo.get(dom).removeClass("x-repaint");
8912 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8913 * then it returns the calculated width of the sides (see getPadding)
8914 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8915 * @return {Object/Number}
8917 getMargins : function(side){
8920 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8921 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8922 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8923 right: parseInt(this.getStyle("margin-right"), 10) || 0
8926 return this.addStyles(side, El.margins);
8931 addStyles : function(sides, styles){
8933 for(var i = 0, len = sides.length; i < len; i++){
8934 v = this.getStyle(styles[sides.charAt(i)]);
8936 w = parseInt(v, 10);
8944 * Creates a proxy element of this element
8945 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8946 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8947 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8948 * @return {Roo.Element} The new proxy element
8950 createProxy : function(config, renderTo, matchBox){
8952 renderTo = Roo.getDom(renderTo);
8954 renderTo = document.body;
8956 config = typeof config == "object" ?
8957 config : {tag : "div", cls: config};
8958 var proxy = Roo.DomHelper.append(renderTo, config, true);
8960 proxy.setBox(this.getBox());
8966 * Puts a mask over this element to disable user interaction. Requires core.css.
8967 * This method can only be applied to elements which accept child nodes.
8968 * @param {String} msg (optional) A message to display in the mask
8969 * @param {String} msgCls (optional) A css class to apply to the msg element
8970 * @return {Element} The mask element
8972 mask : function(msg, msgCls)
8974 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
8975 this.setStyle("position", "relative");
8978 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8980 this.addClass("x-masked");
8981 this._mask.setDisplayed(true);
8986 while (dom && dom.style) {
8987 if (!isNaN(parseInt(dom.style.zIndex))) {
8988 z = Math.max(z, parseInt(dom.style.zIndex));
8990 dom = dom.parentNode;
8992 // if we are masking the body - then it hides everything..
8993 if (this.dom == document.body) {
8995 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
8996 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
8999 if(typeof msg == 'string'){
9001 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9003 var mm = this._maskMsg;
9004 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9005 mm.dom.firstChild.innerHTML = msg;
9006 mm.setDisplayed(true);
9008 mm.setStyle('z-index', z + 102);
9010 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9011 this._mask.setHeight(this.getHeight());
9013 this._mask.setStyle('z-index', z + 100);
9019 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9020 * it is cached for reuse.
9022 unmask : function(removeEl){
9024 if(removeEl === true){
9025 this._mask.remove();
9028 this._maskMsg.remove();
9029 delete this._maskMsg;
9032 this._mask.setDisplayed(false);
9034 this._maskMsg.setDisplayed(false);
9038 this.removeClass("x-masked");
9042 * Returns true if this element is masked
9045 isMasked : function(){
9046 return this._mask && this._mask.isVisible();
9050 * Creates an iframe shim for this element to keep selects and other windowed objects from
9052 * @return {Roo.Element} The new shim element
9054 createShim : function(){
9055 var el = document.createElement('iframe');
9056 el.frameBorder = 'no';
9057 el.className = 'roo-shim';
9058 if(Roo.isIE && Roo.isSecure){
9059 el.src = Roo.SSL_SECURE_URL;
9061 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9062 shim.autoBoxAdjust = false;
9067 * Removes this element from the DOM and deletes it from the cache
9069 remove : function(){
9070 if(this.dom.parentNode){
9071 this.dom.parentNode.removeChild(this.dom);
9073 delete El.cache[this.dom.id];
9077 * Sets up event handlers to add and remove a css class when the mouse is over this element
9078 * @param {String} className
9079 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9080 * mouseout events for children elements
9081 * @return {Roo.Element} this
9083 addClassOnOver : function(className, preventFlicker){
9084 this.on("mouseover", function(){
9085 Roo.fly(this, '_internal').addClass(className);
9087 var removeFn = function(e){
9088 if(preventFlicker !== true || !e.within(this, true)){
9089 Roo.fly(this, '_internal').removeClass(className);
9092 this.on("mouseout", removeFn, this.dom);
9097 * Sets up event handlers to add and remove a css class when this element has the focus
9098 * @param {String} className
9099 * @return {Roo.Element} this
9101 addClassOnFocus : function(className){
9102 this.on("focus", function(){
9103 Roo.fly(this, '_internal').addClass(className);
9105 this.on("blur", function(){
9106 Roo.fly(this, '_internal').removeClass(className);
9111 * 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)
9112 * @param {String} className
9113 * @return {Roo.Element} this
9115 addClassOnClick : function(className){
9117 this.on("mousedown", function(){
9118 Roo.fly(dom, '_internal').addClass(className);
9119 var d = Roo.get(document);
9120 var fn = function(){
9121 Roo.fly(dom, '_internal').removeClass(className);
9122 d.removeListener("mouseup", fn);
9124 d.on("mouseup", fn);
9130 * Stops the specified event from bubbling and optionally prevents the default action
9131 * @param {String} eventName
9132 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9133 * @return {Roo.Element} this
9135 swallowEvent : function(eventName, preventDefault){
9136 var fn = function(e){
9137 e.stopPropagation();
9142 if(eventName instanceof Array){
9143 for(var i = 0, len = eventName.length; i < len; i++){
9144 this.on(eventName[i], fn);
9148 this.on(eventName, fn);
9155 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9158 * Sizes this element to its parent element's dimensions performing
9159 * neccessary box adjustments.
9160 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9161 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9162 * @return {Roo.Element} this
9164 fitToParent : function(monitorResize, targetParent) {
9165 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9166 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9167 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9170 var p = Roo.get(targetParent || this.dom.parentNode);
9171 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9172 if (monitorResize === true) {
9173 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9174 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9180 * Gets the next sibling, skipping text nodes
9181 * @return {HTMLElement} The next sibling or null
9183 getNextSibling : function(){
9184 var n = this.dom.nextSibling;
9185 while(n && n.nodeType != 1){
9192 * Gets the previous sibling, skipping text nodes
9193 * @return {HTMLElement} The previous sibling or null
9195 getPrevSibling : function(){
9196 var n = this.dom.previousSibling;
9197 while(n && n.nodeType != 1){
9198 n = n.previousSibling;
9205 * Appends the passed element(s) to this element
9206 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9207 * @return {Roo.Element} this
9209 appendChild: function(el){
9216 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9217 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9218 * automatically generated with the specified attributes.
9219 * @param {HTMLElement} insertBefore (optional) a child element of this element
9220 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9221 * @return {Roo.Element} The new child element
9223 createChild: function(config, insertBefore, returnDom){
9224 config = config || {tag:'div'};
9226 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9228 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9232 * Appends this element to the passed element
9233 * @param {String/HTMLElement/Element} el The new parent element
9234 * @return {Roo.Element} this
9236 appendTo: function(el){
9237 el = Roo.getDom(el);
9238 el.appendChild(this.dom);
9243 * Inserts this element before the passed element in the DOM
9244 * @param {String/HTMLElement/Element} el The element to insert before
9245 * @return {Roo.Element} this
9247 insertBefore: function(el){
9248 el = Roo.getDom(el);
9249 el.parentNode.insertBefore(this.dom, el);
9254 * Inserts this element after the passed element in the DOM
9255 * @param {String/HTMLElement/Element} el The element to insert after
9256 * @return {Roo.Element} this
9258 insertAfter: function(el){
9259 el = Roo.getDom(el);
9260 el.parentNode.insertBefore(this.dom, el.nextSibling);
9265 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9266 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9267 * @return {Roo.Element} The new child
9269 insertFirst: function(el, returnDom){
9271 if(typeof el == 'object' && !el.nodeType){ // dh config
9272 return this.createChild(el, this.dom.firstChild, returnDom);
9274 el = Roo.getDom(el);
9275 this.dom.insertBefore(el, this.dom.firstChild);
9276 return !returnDom ? Roo.get(el) : el;
9281 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9282 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9283 * @param {String} where (optional) 'before' or 'after' defaults to before
9284 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9285 * @return {Roo.Element} the inserted Element
9287 insertSibling: function(el, where, returnDom){
9288 where = where ? where.toLowerCase() : 'before';
9290 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9292 if(typeof el == 'object' && !el.nodeType){ // dh config
9293 if(where == 'after' && !this.dom.nextSibling){
9294 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9296 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9300 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9301 where == 'before' ? this.dom : this.dom.nextSibling);
9310 * Creates and wraps this element with another element
9311 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9312 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9313 * @return {HTMLElement/Element} The newly created wrapper element
9315 wrap: function(config, returnDom){
9317 config = {tag: "div"};
9319 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9320 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9325 * Replaces the passed element with this element
9326 * @param {String/HTMLElement/Element} el The element to replace
9327 * @return {Roo.Element} this
9329 replace: function(el){
9331 this.insertBefore(el);
9337 * Inserts an html fragment into this element
9338 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9339 * @param {String} html The HTML fragment
9340 * @param {Boolean} returnEl True to return an Roo.Element
9341 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9343 insertHtml : function(where, html, returnEl){
9344 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9345 return returnEl ? Roo.get(el) : el;
9349 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9350 * @param {Object} o The object with the attributes
9351 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9352 * @return {Roo.Element} this
9354 set : function(o, useSet){
9356 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9358 if(attr == "style" || typeof o[attr] == "function") continue;
9360 el.className = o["cls"];
9362 if(useSet) el.setAttribute(attr, o[attr]);
9363 else el[attr] = o[attr];
9367 Roo.DomHelper.applyStyles(el, o.style);
9373 * Convenience method for constructing a KeyMap
9374 * @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:
9375 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9376 * @param {Function} fn The function to call
9377 * @param {Object} scope (optional) The scope of the function
9378 * @return {Roo.KeyMap} The KeyMap created
9380 addKeyListener : function(key, fn, scope){
9382 if(typeof key != "object" || key instanceof Array){
9398 return new Roo.KeyMap(this, config);
9402 * Creates a KeyMap for this element
9403 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9404 * @return {Roo.KeyMap} The KeyMap created
9406 addKeyMap : function(config){
9407 return new Roo.KeyMap(this, config);
9411 * Returns true if this element is scrollable.
9414 isScrollable : function(){
9416 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9420 * 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().
9421 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9422 * @param {Number} value The new scroll value
9423 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9424 * @return {Element} this
9427 scrollTo : function(side, value, animate){
9428 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9430 this.dom[prop] = value;
9432 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9433 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9439 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9440 * within this element's scrollable range.
9441 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9442 * @param {Number} distance How far to scroll the element in pixels
9443 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9444 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9445 * was scrolled as far as it could go.
9447 scroll : function(direction, distance, animate){
9448 if(!this.isScrollable()){
9452 var l = el.scrollLeft, t = el.scrollTop;
9453 var w = el.scrollWidth, h = el.scrollHeight;
9454 var cw = el.clientWidth, ch = el.clientHeight;
9455 direction = direction.toLowerCase();
9456 var scrolled = false;
9457 var a = this.preanim(arguments, 2);
9462 var v = Math.min(l + distance, w-cw);
9463 this.scrollTo("left", v, a);
9470 var v = Math.max(l - distance, 0);
9471 this.scrollTo("left", v, a);
9479 var v = Math.max(t - distance, 0);
9480 this.scrollTo("top", v, a);
9488 var v = Math.min(t + distance, h-ch);
9489 this.scrollTo("top", v, a);
9498 * Translates the passed page coordinates into left/top css values for this element
9499 * @param {Number/Array} x The page x or an array containing [x, y]
9500 * @param {Number} y The page y
9501 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9503 translatePoints : function(x, y){
9504 if(typeof x == 'object' || x instanceof Array){
9507 var p = this.getStyle('position');
9508 var o = this.getXY();
9510 var l = parseInt(this.getStyle('left'), 10);
9511 var t = parseInt(this.getStyle('top'), 10);
9514 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9517 t = (p == "relative") ? 0 : this.dom.offsetTop;
9520 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9524 * Returns the current scroll position of the element.
9525 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9527 getScroll : function(){
9528 var d = this.dom, doc = document;
9529 if(d == doc || d == doc.body){
9530 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9531 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9532 return {left: l, top: t};
9534 return {left: d.scrollLeft, top: d.scrollTop};
9539 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9540 * are convert to standard 6 digit hex color.
9541 * @param {String} attr The css attribute
9542 * @param {String} defaultValue The default value to use when a valid color isn't found
9543 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9546 getColor : function(attr, defaultValue, prefix){
9547 var v = this.getStyle(attr);
9548 if(!v || v == "transparent" || v == "inherit") {
9549 return defaultValue;
9551 var color = typeof prefix == "undefined" ? "#" : prefix;
9552 if(v.substr(0, 4) == "rgb("){
9553 var rvs = v.slice(4, v.length -1).split(",");
9554 for(var i = 0; i < 3; i++){
9555 var h = parseInt(rvs[i]).toString(16);
9562 if(v.substr(0, 1) == "#"){
9564 for(var i = 1; i < 4; i++){
9565 var c = v.charAt(i);
9568 }else if(v.length == 7){
9569 color += v.substr(1);
9573 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9577 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9578 * gradient background, rounded corners and a 4-way shadow.
9579 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9580 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9581 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9582 * @return {Roo.Element} this
9584 boxWrap : function(cls){
9585 cls = cls || 'x-box';
9586 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9587 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9592 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9593 * @param {String} namespace The namespace in which to look for the attribute
9594 * @param {String} name The attribute name
9595 * @return {String} The attribute value
9597 getAttributeNS : Roo.isIE ? function(ns, name){
9599 var type = typeof d[ns+":"+name];
9600 if(type != 'undefined' && type != 'unknown'){
9601 return d[ns+":"+name];
9604 } : function(ns, name){
9606 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9611 * Sets or Returns the value the dom attribute value
9612 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9613 * @param {String} value (optional) The value to set the attribute to
9614 * @return {String} The attribute value
9616 attr : function(name){
9617 if (arguments.length > 1) {
9618 this.dom.setAttribute(name, arguments[1]);
9619 return arguments[1];
9621 if (typeof(name) == 'object') {
9622 for(var i in name) {
9623 this.attr(i, name[i]);
9629 if (!this.dom.hasAttribute(name)) {
9632 return this.dom.getAttribute(name);
9639 var ep = El.prototype;
9642 * Appends an event handler (Shorthand for addListener)
9643 * @param {String} eventName The type of event to append
9644 * @param {Function} fn The method the event invokes
9645 * @param {Object} scope (optional) The scope (this object) of the fn
9646 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9649 ep.on = ep.addListener;
9651 ep.mon = ep.addListener;
9654 * Removes an event handler from this element (shorthand for removeListener)
9655 * @param {String} eventName the type of event to remove
9656 * @param {Function} fn the method the event invokes
9657 * @return {Roo.Element} this
9660 ep.un = ep.removeListener;
9663 * true to automatically adjust width and height settings for box-model issues (default to true)
9665 ep.autoBoxAdjust = true;
9668 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9671 El.addUnits = function(v, defaultUnit){
9672 if(v === "" || v == "auto"){
9675 if(v === undefined){
9678 if(typeof v == "number" || !El.unitPattern.test(v)){
9679 return v + (defaultUnit || 'px');
9684 // special markup used throughout Roo when box wrapping elements
9685 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>';
9687 * Visibility mode constant - Use visibility to hide element
9693 * Visibility mode constant - Use display to hide element
9699 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9700 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9701 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9713 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9714 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9715 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9716 * @return {Element} The Element object
9719 El.get = function(el){
9721 if(!el){ return null; }
9722 if(typeof el == "string"){ // element id
9723 if(!(elm = document.getElementById(el))){
9726 if(ex = El.cache[el]){
9729 ex = El.cache[el] = new El(elm);
9732 }else if(el.tagName){ // dom element
9736 if(ex = El.cache[id]){
9739 ex = El.cache[id] = new El(el);
9742 }else if(el instanceof El){
9744 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9745 // catch case where it hasn't been appended
9746 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9749 }else if(el.isComposite){
9751 }else if(el instanceof Array){
9752 return El.select(el);
9753 }else if(el == document){
9754 // create a bogus element object representing the document object
9756 var f = function(){};
9757 f.prototype = El.prototype;
9759 docEl.dom = document;
9767 El.uncache = function(el){
9768 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9770 delete El.cache[a[i].id || a[i]];
9776 // Garbage collection - uncache elements/purge listeners on orphaned elements
9777 // so we don't hold a reference and cause the browser to retain them
9778 El.garbageCollect = function(){
9779 if(!Roo.enableGarbageCollector){
9780 clearInterval(El.collectorThread);
9783 for(var eid in El.cache){
9784 var el = El.cache[eid], d = el.dom;
9785 // -------------------------------------------------------
9786 // Determining what is garbage:
9787 // -------------------------------------------------------
9789 // dom node is null, definitely garbage
9790 // -------------------------------------------------------
9792 // no parentNode == direct orphan, definitely garbage
9793 // -------------------------------------------------------
9794 // !d.offsetParent && !document.getElementById(eid)
9795 // display none elements have no offsetParent so we will
9796 // also try to look it up by it's id. However, check
9797 // offsetParent first so we don't do unneeded lookups.
9798 // This enables collection of elements that are not orphans
9799 // directly, but somewhere up the line they have an orphan
9801 // -------------------------------------------------------
9802 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9803 delete El.cache[eid];
9804 if(d && Roo.enableListenerCollection){
9810 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9814 El.Flyweight = function(dom){
9817 El.Flyweight.prototype = El.prototype;
9819 El._flyweights = {};
9821 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9822 * the dom node can be overwritten by other code.
9823 * @param {String/HTMLElement} el The dom node or id
9824 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9825 * prevent conflicts (e.g. internally Roo uses "_internal")
9827 * @return {Element} The shared Element object
9829 El.fly = function(el, named){
9830 named = named || '_global';
9831 el = Roo.getDom(el);
9835 if(!El._flyweights[named]){
9836 El._flyweights[named] = new El.Flyweight();
9838 El._flyweights[named].dom = el;
9839 return El._flyweights[named];
9843 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9844 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9845 * Shorthand of {@link Roo.Element#get}
9846 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9847 * @return {Element} The Element object
9853 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9854 * the dom node can be overwritten by other code.
9855 * Shorthand of {@link Roo.Element#fly}
9856 * @param {String/HTMLElement} el The dom node or id
9857 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9858 * prevent conflicts (e.g. internally Roo uses "_internal")
9860 * @return {Element} The shared Element object
9866 // speedy lookup for elements never to box adjust
9867 var noBoxAdjust = Roo.isStrict ? {
9870 input:1, select:1, textarea:1
9872 if(Roo.isIE || Roo.isGecko){
9873 noBoxAdjust['button'] = 1;
9877 Roo.EventManager.on(window, 'unload', function(){
9879 delete El._flyweights;
9887 Roo.Element.selectorFunction = Roo.DomQuery.select;
9890 Roo.Element.select = function(selector, unique, root){
9892 if(typeof selector == "string"){
9893 els = Roo.Element.selectorFunction(selector, root);
9894 }else if(selector.length !== undefined){
9897 throw "Invalid selector";
9899 if(unique === true){
9900 return new Roo.CompositeElement(els);
9902 return new Roo.CompositeElementLite(els);
9906 * Selects elements based on the passed CSS selector to enable working on them as 1.
9907 * @param {String/Array} selector The CSS selector or an array of elements
9908 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9909 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9910 * @return {CompositeElementLite/CompositeElement}
9914 Roo.select = Roo.Element.select;
9931 * Ext JS Library 1.1.1
9932 * Copyright(c) 2006-2007, Ext JS, LLC.
9934 * Originally Released Under LGPL - original licence link has changed is not relivant.
9937 * <script type="text/javascript">
9942 //Notifies Element that fx methods are available
9943 Roo.enableFx = true;
9947 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9948 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9949 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9950 * Element effects to work.</p><br/>
9952 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9953 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9954 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9955 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9956 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9957 * expected results and should be done with care.</p><br/>
9959 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9960 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9963 ----- -----------------------------
9964 tl The top left corner
9965 t The center of the top edge
9966 tr The top right corner
9967 l The center of the left edge
9968 r The center of the right edge
9969 bl The bottom left corner
9970 b The center of the bottom edge
9971 br The bottom right corner
9973 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9974 * below are common options that can be passed to any Fx method.</b>
9975 * @cfg {Function} callback A function called when the effect is finished
9976 * @cfg {Object} scope The scope of the effect function
9977 * @cfg {String} easing A valid Easing value for the effect
9978 * @cfg {String} afterCls A css class to apply after the effect
9979 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9980 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9981 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9982 * effects that end with the element being visually hidden, ignored otherwise)
9983 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9984 * a function which returns such a specification that will be applied to the Element after the effect finishes
9985 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9986 * @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
9987 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9991 * Slides the element into view. An anchor point can be optionally passed to set the point of
9992 * origin for the slide effect. This function automatically handles wrapping the element with
9993 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9996 // default: slide the element in from the top
9999 // custom: slide the element in from the right with a 2-second duration
10000 el.slideIn('r', { duration: 2 });
10002 // common config options shown with default values
10008 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10009 * @param {Object} options (optional) Object literal with any of the Fx config options
10010 * @return {Roo.Element} The Element
10012 slideIn : function(anchor, o){
10013 var el = this.getFxEl();
10016 el.queueFx(o, function(){
10018 anchor = anchor || "t";
10020 // fix display to visibility
10023 // restore values after effect
10024 var r = this.getFxRestore();
10025 var b = this.getBox();
10026 // fixed size for slide
10030 var wrap = this.fxWrap(r.pos, o, "hidden");
10032 var st = this.dom.style;
10033 st.visibility = "visible";
10034 st.position = "absolute";
10036 // clear out temp styles after slide and unwrap
10037 var after = function(){
10038 el.fxUnwrap(wrap, r.pos, o);
10039 st.width = r.width;
10040 st.height = r.height;
10043 // time to calc the positions
10044 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10046 switch(anchor.toLowerCase()){
10048 wrap.setSize(b.width, 0);
10049 st.left = st.bottom = "0";
10053 wrap.setSize(0, b.height);
10054 st.right = st.top = "0";
10058 wrap.setSize(0, b.height);
10059 wrap.setX(b.right);
10060 st.left = st.top = "0";
10061 a = {width: bw, points: pt};
10064 wrap.setSize(b.width, 0);
10065 wrap.setY(b.bottom);
10066 st.left = st.top = "0";
10067 a = {height: bh, points: pt};
10070 wrap.setSize(0, 0);
10071 st.right = st.bottom = "0";
10072 a = {width: bw, height: bh};
10075 wrap.setSize(0, 0);
10076 wrap.setY(b.y+b.height);
10077 st.right = st.top = "0";
10078 a = {width: bw, height: bh, points: pt};
10081 wrap.setSize(0, 0);
10082 wrap.setXY([b.right, b.bottom]);
10083 st.left = st.top = "0";
10084 a = {width: bw, height: bh, points: pt};
10087 wrap.setSize(0, 0);
10088 wrap.setX(b.x+b.width);
10089 st.left = st.bottom = "0";
10090 a = {width: bw, height: bh, points: pt};
10093 this.dom.style.visibility = "visible";
10096 arguments.callee.anim = wrap.fxanim(a,
10106 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10107 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10108 * 'hidden') but block elements will still take up space in the document. The element must be removed
10109 * from the DOM using the 'remove' config option if desired. This function automatically handles
10110 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10113 // default: slide the element out to the top
10116 // custom: slide the element out to the right with a 2-second duration
10117 el.slideOut('r', { duration: 2 });
10119 // common config options shown with default values
10127 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10128 * @param {Object} options (optional) Object literal with any of the Fx config options
10129 * @return {Roo.Element} The Element
10131 slideOut : function(anchor, o){
10132 var el = this.getFxEl();
10135 el.queueFx(o, function(){
10137 anchor = anchor || "t";
10139 // restore values after effect
10140 var r = this.getFxRestore();
10142 var b = this.getBox();
10143 // fixed size for slide
10147 var wrap = this.fxWrap(r.pos, o, "visible");
10149 var st = this.dom.style;
10150 st.visibility = "visible";
10151 st.position = "absolute";
10155 var after = function(){
10157 el.setDisplayed(false);
10162 el.fxUnwrap(wrap, r.pos, o);
10164 st.width = r.width;
10165 st.height = r.height;
10170 var a, zero = {to: 0};
10171 switch(anchor.toLowerCase()){
10173 st.left = st.bottom = "0";
10174 a = {height: zero};
10177 st.right = st.top = "0";
10181 st.left = st.top = "0";
10182 a = {width: zero, points: {to:[b.right, b.y]}};
10185 st.left = st.top = "0";
10186 a = {height: zero, points: {to:[b.x, b.bottom]}};
10189 st.right = st.bottom = "0";
10190 a = {width: zero, height: zero};
10193 st.right = st.top = "0";
10194 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10197 st.left = st.top = "0";
10198 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10201 st.left = st.bottom = "0";
10202 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10206 arguments.callee.anim = wrap.fxanim(a,
10216 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10217 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10218 * The element must be removed from the DOM using the 'remove' config option if desired.
10224 // common config options shown with default values
10232 * @param {Object} options (optional) Object literal with any of the Fx config options
10233 * @return {Roo.Element} The Element
10235 puff : function(o){
10236 var el = this.getFxEl();
10239 el.queueFx(o, function(){
10240 this.clearOpacity();
10243 // restore values after effect
10244 var r = this.getFxRestore();
10245 var st = this.dom.style;
10247 var after = function(){
10249 el.setDisplayed(false);
10256 el.setPositioning(r.pos);
10257 st.width = r.width;
10258 st.height = r.height;
10263 var width = this.getWidth();
10264 var height = this.getHeight();
10266 arguments.callee.anim = this.fxanim({
10267 width : {to: this.adjustWidth(width * 2)},
10268 height : {to: this.adjustHeight(height * 2)},
10269 points : {by: [-(width * .5), -(height * .5)]},
10271 fontSize: {to:200, unit: "%"}
10282 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10283 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10284 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10290 // all config options shown with default values
10298 * @param {Object} options (optional) Object literal with any of the Fx config options
10299 * @return {Roo.Element} The Element
10301 switchOff : function(o){
10302 var el = this.getFxEl();
10305 el.queueFx(o, function(){
10306 this.clearOpacity();
10309 // restore values after effect
10310 var r = this.getFxRestore();
10311 var st = this.dom.style;
10313 var after = function(){
10315 el.setDisplayed(false);
10321 el.setPositioning(r.pos);
10322 st.width = r.width;
10323 st.height = r.height;
10328 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10329 this.clearOpacity();
10333 points:{by:[0, this.getHeight() * .5]}
10334 }, o, 'motion', 0.3, 'easeIn', after);
10335 }).defer(100, this);
10342 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10343 * changed using the "attr" config option) and then fading back to the original color. If no original
10344 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10347 // default: highlight background to yellow
10350 // custom: highlight foreground text to blue for 2 seconds
10351 el.highlight("0000ff", { attr: 'color', duration: 2 });
10353 // common config options shown with default values
10354 el.highlight("ffff9c", {
10355 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10356 endColor: (current color) or "ffffff",
10361 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10362 * @param {Object} options (optional) Object literal with any of the Fx config options
10363 * @return {Roo.Element} The Element
10365 highlight : function(color, o){
10366 var el = this.getFxEl();
10369 el.queueFx(o, function(){
10370 color = color || "ffff9c";
10371 attr = o.attr || "backgroundColor";
10373 this.clearOpacity();
10376 var origColor = this.getColor(attr);
10377 var restoreColor = this.dom.style[attr];
10378 endColor = (o.endColor || origColor) || "ffffff";
10380 var after = function(){
10381 el.dom.style[attr] = restoreColor;
10386 a[attr] = {from: color, to: endColor};
10387 arguments.callee.anim = this.fxanim(a,
10397 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10400 // default: a single light blue ripple
10403 // custom: 3 red ripples lasting 3 seconds total
10404 el.frame("ff0000", 3, { duration: 3 });
10406 // common config options shown with default values
10407 el.frame("C3DAF9", 1, {
10408 duration: 1 //duration of entire animation (not each individual ripple)
10409 // Note: Easing is not configurable and will be ignored if included
10412 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10413 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10414 * @param {Object} options (optional) Object literal with any of the Fx config options
10415 * @return {Roo.Element} The Element
10417 frame : function(color, count, o){
10418 var el = this.getFxEl();
10421 el.queueFx(o, function(){
10422 color = color || "#C3DAF9";
10423 if(color.length == 6){
10424 color = "#" + color;
10426 count = count || 1;
10427 duration = o.duration || 1;
10430 var b = this.getBox();
10431 var animFn = function(){
10432 var proxy = this.createProxy({
10435 visbility:"hidden",
10436 position:"absolute",
10437 "z-index":"35000", // yee haw
10438 border:"0px solid " + color
10441 var scale = Roo.isBorderBox ? 2 : 1;
10443 top:{from:b.y, to:b.y - 20},
10444 left:{from:b.x, to:b.x - 20},
10445 borderWidth:{from:0, to:10},
10446 opacity:{from:1, to:0},
10447 height:{from:b.height, to:(b.height + (20*scale))},
10448 width:{from:b.width, to:(b.width + (20*scale))}
10449 }, duration, function(){
10453 animFn.defer((duration/2)*1000, this);
10464 * Creates a pause before any subsequent queued effects begin. If there are
10465 * no effects queued after the pause it will have no effect.
10470 * @param {Number} seconds The length of time to pause (in seconds)
10471 * @return {Roo.Element} The Element
10473 pause : function(seconds){
10474 var el = this.getFxEl();
10477 el.queueFx(o, function(){
10478 setTimeout(function(){
10480 }, seconds * 1000);
10486 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10487 * using the "endOpacity" config option.
10490 // default: fade in from opacity 0 to 100%
10493 // custom: fade in from opacity 0 to 75% over 2 seconds
10494 el.fadeIn({ endOpacity: .75, duration: 2});
10496 // common config options shown with default values
10498 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10503 * @param {Object} options (optional) Object literal with any of the Fx config options
10504 * @return {Roo.Element} The Element
10506 fadeIn : function(o){
10507 var el = this.getFxEl();
10509 el.queueFx(o, function(){
10510 this.setOpacity(0);
10512 this.dom.style.visibility = 'visible';
10513 var to = o.endOpacity || 1;
10514 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10515 o, null, .5, "easeOut", function(){
10517 this.clearOpacity();
10526 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10527 * using the "endOpacity" config option.
10530 // default: fade out from the element's current opacity to 0
10533 // custom: fade out from the element's current opacity to 25% over 2 seconds
10534 el.fadeOut({ endOpacity: .25, duration: 2});
10536 // common config options shown with default values
10538 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10545 * @param {Object} options (optional) Object literal with any of the Fx config options
10546 * @return {Roo.Element} The Element
10548 fadeOut : function(o){
10549 var el = this.getFxEl();
10551 el.queueFx(o, function(){
10552 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10553 o, null, .5, "easeOut", function(){
10554 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10555 this.dom.style.display = "none";
10557 this.dom.style.visibility = "hidden";
10559 this.clearOpacity();
10567 * Animates the transition of an element's dimensions from a starting height/width
10568 * to an ending height/width.
10571 // change height and width to 100x100 pixels
10572 el.scale(100, 100);
10574 // common config options shown with default values. The height and width will default to
10575 // the element's existing values if passed as null.
10578 [element's height], {
10583 * @param {Number} width The new width (pass undefined to keep the original width)
10584 * @param {Number} height The new height (pass undefined to keep the original height)
10585 * @param {Object} options (optional) Object literal with any of the Fx config options
10586 * @return {Roo.Element} The Element
10588 scale : function(w, h, o){
10589 this.shift(Roo.apply({}, o, {
10597 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10598 * Any of these properties not specified in the config object will not be changed. This effect
10599 * requires that at least one new dimension, position or opacity setting must be passed in on
10600 * the config object in order for the function to have any effect.
10603 // slide the element horizontally to x position 200 while changing the height and opacity
10604 el.shift({ x: 200, height: 50, opacity: .8 });
10606 // common config options shown with default values.
10608 width: [element's width],
10609 height: [element's height],
10610 x: [element's x position],
10611 y: [element's y position],
10612 opacity: [element's opacity],
10617 * @param {Object} options Object literal with any of the Fx config options
10618 * @return {Roo.Element} The Element
10620 shift : function(o){
10621 var el = this.getFxEl();
10623 el.queueFx(o, function(){
10624 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10625 if(w !== undefined){
10626 a.width = {to: this.adjustWidth(w)};
10628 if(h !== undefined){
10629 a.height = {to: this.adjustHeight(h)};
10631 if(x !== undefined || y !== undefined){
10633 x !== undefined ? x : this.getX(),
10634 y !== undefined ? y : this.getY()
10637 if(op !== undefined){
10638 a.opacity = {to: op};
10640 if(o.xy !== undefined){
10641 a.points = {to: o.xy};
10643 arguments.callee.anim = this.fxanim(a,
10644 o, 'motion', .35, "easeOut", function(){
10652 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10653 * ending point of the effect.
10656 // default: slide the element downward while fading out
10659 // custom: slide the element out to the right with a 2-second duration
10660 el.ghost('r', { duration: 2 });
10662 // common config options shown with default values
10670 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10671 * @param {Object} options (optional) Object literal with any of the Fx config options
10672 * @return {Roo.Element} The Element
10674 ghost : function(anchor, o){
10675 var el = this.getFxEl();
10678 el.queueFx(o, function(){
10679 anchor = anchor || "b";
10681 // restore values after effect
10682 var r = this.getFxRestore();
10683 var w = this.getWidth(),
10684 h = this.getHeight();
10686 var st = this.dom.style;
10688 var after = function(){
10690 el.setDisplayed(false);
10696 el.setPositioning(r.pos);
10697 st.width = r.width;
10698 st.height = r.height;
10703 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10704 switch(anchor.toLowerCase()){
10731 arguments.callee.anim = this.fxanim(a,
10741 * Ensures that all effects queued after syncFx is called on the element are
10742 * run concurrently. This is the opposite of {@link #sequenceFx}.
10743 * @return {Roo.Element} The Element
10745 syncFx : function(){
10746 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10755 * Ensures that all effects queued after sequenceFx is called on the element are
10756 * run in sequence. This is the opposite of {@link #syncFx}.
10757 * @return {Roo.Element} The Element
10759 sequenceFx : function(){
10760 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10762 concurrent : false,
10769 nextFx : function(){
10770 var ef = this.fxQueue[0];
10777 * Returns true if the element has any effects actively running or queued, else returns false.
10778 * @return {Boolean} True if element has active effects, else false
10780 hasActiveFx : function(){
10781 return this.fxQueue && this.fxQueue[0];
10785 * Stops any running effects and clears the element's internal effects queue if it contains
10786 * any additional effects that haven't started yet.
10787 * @return {Roo.Element} The Element
10789 stopFx : function(){
10790 if(this.hasActiveFx()){
10791 var cur = this.fxQueue[0];
10792 if(cur && cur.anim && cur.anim.isAnimated()){
10793 this.fxQueue = [cur]; // clear out others
10794 cur.anim.stop(true);
10801 beforeFx : function(o){
10802 if(this.hasActiveFx() && !o.concurrent){
10813 * Returns true if the element is currently blocking so that no other effect can be queued
10814 * until this effect is finished, else returns false if blocking is not set. This is commonly
10815 * used to ensure that an effect initiated by a user action runs to completion prior to the
10816 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10817 * @return {Boolean} True if blocking, else false
10819 hasFxBlock : function(){
10820 var q = this.fxQueue;
10821 return q && q[0] && q[0].block;
10825 queueFx : function(o, fn){
10829 if(!this.hasFxBlock()){
10830 Roo.applyIf(o, this.fxDefaults);
10832 var run = this.beforeFx(o);
10833 fn.block = o.block;
10834 this.fxQueue.push(fn);
10846 fxWrap : function(pos, o, vis){
10848 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10851 wrapXY = this.getXY();
10853 var div = document.createElement("div");
10854 div.style.visibility = vis;
10855 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10856 wrap.setPositioning(pos);
10857 if(wrap.getStyle("position") == "static"){
10858 wrap.position("relative");
10860 this.clearPositioning('auto');
10862 wrap.dom.appendChild(this.dom);
10864 wrap.setXY(wrapXY);
10871 fxUnwrap : function(wrap, pos, o){
10872 this.clearPositioning();
10873 this.setPositioning(pos);
10875 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10881 getFxRestore : function(){
10882 var st = this.dom.style;
10883 return {pos: this.getPositioning(), width: st.width, height : st.height};
10887 afterFx : function(o){
10889 this.applyStyles(o.afterStyle);
10892 this.addClass(o.afterCls);
10894 if(o.remove === true){
10897 Roo.callback(o.callback, o.scope, [this]);
10899 this.fxQueue.shift();
10905 getFxEl : function(){ // support for composite element fx
10906 return Roo.get(this.dom);
10910 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10911 animType = animType || 'run';
10913 var anim = Roo.lib.Anim[animType](
10915 (opt.duration || defaultDur) || .35,
10916 (opt.easing || defaultEase) || 'easeOut',
10918 Roo.callback(cb, this);
10927 // backwords compat
10928 Roo.Fx.resize = Roo.Fx.scale;
10930 //When included, Roo.Fx is automatically applied to Element so that all basic
10931 //effects are available directly via the Element API
10932 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10934 * Ext JS Library 1.1.1
10935 * Copyright(c) 2006-2007, Ext JS, LLC.
10937 * Originally Released Under LGPL - original licence link has changed is not relivant.
10940 * <script type="text/javascript">
10945 * @class Roo.CompositeElement
10946 * Standard composite class. Creates a Roo.Element for every element in the collection.
10948 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10949 * actions will be performed on all the elements in this collection.</b>
10951 * All methods return <i>this</i> and can be chained.
10953 var els = Roo.select("#some-el div.some-class", true);
10954 // or select directly from an existing element
10955 var el = Roo.get('some-el');
10956 el.select('div.some-class', true);
10958 els.setWidth(100); // all elements become 100 width
10959 els.hide(true); // all elements fade out and hide
10961 els.setWidth(100).hide(true);
10964 Roo.CompositeElement = function(els){
10965 this.elements = [];
10966 this.addElements(els);
10968 Roo.CompositeElement.prototype = {
10970 addElements : function(els){
10971 if(!els) return this;
10972 if(typeof els == "string"){
10973 els = Roo.Element.selectorFunction(els);
10975 var yels = this.elements;
10976 var index = yels.length-1;
10977 for(var i = 0, len = els.length; i < len; i++) {
10978 yels[++index] = Roo.get(els[i]);
10984 * Clears this composite and adds the elements returned by the passed selector.
10985 * @param {String/Array} els A string CSS selector, an array of elements or an element
10986 * @return {CompositeElement} this
10988 fill : function(els){
10989 this.elements = [];
10995 * Filters this composite to only elements that match the passed selector.
10996 * @param {String} selector A string CSS selector
10997 * @param {Boolean} inverse return inverse filter (not matches)
10998 * @return {CompositeElement} this
11000 filter : function(selector, inverse){
11002 inverse = inverse || false;
11003 this.each(function(el){
11004 var match = inverse ? !el.is(selector) : el.is(selector);
11006 els[els.length] = el.dom;
11013 invoke : function(fn, args){
11014 var els = this.elements;
11015 for(var i = 0, len = els.length; i < len; i++) {
11016 Roo.Element.prototype[fn].apply(els[i], args);
11021 * Adds elements to this composite.
11022 * @param {String/Array} els A string CSS selector, an array of elements or an element
11023 * @return {CompositeElement} this
11025 add : function(els){
11026 if(typeof els == "string"){
11027 this.addElements(Roo.Element.selectorFunction(els));
11028 }else if(els.length !== undefined){
11029 this.addElements(els);
11031 this.addElements([els]);
11036 * Calls the passed function passing (el, this, index) for each element in this composite.
11037 * @param {Function} fn The function to call
11038 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11039 * @return {CompositeElement} this
11041 each : function(fn, scope){
11042 var els = this.elements;
11043 for(var i = 0, len = els.length; i < len; i++){
11044 if(fn.call(scope || els[i], els[i], this, i) === false) {
11052 * Returns the Element object at the specified index
11053 * @param {Number} index
11054 * @return {Roo.Element}
11056 item : function(index){
11057 return this.elements[index] || null;
11061 * Returns the first Element
11062 * @return {Roo.Element}
11064 first : function(){
11065 return this.item(0);
11069 * Returns the last Element
11070 * @return {Roo.Element}
11073 return this.item(this.elements.length-1);
11077 * Returns the number of elements in this composite
11080 getCount : function(){
11081 return this.elements.length;
11085 * Returns true if this composite contains the passed element
11088 contains : function(el){
11089 return this.indexOf(el) !== -1;
11093 * Returns true if this composite contains the passed element
11096 indexOf : function(el){
11097 return this.elements.indexOf(Roo.get(el));
11102 * Removes the specified element(s).
11103 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11104 * or an array of any of those.
11105 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11106 * @return {CompositeElement} this
11108 removeElement : function(el, removeDom){
11109 if(el instanceof Array){
11110 for(var i = 0, len = el.length; i < len; i++){
11111 this.removeElement(el[i]);
11115 var index = typeof el == 'number' ? el : this.indexOf(el);
11118 var d = this.elements[index];
11122 d.parentNode.removeChild(d);
11125 this.elements.splice(index, 1);
11131 * Replaces the specified element with the passed element.
11132 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11134 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11135 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11136 * @return {CompositeElement} this
11138 replaceElement : function(el, replacement, domReplace){
11139 var index = typeof el == 'number' ? el : this.indexOf(el);
11142 this.elements[index].replaceWith(replacement);
11144 this.elements.splice(index, 1, Roo.get(replacement))
11151 * Removes all elements.
11153 clear : function(){
11154 this.elements = [];
11158 Roo.CompositeElement.createCall = function(proto, fnName){
11159 if(!proto[fnName]){
11160 proto[fnName] = function(){
11161 return this.invoke(fnName, arguments);
11165 for(var fnName in Roo.Element.prototype){
11166 if(typeof Roo.Element.prototype[fnName] == "function"){
11167 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11173 * Ext JS Library 1.1.1
11174 * Copyright(c) 2006-2007, Ext JS, LLC.
11176 * Originally Released Under LGPL - original licence link has changed is not relivant.
11179 * <script type="text/javascript">
11183 * @class Roo.CompositeElementLite
11184 * @extends Roo.CompositeElement
11185 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11187 var els = Roo.select("#some-el div.some-class");
11188 // or select directly from an existing element
11189 var el = Roo.get('some-el');
11190 el.select('div.some-class');
11192 els.setWidth(100); // all elements become 100 width
11193 els.hide(true); // all elements fade out and hide
11195 els.setWidth(100).hide(true);
11196 </code></pre><br><br>
11197 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11198 * actions will be performed on all the elements in this collection.</b>
11200 Roo.CompositeElementLite = function(els){
11201 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11202 this.el = new Roo.Element.Flyweight();
11204 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11205 addElements : function(els){
11207 if(els instanceof Array){
11208 this.elements = this.elements.concat(els);
11210 var yels = this.elements;
11211 var index = yels.length-1;
11212 for(var i = 0, len = els.length; i < len; i++) {
11213 yels[++index] = els[i];
11219 invoke : function(fn, args){
11220 var els = this.elements;
11222 for(var i = 0, len = els.length; i < len; i++) {
11224 Roo.Element.prototype[fn].apply(el, args);
11229 * Returns a flyweight Element of the dom element object at the specified index
11230 * @param {Number} index
11231 * @return {Roo.Element}
11233 item : function(index){
11234 if(!this.elements[index]){
11237 this.el.dom = this.elements[index];
11241 // fixes scope with flyweight
11242 addListener : function(eventName, handler, scope, opt){
11243 var els = this.elements;
11244 for(var i = 0, len = els.length; i < len; i++) {
11245 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11251 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11252 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11253 * a reference to the dom node, use el.dom.</b>
11254 * @param {Function} fn The function to call
11255 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11256 * @return {CompositeElement} this
11258 each : function(fn, scope){
11259 var els = this.elements;
11261 for(var i = 0, len = els.length; i < len; i++){
11263 if(fn.call(scope || el, el, this, i) === false){
11270 indexOf : function(el){
11271 return this.elements.indexOf(Roo.getDom(el));
11274 replaceElement : function(el, replacement, domReplace){
11275 var index = typeof el == 'number' ? el : this.indexOf(el);
11277 replacement = Roo.getDom(replacement);
11279 var d = this.elements[index];
11280 d.parentNode.insertBefore(replacement, d);
11281 d.parentNode.removeChild(d);
11283 this.elements.splice(index, 1, replacement);
11288 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11292 * Ext JS Library 1.1.1
11293 * Copyright(c) 2006-2007, Ext JS, LLC.
11295 * Originally Released Under LGPL - original licence link has changed is not relivant.
11298 * <script type="text/javascript">
11304 * @class Roo.data.Connection
11305 * @extends Roo.util.Observable
11306 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11307 * either to a configured URL, or to a URL specified at request time.<br><br>
11309 * Requests made by this class are asynchronous, and will return immediately. No data from
11310 * the server will be available to the statement immediately following the {@link #request} call.
11311 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11313 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11314 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11315 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11316 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11317 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11318 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11319 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11320 * standard DOM methods.
11322 * @param {Object} config a configuration object.
11324 Roo.data.Connection = function(config){
11325 Roo.apply(this, config);
11328 * @event beforerequest
11329 * Fires before a network request is made to retrieve a data object.
11330 * @param {Connection} conn This Connection object.
11331 * @param {Object} options The options config object passed to the {@link #request} method.
11333 "beforerequest" : true,
11335 * @event requestcomplete
11336 * Fires if the request was successfully completed.
11337 * @param {Connection} conn This Connection object.
11338 * @param {Object} response The XHR object containing the response data.
11339 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11340 * @param {Object} options The options config object passed to the {@link #request} method.
11342 "requestcomplete" : true,
11344 * @event requestexception
11345 * Fires if an error HTTP status was returned from the server.
11346 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11347 * @param {Connection} conn This Connection object.
11348 * @param {Object} response The XHR object containing the response data.
11349 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11350 * @param {Object} options The options config object passed to the {@link #request} method.
11352 "requestexception" : true
11354 Roo.data.Connection.superclass.constructor.call(this);
11357 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11359 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11362 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11363 * extra parameters to each request made by this object. (defaults to undefined)
11366 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11367 * to each request made by this object. (defaults to undefined)
11370 * @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)
11373 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11377 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11383 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11386 disableCaching: true,
11389 * Sends an HTTP request to a remote server.
11390 * @param {Object} options An object which may contain the following properties:<ul>
11391 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11392 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11393 * request, a url encoded string or a function to call to get either.</li>
11394 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11395 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11396 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11397 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11398 * <li>options {Object} The parameter to the request call.</li>
11399 * <li>success {Boolean} True if the request succeeded.</li>
11400 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11402 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11403 * The callback is passed the following parameters:<ul>
11404 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11405 * <li>options {Object} The parameter to the request call.</li>
11407 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11408 * The callback is passed the following parameters:<ul>
11409 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11410 * <li>options {Object} The parameter to the request call.</li>
11412 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11413 * for the callback function. Defaults to the browser window.</li>
11414 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11415 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11416 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11417 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11418 * params for the post data. Any params will be appended to the URL.</li>
11419 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11421 * @return {Number} transactionId
11423 request : function(o){
11424 if(this.fireEvent("beforerequest", this, o) !== false){
11427 if(typeof p == "function"){
11428 p = p.call(o.scope||window, o);
11430 if(typeof p == "object"){
11431 p = Roo.urlEncode(o.params);
11433 if(this.extraParams){
11434 var extras = Roo.urlEncode(this.extraParams);
11435 p = p ? (p + '&' + extras) : extras;
11438 var url = o.url || this.url;
11439 if(typeof url == 'function'){
11440 url = url.call(o.scope||window, o);
11444 var form = Roo.getDom(o.form);
11445 url = url || form.action;
11447 var enctype = form.getAttribute("enctype");
11448 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11449 return this.doFormUpload(o, p, url);
11451 var f = Roo.lib.Ajax.serializeForm(form);
11452 p = p ? (p + '&' + f) : f;
11455 var hs = o.headers;
11456 if(this.defaultHeaders){
11457 hs = Roo.apply(hs || {}, this.defaultHeaders);
11464 success: this.handleResponse,
11465 failure: this.handleFailure,
11467 argument: {options: o},
11468 timeout : o.timeout || this.timeout
11471 var method = o.method||this.method||(p ? "POST" : "GET");
11473 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11474 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11477 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11481 }else if(this.autoAbort !== false){
11485 if((method == 'GET' && p) || o.xmlData){
11486 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11489 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11490 return this.transId;
11492 Roo.callback(o.callback, o.scope, [o, null, null]);
11498 * Determine whether this object has a request outstanding.
11499 * @param {Number} transactionId (Optional) defaults to the last transaction
11500 * @return {Boolean} True if there is an outstanding request.
11502 isLoading : function(transId){
11504 return Roo.lib.Ajax.isCallInProgress(transId);
11506 return this.transId ? true : false;
11511 * Aborts any outstanding request.
11512 * @param {Number} transactionId (Optional) defaults to the last transaction
11514 abort : function(transId){
11515 if(transId || this.isLoading()){
11516 Roo.lib.Ajax.abort(transId || this.transId);
11521 handleResponse : function(response){
11522 this.transId = false;
11523 var options = response.argument.options;
11524 response.argument = options ? options.argument : null;
11525 this.fireEvent("requestcomplete", this, response, options);
11526 Roo.callback(options.success, options.scope, [response, options]);
11527 Roo.callback(options.callback, options.scope, [options, true, response]);
11531 handleFailure : function(response, e){
11532 this.transId = false;
11533 var options = response.argument.options;
11534 response.argument = options ? options.argument : null;
11535 this.fireEvent("requestexception", this, response, options, e);
11536 Roo.callback(options.failure, options.scope, [response, options]);
11537 Roo.callback(options.callback, options.scope, [options, false, response]);
11541 doFormUpload : function(o, ps, url){
11543 var frame = document.createElement('iframe');
11546 frame.className = 'x-hidden';
11548 frame.src = Roo.SSL_SECURE_URL;
11550 document.body.appendChild(frame);
11553 document.frames[id].name = id;
11556 var form = Roo.getDom(o.form);
11558 form.method = 'POST';
11559 form.enctype = form.encoding = 'multipart/form-data';
11565 if(ps){ // add dynamic params
11567 ps = Roo.urlDecode(ps, false);
11569 if(ps.hasOwnProperty(k)){
11570 hd = document.createElement('input');
11571 hd.type = 'hidden';
11574 form.appendChild(hd);
11581 var r = { // bogus response object
11586 r.argument = o ? o.argument : null;
11591 doc = frame.contentWindow.document;
11593 doc = (frame.contentDocument || window.frames[id].document);
11595 if(doc && doc.body){
11596 r.responseText = doc.body.innerHTML;
11598 if(doc && doc.XMLDocument){
11599 r.responseXML = doc.XMLDocument;
11601 r.responseXML = doc;
11608 Roo.EventManager.removeListener(frame, 'load', cb, this);
11610 this.fireEvent("requestcomplete", this, r, o);
11611 Roo.callback(o.success, o.scope, [r, o]);
11612 Roo.callback(o.callback, o.scope, [o, true, r]);
11614 setTimeout(function(){document.body.removeChild(frame);}, 100);
11617 Roo.EventManager.on(frame, 'load', cb, this);
11620 if(hiddens){ // remove dynamic params
11621 for(var i = 0, len = hiddens.length; i < len; i++){
11622 form.removeChild(hiddens[i]);
11629 * Ext JS Library 1.1.1
11630 * Copyright(c) 2006-2007, Ext JS, LLC.
11632 * Originally Released Under LGPL - original licence link has changed is not relivant.
11635 * <script type="text/javascript">
11639 * Global Ajax request class.
11642 * @extends Roo.data.Connection
11645 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11646 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11647 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11648 * @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)
11649 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11650 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11651 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11653 Roo.Ajax = new Roo.data.Connection({
11662 * Serialize the passed form into a url encoded string
11664 * @param {String/HTMLElement} form
11667 serializeForm : function(form){
11668 return Roo.lib.Ajax.serializeForm(form);
11672 * Ext JS Library 1.1.1
11673 * Copyright(c) 2006-2007, Ext JS, LLC.
11675 * Originally Released Under LGPL - original licence link has changed is not relivant.
11678 * <script type="text/javascript">
11683 * @class Roo.UpdateManager
11684 * @extends Roo.util.Observable
11685 * Provides AJAX-style update for Element object.<br><br>
11688 * // Get it from a Roo.Element object
11689 * var el = Roo.get("foo");
11690 * var mgr = el.getUpdateManager();
11691 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11693 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11695 * // or directly (returns the same UpdateManager instance)
11696 * var mgr = new Roo.UpdateManager("myElementId");
11697 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11698 * mgr.on("update", myFcnNeedsToKnow);
11700 // short handed call directly from the element object
11701 Roo.get("foo").load({
11705 text: "Loading Foo..."
11709 * Create new UpdateManager directly.
11710 * @param {String/HTMLElement/Roo.Element} el The element to update
11711 * @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).
11713 Roo.UpdateManager = function(el, forceNew){
11715 if(!forceNew && el.updateManager){
11716 return el.updateManager;
11719 * The Element object
11720 * @type Roo.Element
11724 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11727 this.defaultUrl = null;
11731 * @event beforeupdate
11732 * Fired before an update is made, return false from your handler and the update is cancelled.
11733 * @param {Roo.Element} el
11734 * @param {String/Object/Function} url
11735 * @param {String/Object} params
11737 "beforeupdate": true,
11740 * Fired after successful update is made.
11741 * @param {Roo.Element} el
11742 * @param {Object} oResponseObject The response Object
11747 * Fired on update failure.
11748 * @param {Roo.Element} el
11749 * @param {Object} oResponseObject The response Object
11753 var d = Roo.UpdateManager.defaults;
11755 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11758 this.sslBlankUrl = d.sslBlankUrl;
11760 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11763 this.disableCaching = d.disableCaching;
11765 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11768 this.indicatorText = d.indicatorText;
11770 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11773 this.showLoadIndicator = d.showLoadIndicator;
11775 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11778 this.timeout = d.timeout;
11781 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11784 this.loadScripts = d.loadScripts;
11787 * Transaction object of current executing transaction
11789 this.transaction = null;
11794 this.autoRefreshProcId = null;
11796 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11799 this.refreshDelegate = this.refresh.createDelegate(this);
11801 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11804 this.updateDelegate = this.update.createDelegate(this);
11806 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11809 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11813 this.successDelegate = this.processSuccess.createDelegate(this);
11817 this.failureDelegate = this.processFailure.createDelegate(this);
11819 if(!this.renderer){
11821 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11823 this.renderer = new Roo.UpdateManager.BasicRenderer();
11826 Roo.UpdateManager.superclass.constructor.call(this);
11829 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11831 * Get the Element this UpdateManager is bound to
11832 * @return {Roo.Element} The element
11834 getEl : function(){
11838 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11839 * @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:
11842 url: "your-url.php",<br/>
11843 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11844 callback: yourFunction,<br/>
11845 scope: yourObject, //(optional scope) <br/>
11846 discardUrl: false, <br/>
11847 nocache: false,<br/>
11848 text: "Loading...",<br/>
11850 scripts: false<br/>
11853 * The only required property is url. The optional properties nocache, text and scripts
11854 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11855 * @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}
11856 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11857 * @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.
11859 update : function(url, params, callback, discardUrl){
11860 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11861 var method = this.method,
11863 if(typeof url == "object"){ // must be config object
11866 params = params || cfg.params;
11867 callback = callback || cfg.callback;
11868 discardUrl = discardUrl || cfg.discardUrl;
11869 if(callback && cfg.scope){
11870 callback = callback.createDelegate(cfg.scope);
11872 if(typeof cfg.method != "undefined"){method = cfg.method;};
11873 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11874 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11875 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11876 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11878 this.showLoading();
11880 this.defaultUrl = url;
11882 if(typeof url == "function"){
11883 url = url.call(this);
11886 method = method || (params ? "POST" : "GET");
11887 if(method == "GET"){
11888 url = this.prepareUrl(url);
11891 var o = Roo.apply(cfg ||{}, {
11894 success: this.successDelegate,
11895 failure: this.failureDelegate,
11896 callback: undefined,
11897 timeout: (this.timeout*1000),
11898 argument: {"url": url, "form": null, "callback": callback, "params": params}
11900 Roo.log("updated manager called with timeout of " + o.timeout);
11901 this.transaction = Roo.Ajax.request(o);
11906 * 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.
11907 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11908 * @param {String/HTMLElement} form The form Id or form element
11909 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11910 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11911 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11913 formUpdate : function(form, url, reset, callback){
11914 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11915 if(typeof url == "function"){
11916 url = url.call(this);
11918 form = Roo.getDom(form);
11919 this.transaction = Roo.Ajax.request({
11922 success: this.successDelegate,
11923 failure: this.failureDelegate,
11924 timeout: (this.timeout*1000),
11925 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11927 this.showLoading.defer(1, this);
11932 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11933 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11935 refresh : function(callback){
11936 if(this.defaultUrl == null){
11939 this.update(this.defaultUrl, null, callback, true);
11943 * Set this element to auto refresh.
11944 * @param {Number} interval How often to update (in seconds).
11945 * @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)
11946 * @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}
11947 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11948 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11950 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11952 this.update(url || this.defaultUrl, params, callback, true);
11954 if(this.autoRefreshProcId){
11955 clearInterval(this.autoRefreshProcId);
11957 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11961 * Stop auto refresh on this element.
11963 stopAutoRefresh : function(){
11964 if(this.autoRefreshProcId){
11965 clearInterval(this.autoRefreshProcId);
11966 delete this.autoRefreshProcId;
11970 isAutoRefreshing : function(){
11971 return this.autoRefreshProcId ? true : false;
11974 * Called to update the element to "Loading" state. Override to perform custom action.
11976 showLoading : function(){
11977 if(this.showLoadIndicator){
11978 this.el.update(this.indicatorText);
11983 * Adds unique parameter to query string if disableCaching = true
11986 prepareUrl : function(url){
11987 if(this.disableCaching){
11988 var append = "_dc=" + (new Date().getTime());
11989 if(url.indexOf("?") !== -1){
11990 url += "&" + append;
11992 url += "?" + append;
12001 processSuccess : function(response){
12002 this.transaction = null;
12003 if(response.argument.form && response.argument.reset){
12004 try{ // put in try/catch since some older FF releases had problems with this
12005 response.argument.form.reset();
12008 if(this.loadScripts){
12009 this.renderer.render(this.el, response, this,
12010 this.updateComplete.createDelegate(this, [response]));
12012 this.renderer.render(this.el, response, this);
12013 this.updateComplete(response);
12017 updateComplete : function(response){
12018 this.fireEvent("update", this.el, response);
12019 if(typeof response.argument.callback == "function"){
12020 response.argument.callback(this.el, true, response);
12027 processFailure : function(response){
12028 this.transaction = null;
12029 this.fireEvent("failure", this.el, response);
12030 if(typeof response.argument.callback == "function"){
12031 response.argument.callback(this.el, false, response);
12036 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12037 * @param {Object} renderer The object implementing the render() method
12039 setRenderer : function(renderer){
12040 this.renderer = renderer;
12043 getRenderer : function(){
12044 return this.renderer;
12048 * Set the defaultUrl used for updates
12049 * @param {String/Function} defaultUrl The url or a function to call to get the url
12051 setDefaultUrl : function(defaultUrl){
12052 this.defaultUrl = defaultUrl;
12056 * Aborts the executing transaction
12058 abort : function(){
12059 if(this.transaction){
12060 Roo.Ajax.abort(this.transaction);
12065 * Returns true if an update is in progress
12066 * @return {Boolean}
12068 isUpdating : function(){
12069 if(this.transaction){
12070 return Roo.Ajax.isLoading(this.transaction);
12077 * @class Roo.UpdateManager.defaults
12078 * @static (not really - but it helps the doc tool)
12079 * The defaults collection enables customizing the default properties of UpdateManager
12081 Roo.UpdateManager.defaults = {
12083 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12089 * True to process scripts by default (Defaults to false).
12092 loadScripts : false,
12095 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12098 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12100 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12103 disableCaching : false,
12105 * Whether to show indicatorText when loading (Defaults to true).
12108 showLoadIndicator : true,
12110 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12113 indicatorText : '<div class="loading-indicator">Loading...</div>'
12117 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12119 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12120 * @param {String/HTMLElement/Roo.Element} el The element to update
12121 * @param {String} url The url
12122 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12123 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12126 * @member Roo.UpdateManager
12128 Roo.UpdateManager.updateElement = function(el, url, params, options){
12129 var um = Roo.get(el, true).getUpdateManager();
12130 Roo.apply(um, options);
12131 um.update(url, params, options ? options.callback : null);
12133 // alias for backwards compat
12134 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12136 * @class Roo.UpdateManager.BasicRenderer
12137 * Default Content renderer. Updates the elements innerHTML with the responseText.
12139 Roo.UpdateManager.BasicRenderer = function(){};
12141 Roo.UpdateManager.BasicRenderer.prototype = {
12143 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12144 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12145 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12146 * @param {Roo.Element} el The element being rendered
12147 * @param {Object} response The YUI Connect response object
12148 * @param {UpdateManager} updateManager The calling update manager
12149 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12151 render : function(el, response, updateManager, callback){
12152 el.update(response.responseText, updateManager.loadScripts, callback);
12158 * (c)) Alan Knowles
12164 * @class Roo.DomTemplate
12165 * @extends Roo.Template
12166 * An effort at a dom based template engine..
12168 * Similar to XTemplate, except it uses dom parsing to create the template..
12170 * Supported features:
12175 {a_variable} - output encoded.
12176 {a_variable.format:("Y-m-d")} - call a method on the variable
12177 {a_variable:raw} - unencoded output
12178 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12179 {a_variable:this.method_on_template(...)} - call a method on the template object.
12184 <div roo-for="a_variable or condition.."></div>
12185 <div roo-if="a_variable or condition"></div>
12186 <div roo-exec="some javascript"></div>
12187 <div roo-name="named_template"></div>
12192 Roo.DomTemplate = function()
12194 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12201 Roo.extend(Roo.DomTemplate, Roo.Template, {
12203 * id counter for sub templates.
12207 * flag to indicate if dom parser is inside a pre,
12208 * it will strip whitespace if not.
12213 * The various sub templates
12221 * basic tag replacing syntax
12224 * // you can fake an object call by doing this
12228 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12229 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12231 iterChild : function (node, method) {
12233 var oldPre = this.inPre;
12234 if (node.tagName == 'PRE') {
12237 for( var i = 0; i < node.childNodes.length; i++) {
12238 method.call(this, node.childNodes[i]);
12240 this.inPre = oldPre;
12246 * compile the template
12248 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12251 compile: function()
12255 // covert the html into DOM...
12259 doc = document.implementation.createHTMLDocument("");
12260 doc.documentElement.innerHTML = this.html ;
12261 div = doc.documentElement;
12263 // old IE... - nasty -- it causes all sorts of issues.. with
12264 // images getting pulled from server..
12265 div = document.createElement('div');
12266 div.innerHTML = this.html;
12268 //doc.documentElement.innerHTML = htmlBody
12274 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12276 var tpls = this.tpls;
12278 // create a top level template from the snippet..
12280 //Roo.log(div.innerHTML);
12287 body : div.innerHTML,
12300 Roo.each(tpls, function(tp){
12301 this.compileTpl(tp);
12302 this.tpls[tp.id] = tp;
12305 this.master = tpls[0];
12311 compileNode : function(node, istop) {
12316 // skip anything not a tag..
12317 if (node.nodeType != 1) {
12318 if (node.nodeType == 3 && !this.inPre) {
12319 // reduce white space..
12320 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12343 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12344 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12345 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12346 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12352 // just itterate children..
12353 this.iterChild(node,this.compileNode);
12356 tpl.uid = this.id++;
12357 tpl.value = node.getAttribute('roo-' + tpl.attr);
12358 node.removeAttribute('roo-'+ tpl.attr);
12359 if (tpl.attr != 'name') {
12360 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12361 node.parentNode.replaceChild(placeholder, node);
12364 var placeholder = document.createElement('span');
12365 placeholder.className = 'roo-tpl-' + tpl.value;
12366 node.parentNode.replaceChild(placeholder, node);
12369 // parent now sees '{domtplXXXX}
12370 this.iterChild(node,this.compileNode);
12372 // we should now have node body...
12373 var div = document.createElement('div');
12374 div.appendChild(node);
12376 // this has the unfortunate side effect of converting tagged attributes
12377 // eg. href="{...}" into %7C...%7D
12378 // this has been fixed by searching for those combo's although it's a bit hacky..
12381 tpl.body = div.innerHTML;
12388 switch (tpl.value) {
12389 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12390 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12391 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12396 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12400 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12404 tpl.id = tpl.value; // replace non characters???
12410 this.tpls.push(tpl);
12420 * Compile a segment of the template into a 'sub-template'
12426 compileTpl : function(tpl)
12428 var fm = Roo.util.Format;
12429 var useF = this.disableFormats !== true;
12431 var sep = Roo.isGecko ? "+\n" : ",\n";
12433 var undef = function(str) {
12434 Roo.debug && Roo.log("Property not found :" + str);
12438 //Roo.log(tpl.body);
12442 var fn = function(m, lbrace, name, format, args)
12445 //Roo.log(arguments);
12446 args = args ? args.replace(/\\'/g,"'") : args;
12447 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12448 if (typeof(format) == 'undefined') {
12449 format = 'htmlEncode';
12451 if (format == 'raw' ) {
12455 if(name.substr(0, 6) == 'domtpl'){
12456 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12459 // build an array of options to determine if value is undefined..
12461 // basically get 'xxxx.yyyy' then do
12462 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12463 // (function () { Roo.log("Property not found"); return ''; })() :
12468 Roo.each(name.split('.'), function(st) {
12469 lookfor += (lookfor.length ? '.': '') + st;
12470 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12473 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12476 if(format && useF){
12478 args = args ? ',' + args : "";
12480 if(format.substr(0, 5) != "this."){
12481 format = "fm." + format + '(';
12483 format = 'this.call("'+ format.substr(5) + '", ';
12487 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12490 if (args && args.length) {
12491 // called with xxyx.yuu:(test,test)
12493 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12495 // raw.. - :raw modifier..
12496 return "'"+ sep + udef_st + name + ")"+sep+"'";
12500 // branched to use + in gecko and [].join() in others
12502 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12503 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12506 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12507 body.push(tpl.body.replace(/(\r\n|\n)/g,
12508 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12509 body.push("'].join('');};};");
12510 body = body.join('');
12513 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12515 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12522 * same as applyTemplate, except it's done to one of the subTemplates
12523 * when using named templates, you can do:
12525 * var str = pl.applySubTemplate('your-name', values);
12528 * @param {Number} id of the template
12529 * @param {Object} values to apply to template
12530 * @param {Object} parent (normaly the instance of this object)
12532 applySubTemplate : function(id, values, parent)
12536 var t = this.tpls[id];
12540 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12541 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12545 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12552 if(t.execCall && t.execCall.call(this, values, parent)){
12556 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12562 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12563 parent = t.target ? values : parent;
12564 if(t.forCall && vs instanceof Array){
12566 for(var i = 0, len = vs.length; i < len; i++){
12568 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12570 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12572 //Roo.log(t.compiled);
12576 return buf.join('');
12579 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12584 return t.compiled.call(this, vs, parent);
12586 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12588 //Roo.log(t.compiled);
12596 applyTemplate : function(values){
12597 return this.master.compiled.call(this, values, {});
12598 //var s = this.subs;
12601 apply : function(){
12602 return this.applyTemplate.apply(this, arguments);
12607 Roo.DomTemplate.from = function(el){
12608 el = Roo.getDom(el);
12609 return new Roo.Domtemplate(el.value || el.innerHTML);
12612 * Ext JS Library 1.1.1
12613 * Copyright(c) 2006-2007, Ext JS, LLC.
12615 * Originally Released Under LGPL - original licence link has changed is not relivant.
12618 * <script type="text/javascript">
12622 * @class Roo.util.DelayedTask
12623 * Provides a convenient method of performing setTimeout where a new
12624 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12625 * You can use this class to buffer
12626 * the keypress events for a certain number of milliseconds, and perform only if they stop
12627 * for that amount of time.
12628 * @constructor The parameters to this constructor serve as defaults and are not required.
12629 * @param {Function} fn (optional) The default function to timeout
12630 * @param {Object} scope (optional) The default scope of that timeout
12631 * @param {Array} args (optional) The default Array of arguments
12633 Roo.util.DelayedTask = function(fn, scope, args){
12634 var id = null, d, t;
12636 var call = function(){
12637 var now = new Date().getTime();
12641 fn.apply(scope, args || []);
12645 * Cancels any pending timeout and queues a new one
12646 * @param {Number} delay The milliseconds to delay
12647 * @param {Function} newFn (optional) Overrides function passed to constructor
12648 * @param {Object} newScope (optional) Overrides scope passed to constructor
12649 * @param {Array} newArgs (optional) Overrides args passed to constructor
12651 this.delay = function(delay, newFn, newScope, newArgs){
12652 if(id && delay != d){
12656 t = new Date().getTime();
12658 scope = newScope || scope;
12659 args = newArgs || args;
12661 id = setInterval(call, d);
12666 * Cancel the last queued timeout
12668 this.cancel = function(){
12676 * Ext JS Library 1.1.1
12677 * Copyright(c) 2006-2007, Ext JS, LLC.
12679 * Originally Released Under LGPL - original licence link has changed is not relivant.
12682 * <script type="text/javascript">
12686 Roo.util.TaskRunner = function(interval){
12687 interval = interval || 10;
12688 var tasks = [], removeQueue = [];
12690 var running = false;
12692 var stopThread = function(){
12698 var startThread = function(){
12701 id = setInterval(runTasks, interval);
12705 var removeTask = function(task){
12706 removeQueue.push(task);
12712 var runTasks = function(){
12713 if(removeQueue.length > 0){
12714 for(var i = 0, len = removeQueue.length; i < len; i++){
12715 tasks.remove(removeQueue[i]);
12718 if(tasks.length < 1){
12723 var now = new Date().getTime();
12724 for(var i = 0, len = tasks.length; i < len; ++i){
12726 var itime = now - t.taskRunTime;
12727 if(t.interval <= itime){
12728 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12729 t.taskRunTime = now;
12730 if(rt === false || t.taskRunCount === t.repeat){
12735 if(t.duration && t.duration <= (now - t.taskStartTime)){
12742 * Queues a new task.
12743 * @param {Object} task
12745 this.start = function(task){
12747 task.taskStartTime = new Date().getTime();
12748 task.taskRunTime = 0;
12749 task.taskRunCount = 0;
12754 this.stop = function(task){
12759 this.stopAll = function(){
12761 for(var i = 0, len = tasks.length; i < len; i++){
12762 if(tasks[i].onStop){
12771 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12773 * Ext JS Library 1.1.1
12774 * Copyright(c) 2006-2007, Ext JS, LLC.
12776 * Originally Released Under LGPL - original licence link has changed is not relivant.
12779 * <script type="text/javascript">
12784 * @class Roo.util.MixedCollection
12785 * @extends Roo.util.Observable
12786 * A Collection class that maintains both numeric indexes and keys and exposes events.
12788 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12789 * collection (defaults to false)
12790 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12791 * and return the key value for that item. This is used when available to look up the key on items that
12792 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12793 * equivalent to providing an implementation for the {@link #getKey} method.
12795 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12803 * Fires when the collection is cleared.
12808 * Fires when an item is added to the collection.
12809 * @param {Number} index The index at which the item was added.
12810 * @param {Object} o The item added.
12811 * @param {String} key The key associated with the added item.
12816 * Fires when an item is replaced in the collection.
12817 * @param {String} key he key associated with the new added.
12818 * @param {Object} old The item being replaced.
12819 * @param {Object} new The new item.
12824 * Fires when an item is removed from the collection.
12825 * @param {Object} o The item being removed.
12826 * @param {String} key (optional) The key associated with the removed item.
12831 this.allowFunctions = allowFunctions === true;
12833 this.getKey = keyFn;
12835 Roo.util.MixedCollection.superclass.constructor.call(this);
12838 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12839 allowFunctions : false,
12842 * Adds an item to the collection.
12843 * @param {String} key The key to associate with the item
12844 * @param {Object} o The item to add.
12845 * @return {Object} The item added.
12847 add : function(key, o){
12848 if(arguments.length == 1){
12850 key = this.getKey(o);
12852 if(typeof key == "undefined" || key === null){
12854 this.items.push(o);
12855 this.keys.push(null);
12857 var old = this.map[key];
12859 return this.replace(key, o);
12862 this.items.push(o);
12864 this.keys.push(key);
12866 this.fireEvent("add", this.length-1, o, key);
12871 * MixedCollection has a generic way to fetch keys if you implement getKey.
12874 var mc = new Roo.util.MixedCollection();
12875 mc.add(someEl.dom.id, someEl);
12876 mc.add(otherEl.dom.id, otherEl);
12880 var mc = new Roo.util.MixedCollection();
12881 mc.getKey = function(el){
12887 // or via the constructor
12888 var mc = new Roo.util.MixedCollection(false, function(el){
12894 * @param o {Object} The item for which to find the key.
12895 * @return {Object} The key for the passed item.
12897 getKey : function(o){
12902 * Replaces an item in the collection.
12903 * @param {String} key The key associated with the item to replace, or the item to replace.
12904 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12905 * @return {Object} The new item.
12907 replace : function(key, o){
12908 if(arguments.length == 1){
12910 key = this.getKey(o);
12912 var old = this.item(key);
12913 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12914 return this.add(key, o);
12916 var index = this.indexOfKey(key);
12917 this.items[index] = o;
12919 this.fireEvent("replace", key, old, o);
12924 * Adds all elements of an Array or an Object to the collection.
12925 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12926 * an Array of values, each of which are added to the collection.
12928 addAll : function(objs){
12929 if(arguments.length > 1 || objs instanceof Array){
12930 var args = arguments.length > 1 ? arguments : objs;
12931 for(var i = 0, len = args.length; i < len; i++){
12935 for(var key in objs){
12936 if(this.allowFunctions || typeof objs[key] != "function"){
12937 this.add(key, objs[key]);
12944 * Executes the specified function once for every item in the collection, passing each
12945 * item as the first and only parameter. returning false from the function will stop the iteration.
12946 * @param {Function} fn The function to execute for each item.
12947 * @param {Object} scope (optional) The scope in which to execute the function.
12949 each : function(fn, scope){
12950 var items = [].concat(this.items); // each safe for removal
12951 for(var i = 0, len = items.length; i < len; i++){
12952 if(fn.call(scope || items[i], items[i], i, len) === false){
12959 * Executes the specified function once for every key in the collection, passing each
12960 * key, and its associated item as the first two parameters.
12961 * @param {Function} fn The function to execute for each item.
12962 * @param {Object} scope (optional) The scope in which to execute the function.
12964 eachKey : function(fn, scope){
12965 for(var i = 0, len = this.keys.length; i < len; i++){
12966 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12971 * Returns the first item in the collection which elicits a true return value from the
12972 * passed selection function.
12973 * @param {Function} fn The selection function to execute for each item.
12974 * @param {Object} scope (optional) The scope in which to execute the function.
12975 * @return {Object} The first item in the collection which returned true from the selection function.
12977 find : function(fn, scope){
12978 for(var i = 0, len = this.items.length; i < len; i++){
12979 if(fn.call(scope || window, this.items[i], this.keys[i])){
12980 return this.items[i];
12987 * Inserts an item at the specified index in the collection.
12988 * @param {Number} index The index to insert the item at.
12989 * @param {String} key The key to associate with the new item, or the item itself.
12990 * @param {Object} o (optional) If the second parameter was a key, the new item.
12991 * @return {Object} The item inserted.
12993 insert : function(index, key, o){
12994 if(arguments.length == 2){
12996 key = this.getKey(o);
12998 if(index >= this.length){
12999 return this.add(key, o);
13002 this.items.splice(index, 0, o);
13003 if(typeof key != "undefined" && key != null){
13006 this.keys.splice(index, 0, key);
13007 this.fireEvent("add", index, o, key);
13012 * Removed an item from the collection.
13013 * @param {Object} o The item to remove.
13014 * @return {Object} The item removed.
13016 remove : function(o){
13017 return this.removeAt(this.indexOf(o));
13021 * Remove an item from a specified index in the collection.
13022 * @param {Number} index The index within the collection of the item to remove.
13024 removeAt : function(index){
13025 if(index < this.length && index >= 0){
13027 var o = this.items[index];
13028 this.items.splice(index, 1);
13029 var key = this.keys[index];
13030 if(typeof key != "undefined"){
13031 delete this.map[key];
13033 this.keys.splice(index, 1);
13034 this.fireEvent("remove", o, key);
13039 * Removed an item associated with the passed key fom the collection.
13040 * @param {String} key The key of the item to remove.
13042 removeKey : function(key){
13043 return this.removeAt(this.indexOfKey(key));
13047 * Returns the number of items in the collection.
13048 * @return {Number} the number of items in the collection.
13050 getCount : function(){
13051 return this.length;
13055 * Returns index within the collection of the passed Object.
13056 * @param {Object} o The item to find the index of.
13057 * @return {Number} index of the item.
13059 indexOf : function(o){
13060 if(!this.items.indexOf){
13061 for(var i = 0, len = this.items.length; i < len; i++){
13062 if(this.items[i] == o) return i;
13066 return this.items.indexOf(o);
13071 * Returns index within the collection of the passed key.
13072 * @param {String} key The key to find the index of.
13073 * @return {Number} index of the key.
13075 indexOfKey : function(key){
13076 if(!this.keys.indexOf){
13077 for(var i = 0, len = this.keys.length; i < len; i++){
13078 if(this.keys[i] == key) return i;
13082 return this.keys.indexOf(key);
13087 * Returns the item associated with the passed key OR index. Key has priority over index.
13088 * @param {String/Number} key The key or index of the item.
13089 * @return {Object} The item associated with the passed key.
13091 item : function(key){
13092 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13093 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13097 * Returns the item at the specified index.
13098 * @param {Number} index The index of the item.
13101 itemAt : function(index){
13102 return this.items[index];
13106 * Returns the item associated with the passed key.
13107 * @param {String/Number} key The key of the item.
13108 * @return {Object} The item associated with the passed key.
13110 key : function(key){
13111 return this.map[key];
13115 * Returns true if the collection contains the passed Object as an item.
13116 * @param {Object} o The Object to look for in the collection.
13117 * @return {Boolean} True if the collection contains the Object as an item.
13119 contains : function(o){
13120 return this.indexOf(o) != -1;
13124 * Returns true if the collection contains the passed Object as a key.
13125 * @param {String} key The key to look for in the collection.
13126 * @return {Boolean} True if the collection contains the Object as a key.
13128 containsKey : function(key){
13129 return typeof this.map[key] != "undefined";
13133 * Removes all items from the collection.
13135 clear : function(){
13140 this.fireEvent("clear");
13144 * Returns the first item in the collection.
13145 * @return {Object} the first item in the collection..
13147 first : function(){
13148 return this.items[0];
13152 * Returns the last item in the collection.
13153 * @return {Object} the last item in the collection..
13156 return this.items[this.length-1];
13159 _sort : function(property, dir, fn){
13160 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13161 fn = fn || function(a, b){
13164 var c = [], k = this.keys, items = this.items;
13165 for(var i = 0, len = items.length; i < len; i++){
13166 c[c.length] = {key: k[i], value: items[i], index: i};
13168 c.sort(function(a, b){
13169 var v = fn(a[property], b[property]) * dsc;
13171 v = (a.index < b.index ? -1 : 1);
13175 for(var i = 0, len = c.length; i < len; i++){
13176 items[i] = c[i].value;
13179 this.fireEvent("sort", this);
13183 * Sorts this collection with the passed comparison function
13184 * @param {String} direction (optional) "ASC" or "DESC"
13185 * @param {Function} fn (optional) comparison function
13187 sort : function(dir, fn){
13188 this._sort("value", dir, fn);
13192 * Sorts this collection by keys
13193 * @param {String} direction (optional) "ASC" or "DESC"
13194 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13196 keySort : function(dir, fn){
13197 this._sort("key", dir, fn || function(a, b){
13198 return String(a).toUpperCase()-String(b).toUpperCase();
13203 * Returns a range of items in this collection
13204 * @param {Number} startIndex (optional) defaults to 0
13205 * @param {Number} endIndex (optional) default to the last item
13206 * @return {Array} An array of items
13208 getRange : function(start, end){
13209 var items = this.items;
13210 if(items.length < 1){
13213 start = start || 0;
13214 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13217 for(var i = start; i <= end; i++) {
13218 r[r.length] = items[i];
13221 for(var i = start; i >= end; i--) {
13222 r[r.length] = items[i];
13229 * Filter the <i>objects</i> in this collection by a specific property.
13230 * Returns a new collection that has been filtered.
13231 * @param {String} property A property on your objects
13232 * @param {String/RegExp} value Either string that the property values
13233 * should start with or a RegExp to test against the property
13234 * @return {MixedCollection} The new filtered collection
13236 filter : function(property, value){
13237 if(!value.exec){ // not a regex
13238 value = String(value);
13239 if(value.length == 0){
13240 return this.clone();
13242 value = new RegExp("^" + Roo.escapeRe(value), "i");
13244 return this.filterBy(function(o){
13245 return o && value.test(o[property]);
13250 * Filter by a function. * Returns a new collection that has been filtered.
13251 * The passed function will be called with each
13252 * object in the collection. If the function returns true, the value is included
13253 * otherwise it is filtered.
13254 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13255 * @param {Object} scope (optional) The scope of the function (defaults to this)
13256 * @return {MixedCollection} The new filtered collection
13258 filterBy : function(fn, scope){
13259 var r = new Roo.util.MixedCollection();
13260 r.getKey = this.getKey;
13261 var k = this.keys, it = this.items;
13262 for(var i = 0, len = it.length; i < len; i++){
13263 if(fn.call(scope||this, it[i], k[i])){
13264 r.add(k[i], it[i]);
13271 * Creates a duplicate of this collection
13272 * @return {MixedCollection}
13274 clone : function(){
13275 var r = new Roo.util.MixedCollection();
13276 var k = this.keys, it = this.items;
13277 for(var i = 0, len = it.length; i < len; i++){
13278 r.add(k[i], it[i]);
13280 r.getKey = this.getKey;
13285 * Returns the item associated with the passed key or index.
13287 * @param {String/Number} key The key or index of the item.
13288 * @return {Object} The item associated with the passed key.
13290 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13292 * Ext JS Library 1.1.1
13293 * Copyright(c) 2006-2007, Ext JS, LLC.
13295 * Originally Released Under LGPL - original licence link has changed is not relivant.
13298 * <script type="text/javascript">
13301 * @class Roo.util.JSON
13302 * Modified version of Douglas Crockford"s json.js that doesn"t
13303 * mess with the Object prototype
13304 * http://www.json.org/js.html
13307 Roo.util.JSON = new (function(){
13308 var useHasOwn = {}.hasOwnProperty ? true : false;
13310 // crashes Safari in some instances
13311 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13313 var pad = function(n) {
13314 return n < 10 ? "0" + n : n;
13327 var encodeString = function(s){
13328 if (/["\\\x00-\x1f]/.test(s)) {
13329 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13334 c = b.charCodeAt();
13336 Math.floor(c / 16).toString(16) +
13337 (c % 16).toString(16);
13340 return '"' + s + '"';
13343 var encodeArray = function(o){
13344 var a = ["["], b, i, l = o.length, v;
13345 for (i = 0; i < l; i += 1) {
13347 switch (typeof v) {
13356 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13364 var encodeDate = function(o){
13365 return '"' + o.getFullYear() + "-" +
13366 pad(o.getMonth() + 1) + "-" +
13367 pad(o.getDate()) + "T" +
13368 pad(o.getHours()) + ":" +
13369 pad(o.getMinutes()) + ":" +
13370 pad(o.getSeconds()) + '"';
13374 * Encodes an Object, Array or other value
13375 * @param {Mixed} o The variable to encode
13376 * @return {String} The JSON string
13378 this.encode = function(o)
13380 // should this be extended to fully wrap stringify..
13382 if(typeof o == "undefined" || o === null){
13384 }else if(o instanceof Array){
13385 return encodeArray(o);
13386 }else if(o instanceof Date){
13387 return encodeDate(o);
13388 }else if(typeof o == "string"){
13389 return encodeString(o);
13390 }else if(typeof o == "number"){
13391 return isFinite(o) ? String(o) : "null";
13392 }else if(typeof o == "boolean"){
13395 var a = ["{"], b, i, v;
13397 if(!useHasOwn || o.hasOwnProperty(i)) {
13399 switch (typeof v) {
13408 a.push(this.encode(i), ":",
13409 v === null ? "null" : this.encode(v));
13420 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13421 * @param {String} json The JSON string
13422 * @return {Object} The resulting object
13424 this.decode = function(json){
13426 return /** eval:var:json */ eval("(" + json + ')');
13430 * Shorthand for {@link Roo.util.JSON#encode}
13431 * @member Roo encode
13433 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13435 * Shorthand for {@link Roo.util.JSON#decode}
13436 * @member Roo decode
13438 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13441 * Ext JS Library 1.1.1
13442 * Copyright(c) 2006-2007, Ext JS, LLC.
13444 * Originally Released Under LGPL - original licence link has changed is not relivant.
13447 * <script type="text/javascript">
13451 * @class Roo.util.Format
13452 * Reusable data formatting functions
13455 Roo.util.Format = function(){
13456 var trimRe = /^\s+|\s+$/g;
13459 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13460 * @param {String} value The string to truncate
13461 * @param {Number} length The maximum length to allow before truncating
13462 * @return {String} The converted text
13464 ellipsis : function(value, len){
13465 if(value && value.length > len){
13466 return value.substr(0, len-3)+"...";
13472 * Checks a reference and converts it to empty string if it is undefined
13473 * @param {Mixed} value Reference to check
13474 * @return {Mixed} Empty string if converted, otherwise the original value
13476 undef : function(value){
13477 return typeof value != "undefined" ? value : "";
13481 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13482 * @param {String} value The string to encode
13483 * @return {String} The encoded text
13485 htmlEncode : function(value){
13486 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13490 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13491 * @param {String} value The string to decode
13492 * @return {String} The decoded text
13494 htmlDecode : function(value){
13495 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13499 * Trims any whitespace from either side of a string
13500 * @param {String} value The text to trim
13501 * @return {String} The trimmed text
13503 trim : function(value){
13504 return String(value).replace(trimRe, "");
13508 * Returns a substring from within an original string
13509 * @param {String} value The original text
13510 * @param {Number} start The start index of the substring
13511 * @param {Number} length The length of the substring
13512 * @return {String} The substring
13514 substr : function(value, start, length){
13515 return String(value).substr(start, length);
13519 * Converts a string to all lower case letters
13520 * @param {String} value The text to convert
13521 * @return {String} The converted text
13523 lowercase : function(value){
13524 return String(value).toLowerCase();
13528 * Converts a string to all upper case letters
13529 * @param {String} value The text to convert
13530 * @return {String} The converted text
13532 uppercase : function(value){
13533 return String(value).toUpperCase();
13537 * Converts the first character only of a string to upper case
13538 * @param {String} value The text to convert
13539 * @return {String} The converted text
13541 capitalize : function(value){
13542 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13546 call : function(value, fn){
13547 if(arguments.length > 2){
13548 var args = Array.prototype.slice.call(arguments, 2);
13549 args.unshift(value);
13551 return /** eval:var:value */ eval(fn).apply(window, args);
13553 /** eval:var:value */
13554 return /** eval:var:value */ eval(fn).call(window, value);
13560 * safer version of Math.toFixed..??/
13561 * @param {Number/String} value The numeric value to format
13562 * @param {Number/String} value Decimal places
13563 * @return {String} The formatted currency string
13565 toFixed : function(v, n)
13567 // why not use to fixed - precision is buggered???
13569 return Math.round(v-0);
13571 var fact = Math.pow(10,n+1);
13572 v = (Math.round((v-0)*fact))/fact;
13573 var z = (''+fact).substring(2);
13574 if (v == Math.floor(v)) {
13575 return Math.floor(v) + '.' + z;
13578 // now just padd decimals..
13579 var ps = String(v).split('.');
13580 var fd = (ps[1] + z);
13581 var r = fd.substring(0,n);
13582 var rm = fd.substring(n);
13584 return ps[0] + '.' + r;
13586 r*=1; // turn it into a number;
13588 if (String(r).length != n) {
13591 r = String(r).substring(1); // chop the end off.
13594 return ps[0] + '.' + r;
13599 * Format a number as US currency
13600 * @param {Number/String} value The numeric value to format
13601 * @return {String} The formatted currency string
13603 usMoney : function(v){
13604 return '$' + Roo.util.Format.number(v);
13609 * eventually this should probably emulate php's number_format
13610 * @param {Number/String} value The numeric value to format
13611 * @param {Number} decimals number of decimal places
13612 * @return {String} The formatted currency string
13614 number : function(v,decimals)
13616 // multiply and round.
13617 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13618 var mul = Math.pow(10, decimals);
13619 var zero = String(mul).substring(1);
13620 v = (Math.round((v-0)*mul))/mul;
13622 // if it's '0' number.. then
13624 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13626 var ps = v.split('.');
13630 var r = /(\d+)(\d{3})/;
13632 while (r.test(whole)) {
13633 whole = whole.replace(r, '$1' + ',' + '$2');
13639 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13640 // does not have decimals
13641 (decimals ? ('.' + zero) : '');
13644 return whole + sub ;
13648 * Parse a value into a formatted date using the specified format pattern.
13649 * @param {Mixed} value The value to format
13650 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13651 * @return {String} The formatted date string
13653 date : function(v, format){
13657 if(!(v instanceof Date)){
13658 v = new Date(Date.parse(v));
13660 return v.dateFormat(format || Roo.util.Format.defaults.date);
13664 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13665 * @param {String} format Any valid date format string
13666 * @return {Function} The date formatting function
13668 dateRenderer : function(format){
13669 return function(v){
13670 return Roo.util.Format.date(v, format);
13675 stripTagsRE : /<\/?[^>]+>/gi,
13678 * Strips all HTML tags
13679 * @param {Mixed} value The text from which to strip tags
13680 * @return {String} The stripped text
13682 stripTags : function(v){
13683 return !v ? v : String(v).replace(this.stripTagsRE, "");
13687 Roo.util.Format.defaults = {
13691 * Ext JS Library 1.1.1
13692 * Copyright(c) 2006-2007, Ext JS, LLC.
13694 * Originally Released Under LGPL - original licence link has changed is not relivant.
13697 * <script type="text/javascript">
13704 * @class Roo.MasterTemplate
13705 * @extends Roo.Template
13706 * Provides a template that can have child templates. The syntax is:
13708 var t = new Roo.MasterTemplate(
13709 '<select name="{name}">',
13710 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13713 t.add('options', {value: 'foo', text: 'bar'});
13714 // or you can add multiple child elements in one shot
13715 t.addAll('options', [
13716 {value: 'foo', text: 'bar'},
13717 {value: 'foo2', text: 'bar2'},
13718 {value: 'foo3', text: 'bar3'}
13720 // then append, applying the master template values
13721 t.append('my-form', {name: 'my-select'});
13723 * A name attribute for the child template is not required if you have only one child
13724 * template or you want to refer to them by index.
13726 Roo.MasterTemplate = function(){
13727 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13728 this.originalHtml = this.html;
13730 var m, re = this.subTemplateRe;
13733 while(m = re.exec(this.html)){
13734 var name = m[1], content = m[2];
13739 tpl : new Roo.Template(content)
13742 st[name] = st[subIndex];
13744 st[subIndex].tpl.compile();
13745 st[subIndex].tpl.call = this.call.createDelegate(this);
13748 this.subCount = subIndex;
13751 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13753 * The regular expression used to match sub templates
13757 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13760 * Applies the passed values to a child template.
13761 * @param {String/Number} name (optional) The name or index of the child template
13762 * @param {Array/Object} values The values to be applied to the template
13763 * @return {MasterTemplate} this
13765 add : function(name, values){
13766 if(arguments.length == 1){
13767 values = arguments[0];
13770 var s = this.subs[name];
13771 s.buffer[s.buffer.length] = s.tpl.apply(values);
13776 * Applies all the passed values to a child template.
13777 * @param {String/Number} name (optional) The name or index of the child template
13778 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13779 * @param {Boolean} reset (optional) True to reset the template first
13780 * @return {MasterTemplate} this
13782 fill : function(name, values, reset){
13784 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13792 for(var i = 0, len = values.length; i < len; i++){
13793 this.add(name, values[i]);
13799 * Resets the template for reuse
13800 * @return {MasterTemplate} this
13802 reset : function(){
13804 for(var i = 0; i < this.subCount; i++){
13810 applyTemplate : function(values){
13812 var replaceIndex = -1;
13813 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13814 return s[++replaceIndex].buffer.join("");
13816 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13819 apply : function(){
13820 return this.applyTemplate.apply(this, arguments);
13823 compile : function(){return this;}
13827 * Alias for fill().
13830 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13832 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13833 * var tpl = Roo.MasterTemplate.from('element-id');
13834 * @param {String/HTMLElement} el
13835 * @param {Object} config
13838 Roo.MasterTemplate.from = function(el, config){
13839 el = Roo.getDom(el);
13840 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13843 * Ext JS Library 1.1.1
13844 * Copyright(c) 2006-2007, Ext JS, LLC.
13846 * Originally Released Under LGPL - original licence link has changed is not relivant.
13849 * <script type="text/javascript">
13854 * @class Roo.util.CSS
13855 * Utility class for manipulating CSS rules
13858 Roo.util.CSS = function(){
13860 var doc = document;
13862 var camelRe = /(-[a-z])/gi;
13863 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13867 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13868 * tag and appended to the HEAD of the document.
13869 * @param {String|Object} cssText The text containing the css rules
13870 * @param {String} id An id to add to the stylesheet for later removal
13871 * @return {StyleSheet}
13873 createStyleSheet : function(cssText, id){
13875 var head = doc.getElementsByTagName("head")[0];
13876 var nrules = doc.createElement("style");
13877 nrules.setAttribute("type", "text/css");
13879 nrules.setAttribute("id", id);
13881 if (typeof(cssText) != 'string') {
13882 // support object maps..
13883 // not sure if this a good idea..
13884 // perhaps it should be merged with the general css handling
13885 // and handle js style props.
13886 var cssTextNew = [];
13887 for(var n in cssText) {
13889 for(var k in cssText[n]) {
13890 citems.push( k + ' : ' +cssText[n][k] + ';' );
13892 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13895 cssText = cssTextNew.join("\n");
13901 head.appendChild(nrules);
13902 ss = nrules.styleSheet;
13903 ss.cssText = cssText;
13906 nrules.appendChild(doc.createTextNode(cssText));
13908 nrules.cssText = cssText;
13910 head.appendChild(nrules);
13911 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13913 this.cacheStyleSheet(ss);
13918 * Removes a style or link tag by id
13919 * @param {String} id The id of the tag
13921 removeStyleSheet : function(id){
13922 var existing = doc.getElementById(id);
13924 existing.parentNode.removeChild(existing);
13929 * Dynamically swaps an existing stylesheet reference for a new one
13930 * @param {String} id The id of an existing link tag to remove
13931 * @param {String} url The href of the new stylesheet to include
13933 swapStyleSheet : function(id, url){
13934 this.removeStyleSheet(id);
13935 var ss = doc.createElement("link");
13936 ss.setAttribute("rel", "stylesheet");
13937 ss.setAttribute("type", "text/css");
13938 ss.setAttribute("id", id);
13939 ss.setAttribute("href", url);
13940 doc.getElementsByTagName("head")[0].appendChild(ss);
13944 * Refresh the rule cache if you have dynamically added stylesheets
13945 * @return {Object} An object (hash) of rules indexed by selector
13947 refreshCache : function(){
13948 return this.getRules(true);
13952 cacheStyleSheet : function(stylesheet){
13956 try{// try catch for cross domain access issue
13957 var ssRules = stylesheet.cssRules || stylesheet.rules;
13958 for(var j = ssRules.length-1; j >= 0; --j){
13959 rules[ssRules[j].selectorText] = ssRules[j];
13965 * Gets all css rules for the document
13966 * @param {Boolean} refreshCache true to refresh the internal cache
13967 * @return {Object} An object (hash) of rules indexed by selector
13969 getRules : function(refreshCache){
13970 if(rules == null || refreshCache){
13972 var ds = doc.styleSheets;
13973 for(var i =0, len = ds.length; i < len; i++){
13975 this.cacheStyleSheet(ds[i]);
13983 * Gets an an individual CSS rule by selector(s)
13984 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13985 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13986 * @return {CSSRule} The CSS rule or null if one is not found
13988 getRule : function(selector, refreshCache){
13989 var rs = this.getRules(refreshCache);
13990 if(!(selector instanceof Array)){
13991 return rs[selector];
13993 for(var i = 0; i < selector.length; i++){
13994 if(rs[selector[i]]){
13995 return rs[selector[i]];
14003 * Updates a rule property
14004 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14005 * @param {String} property The css property
14006 * @param {String} value The new value for the property
14007 * @return {Boolean} true If a rule was found and updated
14009 updateRule : function(selector, property, value){
14010 if(!(selector instanceof Array)){
14011 var rule = this.getRule(selector);
14013 rule.style[property.replace(camelRe, camelFn)] = value;
14017 for(var i = 0; i < selector.length; i++){
14018 if(this.updateRule(selector[i], property, value)){
14028 * Ext JS Library 1.1.1
14029 * Copyright(c) 2006-2007, Ext JS, LLC.
14031 * Originally Released Under LGPL - original licence link has changed is not relivant.
14034 * <script type="text/javascript">
14040 * @class Roo.util.ClickRepeater
14041 * @extends Roo.util.Observable
14043 * A wrapper class which can be applied to any element. Fires a "click" event while the
14044 * mouse is pressed. The interval between firings may be specified in the config but
14045 * defaults to 10 milliseconds.
14047 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14049 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14050 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14051 * Similar to an autorepeat key delay.
14052 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14053 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14054 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14055 * "interval" and "delay" are ignored. "immediate" is honored.
14056 * @cfg {Boolean} preventDefault True to prevent the default click event
14057 * @cfg {Boolean} stopDefault True to stop the default click event
14060 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14061 * 2007-02-02 jvs Renamed to ClickRepeater
14062 * 2007-02-03 jvs Modifications for FF Mac and Safari
14065 * @param {String/HTMLElement/Element} el The element to listen on
14066 * @param {Object} config
14068 Roo.util.ClickRepeater = function(el, config)
14070 this.el = Roo.get(el);
14071 this.el.unselectable();
14073 Roo.apply(this, config);
14078 * Fires when the mouse button is depressed.
14079 * @param {Roo.util.ClickRepeater} this
14081 "mousedown" : true,
14084 * Fires on a specified interval during the time the element is pressed.
14085 * @param {Roo.util.ClickRepeater} this
14090 * Fires when the mouse key is released.
14091 * @param {Roo.util.ClickRepeater} this
14096 this.el.on("mousedown", this.handleMouseDown, this);
14097 if(this.preventDefault || this.stopDefault){
14098 this.el.on("click", function(e){
14099 if(this.preventDefault){
14100 e.preventDefault();
14102 if(this.stopDefault){
14108 // allow inline handler
14110 this.on("click", this.handler, this.scope || this);
14113 Roo.util.ClickRepeater.superclass.constructor.call(this);
14116 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14119 preventDefault : true,
14120 stopDefault : false,
14124 handleMouseDown : function(){
14125 clearTimeout(this.timer);
14127 if(this.pressClass){
14128 this.el.addClass(this.pressClass);
14130 this.mousedownTime = new Date();
14132 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14133 this.el.on("mouseout", this.handleMouseOut, this);
14135 this.fireEvent("mousedown", this);
14136 this.fireEvent("click", this);
14138 this.timer = this.click.defer(this.delay || this.interval, this);
14142 click : function(){
14143 this.fireEvent("click", this);
14144 this.timer = this.click.defer(this.getInterval(), this);
14148 getInterval: function(){
14149 if(!this.accelerate){
14150 return this.interval;
14152 var pressTime = this.mousedownTime.getElapsed();
14153 if(pressTime < 500){
14155 }else if(pressTime < 1700){
14157 }else if(pressTime < 2600){
14159 }else if(pressTime < 3500){
14161 }else if(pressTime < 4400){
14163 }else if(pressTime < 5300){
14165 }else if(pressTime < 6200){
14173 handleMouseOut : function(){
14174 clearTimeout(this.timer);
14175 if(this.pressClass){
14176 this.el.removeClass(this.pressClass);
14178 this.el.on("mouseover", this.handleMouseReturn, this);
14182 handleMouseReturn : function(){
14183 this.el.un("mouseover", this.handleMouseReturn);
14184 if(this.pressClass){
14185 this.el.addClass(this.pressClass);
14191 handleMouseUp : function(){
14192 clearTimeout(this.timer);
14193 this.el.un("mouseover", this.handleMouseReturn);
14194 this.el.un("mouseout", this.handleMouseOut);
14195 Roo.get(document).un("mouseup", this.handleMouseUp);
14196 this.el.removeClass(this.pressClass);
14197 this.fireEvent("mouseup", this);
14201 * Ext JS Library 1.1.1
14202 * Copyright(c) 2006-2007, Ext JS, LLC.
14204 * Originally Released Under LGPL - original licence link has changed is not relivant.
14207 * <script type="text/javascript">
14212 * @class Roo.KeyNav
14213 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14214 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14215 * way to implement custom navigation schemes for any UI component.</p>
14216 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14217 * pageUp, pageDown, del, home, end. Usage:</p>
14219 var nav = new Roo.KeyNav("my-element", {
14220 "left" : function(e){
14221 this.moveLeft(e.ctrlKey);
14223 "right" : function(e){
14224 this.moveRight(e.ctrlKey);
14226 "enter" : function(e){
14233 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14234 * @param {Object} config The config
14236 Roo.KeyNav = function(el, config){
14237 this.el = Roo.get(el);
14238 Roo.apply(this, config);
14239 if(!this.disabled){
14240 this.disabled = true;
14245 Roo.KeyNav.prototype = {
14247 * @cfg {Boolean} disabled
14248 * True to disable this KeyNav instance (defaults to false)
14252 * @cfg {String} defaultEventAction
14253 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14254 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14255 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14257 defaultEventAction: "stopEvent",
14259 * @cfg {Boolean} forceKeyDown
14260 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14261 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14262 * handle keydown instead of keypress.
14264 forceKeyDown : false,
14267 prepareEvent : function(e){
14268 var k = e.getKey();
14269 var h = this.keyToHandler[k];
14270 //if(h && this[h]){
14271 // e.stopPropagation();
14273 if(Roo.isSafari && h && k >= 37 && k <= 40){
14279 relay : function(e){
14280 var k = e.getKey();
14281 var h = this.keyToHandler[k];
14283 if(this.doRelay(e, this[h], h) !== true){
14284 e[this.defaultEventAction]();
14290 doRelay : function(e, h, hname){
14291 return h.call(this.scope || this, e);
14294 // possible handlers
14308 // quick lookup hash
14325 * Enable this KeyNav
14327 enable: function(){
14329 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14330 // the EventObject will normalize Safari automatically
14331 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14332 this.el.on("keydown", this.relay, this);
14334 this.el.on("keydown", this.prepareEvent, this);
14335 this.el.on("keypress", this.relay, this);
14337 this.disabled = false;
14342 * Disable this KeyNav
14344 disable: function(){
14345 if(!this.disabled){
14346 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14347 this.el.un("keydown", this.relay);
14349 this.el.un("keydown", this.prepareEvent);
14350 this.el.un("keypress", this.relay);
14352 this.disabled = true;
14357 * Ext JS Library 1.1.1
14358 * Copyright(c) 2006-2007, Ext JS, LLC.
14360 * Originally Released Under LGPL - original licence link has changed is not relivant.
14363 * <script type="text/javascript">
14368 * @class Roo.KeyMap
14369 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14370 * The constructor accepts the same config object as defined by {@link #addBinding}.
14371 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14372 * combination it will call the function with this signature (if the match is a multi-key
14373 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14374 * A KeyMap can also handle a string representation of keys.<br />
14377 // map one key by key code
14378 var map = new Roo.KeyMap("my-element", {
14379 key: 13, // or Roo.EventObject.ENTER
14384 // map multiple keys to one action by string
14385 var map = new Roo.KeyMap("my-element", {
14391 // map multiple keys to multiple actions by strings and array of codes
14392 var map = new Roo.KeyMap("my-element", [
14395 fn: function(){ alert("Return was pressed"); }
14398 fn: function(){ alert('a, b or c was pressed'); }
14403 fn: function(){ alert('Control + shift + tab was pressed.'); }
14407 * <b>Note: A KeyMap starts enabled</b>
14409 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14410 * @param {Object} config The config (see {@link #addBinding})
14411 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14413 Roo.KeyMap = function(el, config, eventName){
14414 this.el = Roo.get(el);
14415 this.eventName = eventName || "keydown";
14416 this.bindings = [];
14418 this.addBinding(config);
14423 Roo.KeyMap.prototype = {
14425 * True to stop the event from bubbling and prevent the default browser action if the
14426 * key was handled by the KeyMap (defaults to false)
14432 * Add a new binding to this KeyMap. The following config object properties are supported:
14434 Property Type Description
14435 ---------- --------------- ----------------------------------------------------------------------
14436 key String/Array A single keycode or an array of keycodes to handle
14437 shift Boolean True to handle key only when shift is pressed (defaults to false)
14438 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14439 alt Boolean True to handle key only when alt is pressed (defaults to false)
14440 fn Function The function to call when KeyMap finds the expected key combination
14441 scope Object The scope of the callback function
14447 var map = new Roo.KeyMap(document, {
14448 key: Roo.EventObject.ENTER,
14453 //Add a new binding to the existing KeyMap later
14461 * @param {Object/Array} config A single KeyMap config or an array of configs
14463 addBinding : function(config){
14464 if(config instanceof Array){
14465 for(var i = 0, len = config.length; i < len; i++){
14466 this.addBinding(config[i]);
14470 var keyCode = config.key,
14471 shift = config.shift,
14472 ctrl = config.ctrl,
14475 scope = config.scope;
14476 if(typeof keyCode == "string"){
14478 var keyString = keyCode.toUpperCase();
14479 for(var j = 0, len = keyString.length; j < len; j++){
14480 ks.push(keyString.charCodeAt(j));
14484 var keyArray = keyCode instanceof Array;
14485 var handler = function(e){
14486 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14487 var k = e.getKey();
14489 for(var i = 0, len = keyCode.length; i < len; i++){
14490 if(keyCode[i] == k){
14491 if(this.stopEvent){
14494 fn.call(scope || window, k, e);
14500 if(this.stopEvent){
14503 fn.call(scope || window, k, e);
14508 this.bindings.push(handler);
14512 * Shorthand for adding a single key listener
14513 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14514 * following options:
14515 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14516 * @param {Function} fn The function to call
14517 * @param {Object} scope (optional) The scope of the function
14519 on : function(key, fn, scope){
14520 var keyCode, shift, ctrl, alt;
14521 if(typeof key == "object" && !(key instanceof Array)){
14540 handleKeyDown : function(e){
14541 if(this.enabled){ //just in case
14542 var b = this.bindings;
14543 for(var i = 0, len = b.length; i < len; i++){
14544 b[i].call(this, e);
14550 * Returns true if this KeyMap is enabled
14551 * @return {Boolean}
14553 isEnabled : function(){
14554 return this.enabled;
14558 * Enables this KeyMap
14560 enable: function(){
14562 this.el.on(this.eventName, this.handleKeyDown, this);
14563 this.enabled = true;
14568 * Disable this KeyMap
14570 disable: function(){
14572 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14573 this.enabled = false;
14578 * Ext JS Library 1.1.1
14579 * Copyright(c) 2006-2007, Ext JS, LLC.
14581 * Originally Released Under LGPL - original licence link has changed is not relivant.
14584 * <script type="text/javascript">
14589 * @class Roo.util.TextMetrics
14590 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14591 * wide, in pixels, a given block of text will be.
14594 Roo.util.TextMetrics = function(){
14598 * Measures the size of the specified text
14599 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14600 * that can affect the size of the rendered text
14601 * @param {String} text The text to measure
14602 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14603 * in order to accurately measure the text height
14604 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14606 measure : function(el, text, fixedWidth){
14608 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14611 shared.setFixedWidth(fixedWidth || 'auto');
14612 return shared.getSize(text);
14616 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14617 * the overhead of multiple calls to initialize the style properties on each measurement.
14618 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14619 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14620 * in order to accurately measure the text height
14621 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14623 createInstance : function(el, fixedWidth){
14624 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14631 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14632 var ml = new Roo.Element(document.createElement('div'));
14633 document.body.appendChild(ml.dom);
14634 ml.position('absolute');
14635 ml.setLeftTop(-1000, -1000);
14639 ml.setWidth(fixedWidth);
14644 * Returns the size of the specified text based on the internal element's style and width properties
14645 * @memberOf Roo.util.TextMetrics.Instance#
14646 * @param {String} text The text to measure
14647 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14649 getSize : function(text){
14651 var s = ml.getSize();
14657 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14658 * that can affect the size of the rendered text
14659 * @memberOf Roo.util.TextMetrics.Instance#
14660 * @param {String/HTMLElement} el The element, dom node or id
14662 bind : function(el){
14664 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14669 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14670 * to set a fixed width in order to accurately measure the text height.
14671 * @memberOf Roo.util.TextMetrics.Instance#
14672 * @param {Number} width The width to set on the element
14674 setFixedWidth : function(width){
14675 ml.setWidth(width);
14679 * Returns the measured width of the specified text
14680 * @memberOf Roo.util.TextMetrics.Instance#
14681 * @param {String} text The text to measure
14682 * @return {Number} width The width in pixels
14684 getWidth : function(text){
14685 ml.dom.style.width = 'auto';
14686 return this.getSize(text).width;
14690 * Returns the measured height of the specified text. For multiline text, be sure to call
14691 * {@link #setFixedWidth} if necessary.
14692 * @memberOf Roo.util.TextMetrics.Instance#
14693 * @param {String} text The text to measure
14694 * @return {Number} height The height in pixels
14696 getHeight : function(text){
14697 return this.getSize(text).height;
14701 instance.bind(bindTo);
14706 // backwards compat
14707 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14709 * Ext JS Library 1.1.1
14710 * Copyright(c) 2006-2007, Ext JS, LLC.
14712 * Originally Released Under LGPL - original licence link has changed is not relivant.
14715 * <script type="text/javascript">
14719 * @class Roo.state.Provider
14720 * Abstract base class for state provider implementations. This class provides methods
14721 * for encoding and decoding <b>typed</b> variables including dates and defines the
14722 * Provider interface.
14724 Roo.state.Provider = function(){
14726 * @event statechange
14727 * Fires when a state change occurs.
14728 * @param {Provider} this This state provider
14729 * @param {String} key The state key which was changed
14730 * @param {String} value The encoded value for the state
14733 "statechange": true
14736 Roo.state.Provider.superclass.constructor.call(this);
14738 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14740 * Returns the current value for a key
14741 * @param {String} name The key name
14742 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14743 * @return {Mixed} The state data
14745 get : function(name, defaultValue){
14746 return typeof this.state[name] == "undefined" ?
14747 defaultValue : this.state[name];
14751 * Clears a value from the state
14752 * @param {String} name The key name
14754 clear : function(name){
14755 delete this.state[name];
14756 this.fireEvent("statechange", this, name, null);
14760 * Sets the value for a key
14761 * @param {String} name The key name
14762 * @param {Mixed} value The value to set
14764 set : function(name, value){
14765 this.state[name] = value;
14766 this.fireEvent("statechange", this, name, value);
14770 * Decodes a string previously encoded with {@link #encodeValue}.
14771 * @param {String} value The value to decode
14772 * @return {Mixed} The decoded value
14774 decodeValue : function(cookie){
14775 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14776 var matches = re.exec(unescape(cookie));
14777 if(!matches || !matches[1]) return; // non state cookie
14778 var type = matches[1];
14779 var v = matches[2];
14782 return parseFloat(v);
14784 return new Date(Date.parse(v));
14789 var values = v.split("^");
14790 for(var i = 0, len = values.length; i < len; i++){
14791 all.push(this.decodeValue(values[i]));
14796 var values = v.split("^");
14797 for(var i = 0, len = values.length; i < len; i++){
14798 var kv = values[i].split("=");
14799 all[kv[0]] = this.decodeValue(kv[1]);
14808 * Encodes a value including type information. Decode with {@link #decodeValue}.
14809 * @param {Mixed} value The value to encode
14810 * @return {String} The encoded value
14812 encodeValue : function(v){
14814 if(typeof v == "number"){
14816 }else if(typeof v == "boolean"){
14817 enc = "b:" + (v ? "1" : "0");
14818 }else if(v instanceof Date){
14819 enc = "d:" + v.toGMTString();
14820 }else if(v instanceof Array){
14822 for(var i = 0, len = v.length; i < len; i++){
14823 flat += this.encodeValue(v[i]);
14824 if(i != len-1) flat += "^";
14827 }else if(typeof v == "object"){
14830 if(typeof v[key] != "function"){
14831 flat += key + "=" + this.encodeValue(v[key]) + "^";
14834 enc = "o:" + flat.substring(0, flat.length-1);
14838 return escape(enc);
14844 * Ext JS Library 1.1.1
14845 * Copyright(c) 2006-2007, Ext JS, LLC.
14847 * Originally Released Under LGPL - original licence link has changed is not relivant.
14850 * <script type="text/javascript">
14853 * @class Roo.state.Manager
14854 * This is the global state manager. By default all components that are "state aware" check this class
14855 * for state information if you don't pass them a custom state provider. In order for this class
14856 * to be useful, it must be initialized with a provider when your application initializes.
14858 // in your initialization function
14860 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14862 // supposed you have a {@link Roo.BorderLayout}
14863 var layout = new Roo.BorderLayout(...);
14864 layout.restoreState();
14865 // or a {Roo.BasicDialog}
14866 var dialog = new Roo.BasicDialog(...);
14867 dialog.restoreState();
14871 Roo.state.Manager = function(){
14872 var provider = new Roo.state.Provider();
14876 * Configures the default state provider for your application
14877 * @param {Provider} stateProvider The state provider to set
14879 setProvider : function(stateProvider){
14880 provider = stateProvider;
14884 * Returns the current value for a key
14885 * @param {String} name The key name
14886 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14887 * @return {Mixed} The state data
14889 get : function(key, defaultValue){
14890 return provider.get(key, defaultValue);
14894 * Sets the value for a key
14895 * @param {String} name The key name
14896 * @param {Mixed} value The state data
14898 set : function(key, value){
14899 provider.set(key, value);
14903 * Clears a value from the state
14904 * @param {String} name The key name
14906 clear : function(key){
14907 provider.clear(key);
14911 * Gets the currently configured state provider
14912 * @return {Provider} The state provider
14914 getProvider : function(){
14921 * Ext JS Library 1.1.1
14922 * Copyright(c) 2006-2007, Ext JS, LLC.
14924 * Originally Released Under LGPL - original licence link has changed is not relivant.
14927 * <script type="text/javascript">
14930 * @class Roo.state.CookieProvider
14931 * @extends Roo.state.Provider
14932 * The default Provider implementation which saves state via cookies.
14935 var cp = new Roo.state.CookieProvider({
14937 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14938 domain: "roojs.com"
14940 Roo.state.Manager.setProvider(cp);
14942 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14943 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14944 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14945 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14946 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14947 * domain the page is running on including the 'www' like 'www.roojs.com')
14948 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14950 * Create a new CookieProvider
14951 * @param {Object} config The configuration object
14953 Roo.state.CookieProvider = function(config){
14954 Roo.state.CookieProvider.superclass.constructor.call(this);
14956 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14957 this.domain = null;
14958 this.secure = false;
14959 Roo.apply(this, config);
14960 this.state = this.readCookies();
14963 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14965 set : function(name, value){
14966 if(typeof value == "undefined" || value === null){
14970 this.setCookie(name, value);
14971 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14975 clear : function(name){
14976 this.clearCookie(name);
14977 Roo.state.CookieProvider.superclass.clear.call(this, name);
14981 readCookies : function(){
14983 var c = document.cookie + ";";
14984 var re = /\s?(.*?)=(.*?);/g;
14986 while((matches = re.exec(c)) != null){
14987 var name = matches[1];
14988 var value = matches[2];
14989 if(name && name.substring(0,3) == "ys-"){
14990 cookies[name.substr(3)] = this.decodeValue(value);
14997 setCookie : function(name, value){
14998 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14999 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15000 ((this.path == null) ? "" : ("; path=" + this.path)) +
15001 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15002 ((this.secure == true) ? "; secure" : "");
15006 clearCookie : function(name){
15007 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15008 ((this.path == null) ? "" : ("; path=" + this.path)) +
15009 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15010 ((this.secure == true) ? "; secure" : "");
15014 * Ext JS Library 1.1.1
15015 * Copyright(c) 2006-2007, Ext JS, LLC.
15017 * Originally Released Under LGPL - original licence link has changed is not relivant.
15020 * <script type="text/javascript">
15025 * @class Roo.ComponentMgr
15026 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15029 Roo.ComponentMgr = function(){
15030 var all = new Roo.util.MixedCollection();
15034 * Registers a component.
15035 * @param {Roo.Component} c The component
15037 register : function(c){
15042 * Unregisters a component.
15043 * @param {Roo.Component} c The component
15045 unregister : function(c){
15050 * Returns a component by id
15051 * @param {String} id The component id
15053 get : function(id){
15054 return all.get(id);
15058 * Registers a function that will be called when a specified component is added to ComponentMgr
15059 * @param {String} id The component id
15060 * @param {Funtction} fn The callback function
15061 * @param {Object} scope The scope of the callback
15063 onAvailable : function(id, fn, scope){
15064 all.on("add", function(index, o){
15066 fn.call(scope || o, o);
15067 all.un("add", fn, scope);
15074 * Ext JS Library 1.1.1
15075 * Copyright(c) 2006-2007, Ext JS, LLC.
15077 * Originally Released Under LGPL - original licence link has changed is not relivant.
15080 * <script type="text/javascript">
15084 * @class Roo.Component
15085 * @extends Roo.util.Observable
15086 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15087 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15088 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15089 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15090 * All visual components (widgets) that require rendering into a layout should subclass Component.
15092 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15093 * 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
15094 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15096 Roo.Component = function(config){
15097 config = config || {};
15098 if(config.tagName || config.dom || typeof config == "string"){ // element object
15099 config = {el: config, id: config.id || config};
15101 this.initialConfig = config;
15103 Roo.apply(this, config);
15107 * Fires after the component is disabled.
15108 * @param {Roo.Component} this
15113 * Fires after the component is enabled.
15114 * @param {Roo.Component} this
15118 * @event beforeshow
15119 * Fires before the component is shown. Return false to stop the show.
15120 * @param {Roo.Component} this
15125 * Fires after the component is shown.
15126 * @param {Roo.Component} this
15130 * @event beforehide
15131 * Fires before the component is hidden. Return false to stop the hide.
15132 * @param {Roo.Component} this
15137 * Fires after the component is hidden.
15138 * @param {Roo.Component} this
15142 * @event beforerender
15143 * Fires before the component is rendered. Return false to stop the render.
15144 * @param {Roo.Component} this
15146 beforerender : true,
15149 * Fires after the component is rendered.
15150 * @param {Roo.Component} this
15154 * @event beforedestroy
15155 * Fires before the component is destroyed. Return false to stop the destroy.
15156 * @param {Roo.Component} this
15158 beforedestroy : true,
15161 * Fires after the component is destroyed.
15162 * @param {Roo.Component} this
15167 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
15169 Roo.ComponentMgr.register(this);
15170 Roo.Component.superclass.constructor.call(this);
15171 this.initComponent();
15172 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15173 this.render(this.renderTo);
15174 delete this.renderTo;
15179 Roo.Component.AUTO_ID = 1000;
15181 Roo.extend(Roo.Component, Roo.util.Observable, {
15183 * @scope Roo.Component.prototype
15185 * true if this component is hidden. Read-only.
15190 * true if this component is disabled. Read-only.
15195 * true if this component has been rendered. Read-only.
15199 /** @cfg {String} disableClass
15200 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15202 disabledClass : "x-item-disabled",
15203 /** @cfg {Boolean} allowDomMove
15204 * Whether the component can move the Dom node when rendering (defaults to true).
15206 allowDomMove : true,
15207 /** @cfg {String} hideMode
15208 * How this component should hidden. Supported values are
15209 * "visibility" (css visibility), "offsets" (negative offset position) and
15210 * "display" (css display) - defaults to "display".
15212 hideMode: 'display',
15215 ctype : "Roo.Component",
15218 * @cfg {String} actionMode
15219 * which property holds the element that used for hide() / show() / disable() / enable()
15225 getActionEl : function(){
15226 return this[this.actionMode];
15229 initComponent : Roo.emptyFn,
15231 * If this is a lazy rendering component, render it to its container element.
15232 * @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.
15234 render : function(container, position){
15235 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15236 if(!container && this.el){
15237 this.el = Roo.get(this.el);
15238 container = this.el.dom.parentNode;
15239 this.allowDomMove = false;
15241 this.container = Roo.get(container);
15242 this.rendered = true;
15243 if(position !== undefined){
15244 if(typeof position == 'number'){
15245 position = this.container.dom.childNodes[position];
15247 position = Roo.getDom(position);
15250 this.onRender(this.container, position || null);
15252 this.el.addClass(this.cls);
15256 this.el.applyStyles(this.style);
15259 this.fireEvent("render", this);
15260 this.afterRender(this.container);
15272 // default function is not really useful
15273 onRender : function(ct, position){
15275 this.el = Roo.get(this.el);
15276 if(this.allowDomMove !== false){
15277 ct.dom.insertBefore(this.el.dom, position);
15283 getAutoCreate : function(){
15284 var cfg = typeof this.autoCreate == "object" ?
15285 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15286 if(this.id && !cfg.id){
15293 afterRender : Roo.emptyFn,
15296 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15297 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15299 destroy : function(){
15300 if(this.fireEvent("beforedestroy", this) !== false){
15301 this.purgeListeners();
15302 this.beforeDestroy();
15304 this.el.removeAllListeners();
15306 if(this.actionMode == "container"){
15307 this.container.remove();
15311 Roo.ComponentMgr.unregister(this);
15312 this.fireEvent("destroy", this);
15317 beforeDestroy : function(){
15322 onDestroy : function(){
15327 * Returns the underlying {@link Roo.Element}.
15328 * @return {Roo.Element} The element
15330 getEl : function(){
15335 * Returns the id of this component.
15338 getId : function(){
15343 * Try to focus this component.
15344 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15345 * @return {Roo.Component} this
15347 focus : function(selectText){
15350 if(selectText === true){
15351 this.el.dom.select();
15366 * Disable this component.
15367 * @return {Roo.Component} this
15369 disable : function(){
15373 this.disabled = true;
15374 this.fireEvent("disable", this);
15379 onDisable : function(){
15380 this.getActionEl().addClass(this.disabledClass);
15381 this.el.dom.disabled = true;
15385 * Enable this component.
15386 * @return {Roo.Component} this
15388 enable : function(){
15392 this.disabled = false;
15393 this.fireEvent("enable", this);
15398 onEnable : function(){
15399 this.getActionEl().removeClass(this.disabledClass);
15400 this.el.dom.disabled = false;
15404 * Convenience function for setting disabled/enabled by boolean.
15405 * @param {Boolean} disabled
15407 setDisabled : function(disabled){
15408 this[disabled ? "disable" : "enable"]();
15412 * Show this component.
15413 * @return {Roo.Component} this
15416 if(this.fireEvent("beforeshow", this) !== false){
15417 this.hidden = false;
15421 this.fireEvent("show", this);
15427 onShow : function(){
15428 var ae = this.getActionEl();
15429 if(this.hideMode == 'visibility'){
15430 ae.dom.style.visibility = "visible";
15431 }else if(this.hideMode == 'offsets'){
15432 ae.removeClass('x-hidden');
15434 ae.dom.style.display = "";
15439 * Hide this component.
15440 * @return {Roo.Component} this
15443 if(this.fireEvent("beforehide", this) !== false){
15444 this.hidden = true;
15448 this.fireEvent("hide", this);
15454 onHide : function(){
15455 var ae = this.getActionEl();
15456 if(this.hideMode == 'visibility'){
15457 ae.dom.style.visibility = "hidden";
15458 }else if(this.hideMode == 'offsets'){
15459 ae.addClass('x-hidden');
15461 ae.dom.style.display = "none";
15466 * Convenience function to hide or show this component by boolean.
15467 * @param {Boolean} visible True to show, false to hide
15468 * @return {Roo.Component} this
15470 setVisible: function(visible){
15480 * Returns true if this component is visible.
15482 isVisible : function(){
15483 return this.getActionEl().isVisible();
15486 cloneConfig : function(overrides){
15487 overrides = overrides || {};
15488 var id = overrides.id || Roo.id();
15489 var cfg = Roo.applyIf(overrides, this.initialConfig);
15490 cfg.id = id; // prevent dup id
15491 return new this.constructor(cfg);
15495 * Ext JS Library 1.1.1
15496 * Copyright(c) 2006-2007, Ext JS, LLC.
15498 * Originally Released Under LGPL - original licence link has changed is not relivant.
15501 * <script type="text/javascript">
15505 * @class Roo.BoxComponent
15506 * @extends Roo.Component
15507 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15508 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15509 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15510 * layout containers.
15512 * @param {Roo.Element/String/Object} config The configuration options.
15514 Roo.BoxComponent = function(config){
15515 Roo.Component.call(this, config);
15519 * Fires after the component is resized.
15520 * @param {Roo.Component} this
15521 * @param {Number} adjWidth The box-adjusted width that was set
15522 * @param {Number} adjHeight The box-adjusted height that was set
15523 * @param {Number} rawWidth The width that was originally specified
15524 * @param {Number} rawHeight The height that was originally specified
15529 * Fires after the component is moved.
15530 * @param {Roo.Component} this
15531 * @param {Number} x The new x position
15532 * @param {Number} y The new y position
15538 Roo.extend(Roo.BoxComponent, Roo.Component, {
15539 // private, set in afterRender to signify that the component has been rendered
15541 // private, used to defer height settings to subclasses
15542 deferHeight: false,
15543 /** @cfg {Number} width
15544 * width (optional) size of component
15546 /** @cfg {Number} height
15547 * height (optional) size of component
15551 * Sets the width and height of the component. This method fires the resize event. This method can accept
15552 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15553 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15554 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15555 * @return {Roo.BoxComponent} this
15557 setSize : function(w, h){
15558 // support for standard size objects
15559 if(typeof w == 'object'){
15564 if(!this.boxReady){
15570 // prevent recalcs when not needed
15571 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15574 this.lastSize = {width: w, height: h};
15576 var adj = this.adjustSize(w, h);
15577 var aw = adj.width, ah = adj.height;
15578 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15579 var rz = this.getResizeEl();
15580 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15581 rz.setSize(aw, ah);
15582 }else if(!this.deferHeight && ah !== undefined){
15584 }else if(aw !== undefined){
15587 this.onResize(aw, ah, w, h);
15588 this.fireEvent('resize', this, aw, ah, w, h);
15594 * Gets the current size of the component's underlying element.
15595 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15597 getSize : function(){
15598 return this.el.getSize();
15602 * Gets the current XY position of the component's underlying element.
15603 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15604 * @return {Array} The XY position of the element (e.g., [100, 200])
15606 getPosition : function(local){
15607 if(local === true){
15608 return [this.el.getLeft(true), this.el.getTop(true)];
15610 return this.xy || this.el.getXY();
15614 * Gets the current box measurements 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 * @returns {Object} box An object in the format {x, y, width, height}
15618 getBox : function(local){
15619 var s = this.el.getSize();
15621 s.x = this.el.getLeft(true);
15622 s.y = this.el.getTop(true);
15624 var xy = this.xy || this.el.getXY();
15632 * Sets the current box measurements of the component's underlying element.
15633 * @param {Object} box An object in the format {x, y, width, height}
15634 * @returns {Roo.BoxComponent} this
15636 updateBox : function(box){
15637 this.setSize(box.width, box.height);
15638 this.setPagePosition(box.x, box.y);
15643 getResizeEl : function(){
15644 return this.resizeEl || this.el;
15648 getPositionEl : function(){
15649 return this.positionEl || this.el;
15653 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15654 * This method fires the move event.
15655 * @param {Number} left The new left
15656 * @param {Number} top The new top
15657 * @returns {Roo.BoxComponent} this
15659 setPosition : function(x, y){
15662 if(!this.boxReady){
15665 var adj = this.adjustPosition(x, y);
15666 var ax = adj.x, ay = adj.y;
15668 var el = this.getPositionEl();
15669 if(ax !== undefined || ay !== undefined){
15670 if(ax !== undefined && ay !== undefined){
15671 el.setLeftTop(ax, ay);
15672 }else if(ax !== undefined){
15674 }else if(ay !== undefined){
15677 this.onPosition(ax, ay);
15678 this.fireEvent('move', this, ax, ay);
15684 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15685 * This method fires the move event.
15686 * @param {Number} x The new x position
15687 * @param {Number} y The new y position
15688 * @returns {Roo.BoxComponent} this
15690 setPagePosition : function(x, y){
15693 if(!this.boxReady){
15696 if(x === undefined || y === undefined){ // cannot translate undefined points
15699 var p = this.el.translatePoints(x, y);
15700 this.setPosition(p.left, p.top);
15705 onRender : function(ct, position){
15706 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15708 this.resizeEl = Roo.get(this.resizeEl);
15710 if(this.positionEl){
15711 this.positionEl = Roo.get(this.positionEl);
15716 afterRender : function(){
15717 Roo.BoxComponent.superclass.afterRender.call(this);
15718 this.boxReady = true;
15719 this.setSize(this.width, this.height);
15720 if(this.x || this.y){
15721 this.setPosition(this.x, this.y);
15723 if(this.pageX || this.pageY){
15724 this.setPagePosition(this.pageX, this.pageY);
15729 * Force the component's size to recalculate based on the underlying element's current height and width.
15730 * @returns {Roo.BoxComponent} this
15732 syncSize : function(){
15733 delete this.lastSize;
15734 this.setSize(this.el.getWidth(), this.el.getHeight());
15739 * Called after the component is resized, this method is empty by default but can be implemented by any
15740 * subclass that needs to perform custom logic after a resize occurs.
15741 * @param {Number} adjWidth The box-adjusted width that was set
15742 * @param {Number} adjHeight The box-adjusted height that was set
15743 * @param {Number} rawWidth The width that was originally specified
15744 * @param {Number} rawHeight The height that was originally specified
15746 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15751 * Called after the component is moved, this method is empty by default but can be implemented by any
15752 * subclass that needs to perform custom logic after a move occurs.
15753 * @param {Number} x The new x position
15754 * @param {Number} y The new y position
15756 onPosition : function(x, y){
15761 adjustSize : function(w, h){
15762 if(this.autoWidth){
15765 if(this.autoHeight){
15768 return {width : w, height: h};
15772 adjustPosition : function(x, y){
15773 return {x : x, y: y};
15776 * Original code for Roojs - LGPL
15777 * <script type="text/javascript">
15781 * @class Roo.XComponent
15782 * A delayed Element creator...
15783 * Or a way to group chunks of interface together.
15784 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15785 * used in conjunction with XComponent.build() it will create an instance of each element,
15786 * then call addxtype() to build the User interface.
15788 * Mypart.xyx = new Roo.XComponent({
15790 parent : 'Mypart.xyz', // empty == document.element.!!
15794 disabled : function() {}
15796 tree : function() { // return an tree of xtype declared components
15800 xtype : 'NestedLayoutPanel',
15807 * It can be used to build a big heiracy, with parent etc.
15808 * or you can just use this to render a single compoent to a dom element
15809 * MYPART.render(Roo.Element | String(id) | dom_element )
15816 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15817 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15819 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15821 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15822 * - if mulitple topModules exist, the last one is defined as the top module.
15826 * When the top level or multiple modules are to embedded into a existing HTML page,
15827 * the parent element can container '#id' of the element where the module will be drawn.
15831 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15832 * it relies more on a include mechanism, where sub modules are included into an outer page.
15833 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15835 * Bootstrap Roo Included elements
15837 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15838 * hence confusing the component builder as it thinks there are multiple top level elements.
15842 * @extends Roo.util.Observable
15844 * @param cfg {Object} configuration of component
15847 Roo.XComponent = function(cfg) {
15848 Roo.apply(this, cfg);
15852 * Fires when this the componnt is built
15853 * @param {Roo.XComponent} c the component
15858 this.region = this.region || 'center'; // default..
15859 Roo.XComponent.register(this);
15860 this.modules = false;
15861 this.el = false; // where the layout goes..
15865 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15868 * The created element (with Roo.factory())
15869 * @type {Roo.Layout}
15875 * for BC - use el in new code
15876 * @type {Roo.Layout}
15882 * for BC - use el in new code
15883 * @type {Roo.Layout}
15888 * @cfg {Function|boolean} disabled
15889 * If this module is disabled by some rule, return true from the funtion
15894 * @cfg {String} parent
15895 * Name of parent element which it get xtype added to..
15900 * @cfg {String} order
15901 * Used to set the order in which elements are created (usefull for multiple tabs)
15906 * @cfg {String} name
15907 * String to display while loading.
15911 * @cfg {String} region
15912 * Region to render component to (defaults to center)
15917 * @cfg {Array} items
15918 * A single item array - the first element is the root of the tree..
15919 * It's done this way to stay compatible with the Xtype system...
15925 * The method that retuns the tree of parts that make up this compoennt
15932 * render element to dom or tree
15933 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
15936 render : function(el)
15940 var hp = this.parent ? 1 : 0;
15941 Roo.debug && Roo.log(this);
15943 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
15944 // if parent is a '#.....' string, then let's use that..
15945 var ename = this.parent.substr(1);
15946 this.parent = false;
15947 Roo.debug && Roo.log(ename);
15949 case 'bootstrap-body' :
15950 if (typeof(Roo.bootstrap.Body) != 'undefined') {
15951 this.parent = { el : new Roo.bootstrap.Body() };
15952 Roo.debug && Roo.log("setting el to doc body");
15955 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
15959 this.parent = { el : true};
15962 el = Roo.get(ename);
15967 if (!el && !this.parent) {
15968 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
15972 Roo.debug && Roo.log("EL:");
15973 Roo.debug && Roo.log(el);
15974 Roo.debug && Roo.log("this.parent.el:");
15975 Roo.debug && Roo.log(this.parent.el);
15977 var tree = this._tree ? this._tree() : this.tree();
15979 // altertive root elements ??? - we need a better way to indicate these.
15980 var is_alt = (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
15981 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
15983 if (!this.parent && is_alt) {
15984 //el = Roo.get(document.body);
15985 this.parent = { el : true };
15990 if (!this.parent) {
15992 Roo.debug && Roo.log("no parent - creating one");
15994 el = el ? Roo.get(el) : false;
15996 // it's a top level one..
15998 el : new Roo.BorderLayout(el || document.body, {
16004 tabPosition: 'top',
16005 //resizeTabs: true,
16006 alwaysShowTabs: el && hp? false : true,
16007 hideTabs: el || !hp ? true : false,
16014 if (!this.parent.el) {
16015 // probably an old style ctor, which has been disabled.
16019 // The 'tree' method is '_tree now'
16021 tree.region = tree.region || this.region;
16023 if (this.parent.el === true) {
16024 // bootstrap... - body..
16025 this.parent.el = Roo.factory(tree);
16028 this.el = this.parent.el.addxtype(tree);
16029 this.fireEvent('built', this);
16031 this.panel = this.el;
16032 this.layout = this.panel.layout;
16033 this.parentLayout = this.parent.layout || false;
16039 Roo.apply(Roo.XComponent, {
16041 * @property hideProgress
16042 * true to disable the building progress bar.. usefull on single page renders.
16045 hideProgress : false,
16047 * @property buildCompleted
16048 * True when the builder has completed building the interface.
16051 buildCompleted : false,
16054 * @property topModule
16055 * the upper most module - uses document.element as it's constructor.
16062 * @property modules
16063 * array of modules to be created by registration system.
16064 * @type {Array} of Roo.XComponent
16069 * @property elmodules
16070 * array of modules to be created by which use #ID
16071 * @type {Array} of Roo.XComponent
16077 * @property build_from_html
16078 * Build elements from html - used by bootstrap HTML stuff
16079 * - this is cleared after build is completed
16080 * @type {boolean} true (default false)
16083 build_from_html : false,
16086 * Register components to be built later.
16088 * This solves the following issues
16089 * - Building is not done on page load, but after an authentication process has occured.
16090 * - Interface elements are registered on page load
16091 * - Parent Interface elements may not be loaded before child, so this handles that..
16098 module : 'Pman.Tab.projectMgr',
16100 parent : 'Pman.layout',
16101 disabled : false, // or use a function..
16104 * * @param {Object} details about module
16106 register : function(obj) {
16108 Roo.XComponent.event.fireEvent('register', obj);
16109 switch(typeof(obj.disabled) ) {
16115 if ( obj.disabled() ) {
16121 if (obj.disabled) {
16127 this.modules.push(obj);
16131 * convert a string to an object..
16132 * eg. 'AAA.BBB' -> finds AAA.BBB
16136 toObject : function(str)
16138 if (!str || typeof(str) == 'object') {
16141 if (str.substring(0,1) == '#') {
16145 var ar = str.split('.');
16150 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16152 throw "Module not found : " + str;
16156 throw "Module not found : " + str;
16158 Roo.each(ar, function(e) {
16159 if (typeof(o[e]) == 'undefined') {
16160 throw "Module not found : " + str;
16171 * move modules into their correct place in the tree..
16174 preBuild : function ()
16177 Roo.each(this.modules , function (obj)
16179 Roo.XComponent.event.fireEvent('beforebuild', obj);
16181 var opar = obj.parent;
16183 obj.parent = this.toObject(opar);
16185 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16190 Roo.debug && Roo.log("GOT top level module");
16191 Roo.debug && Roo.log(obj);
16192 obj.modules = new Roo.util.MixedCollection(false,
16193 function(o) { return o.order + '' }
16195 this.topModule = obj;
16198 // parent is a string (usually a dom element name..)
16199 if (typeof(obj.parent) == 'string') {
16200 this.elmodules.push(obj);
16203 if (obj.parent.constructor != Roo.XComponent) {
16204 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16206 if (!obj.parent.modules) {
16207 obj.parent.modules = new Roo.util.MixedCollection(false,
16208 function(o) { return o.order + '' }
16211 if (obj.parent.disabled) {
16212 obj.disabled = true;
16214 obj.parent.modules.add(obj);
16219 * make a list of modules to build.
16220 * @return {Array} list of modules.
16223 buildOrder : function()
16226 var cmp = function(a,b) {
16227 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16229 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16230 throw "No top level modules to build";
16233 // make a flat list in order of modules to build.
16234 var mods = this.topModule ? [ this.topModule ] : [];
16237 // elmodules (is a list of DOM based modules )
16238 Roo.each(this.elmodules, function(e) {
16240 if (!this.topModule &&
16241 typeof(e.parent) == 'string' &&
16242 e.parent.substring(0,1) == '#' &&
16243 Roo.get(e.parent.substr(1))
16246 _this.topModule = e;
16252 // add modules to their parents..
16253 var addMod = function(m) {
16254 Roo.debug && Roo.log("build Order: add: " + m.name);
16257 if (m.modules && !m.disabled) {
16258 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16259 m.modules.keySort('ASC', cmp );
16260 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16262 m.modules.each(addMod);
16264 Roo.debug && Roo.log("build Order: no child modules");
16266 // not sure if this is used any more..
16268 m.finalize.name = m.name + " (clean up) ";
16269 mods.push(m.finalize);
16273 if (this.topModule && this.topModule.modules) {
16274 this.topModule.modules.keySort('ASC', cmp );
16275 this.topModule.modules.each(addMod);
16281 * Build the registered modules.
16282 * @param {Object} parent element.
16283 * @param {Function} optional method to call after module has been added.
16287 build : function(opts)
16290 if (typeof(opts) != 'undefined') {
16291 Roo.apply(this,opts);
16295 var mods = this.buildOrder();
16297 //this.allmods = mods;
16298 //Roo.debug && Roo.log(mods);
16300 if (!mods.length) { // should not happen
16301 throw "NO modules!!!";
16305 var msg = "Building Interface...";
16306 // flash it up as modal - so we store the mask!?
16307 if (!this.hideProgress && Roo.MessageBox) {
16308 Roo.MessageBox.show({ title: 'loading' });
16309 Roo.MessageBox.show({
16310 title: "Please wait...",
16319 var total = mods.length;
16322 var progressRun = function() {
16323 if (!mods.length) {
16324 Roo.debug && Roo.log('hide?');
16325 if (!this.hideProgress && Roo.MessageBox) {
16326 Roo.MessageBox.hide();
16328 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16330 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16336 var m = mods.shift();
16339 Roo.debug && Roo.log(m);
16340 // not sure if this is supported any more.. - modules that are are just function
16341 if (typeof(m) == 'function') {
16343 return progressRun.defer(10, _this);
16347 msg = "Building Interface " + (total - mods.length) +
16349 (m.name ? (' - ' + m.name) : '');
16350 Roo.debug && Roo.log(msg);
16351 if (!this.hideProgress && Roo.MessageBox) {
16352 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16356 // is the module disabled?
16357 var disabled = (typeof(m.disabled) == 'function') ?
16358 m.disabled.call(m.module.disabled) : m.disabled;
16362 return progressRun(); // we do not update the display!
16370 // it's 10 on top level, and 1 on others??? why...
16371 return progressRun.defer(10, _this);
16374 progressRun.defer(1, _this);
16388 * wrapper for event.on - aliased later..
16389 * Typically use to register a event handler for register:
16391 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16400 Roo.XComponent.event = new Roo.util.Observable({
16404 * Fires when an Component is registered,
16405 * set the disable property on the Component to stop registration.
16406 * @param {Roo.XComponent} c the component being registerd.
16411 * @event beforebuild
16412 * Fires before each Component is built
16413 * can be used to apply permissions.
16414 * @param {Roo.XComponent} c the component being registerd.
16417 'beforebuild' : true,
16419 * @event buildcomplete
16420 * Fires on the top level element when all elements have been built
16421 * @param {Roo.XComponent} the top level component.
16423 'buildcomplete' : true
16428 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);