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 Roo.log('extend!!!!');
213 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
216 sb = function(){sp.apply(this, arguments);};
218 var F = function(){}, sbp, spp = sp.prototype;
220 sbp = sb.prototype = new F();
224 if(spp.constructor == Object.prototype.constructor){
229 sb.override = function(o){
233 Roo.override(sb, overrides);
239 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
241 Roo.override(MyClass, {
242 newMethod1: function(){
245 newMethod2: function(foo){
250 * @param {Object} origclass The class to override
251 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
252 * containing one or more methods.
255 override : function(origclass, overrides){
257 var p = origclass.prototype;
258 for(var method in overrides){
259 p[method] = overrides[method];
264 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
266 Roo.namespace('Company', 'Company.data');
267 Company.Widget = function() { ... }
268 Company.data.CustomStore = function(config) { ... }
270 * @param {String} namespace1
271 * @param {String} namespace2
272 * @param {String} etc
275 namespace : function(){
276 var a=arguments, o=null, i, j, d, rt;
277 for (i=0; i<a.length; ++i) {
281 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
282 for (j=1; j<d.length; ++j) {
283 o[d[j]]=o[d[j]] || {};
289 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
291 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
292 Roo.factory(conf, Roo.data);
294 * @param {String} classname
295 * @param {String} namespace (optional)
299 factory : function(c, ns)
301 // no xtype, no ns or c.xns - or forced off by c.xns
302 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
305 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
306 if (c.constructor == ns[c.xtype]) {// already created...
310 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
311 var ret = new ns[c.xtype](c);
315 c.xns = false; // prevent recursion..
319 * Logs to console if it can.
321 * @param {String|Object} string
326 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
333 * 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.
337 urlEncode : function(o){
343 var ov = o[key], k = Roo.encodeURIComponent(key);
344 var type = typeof ov;
345 if(type == 'undefined'){
347 }else if(type != "function" && type != "object"){
348 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
349 }else if(ov instanceof Array){
351 for(var i = 0, len = ov.length; i < len; i++) {
352 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
363 * Safe version of encodeURIComponent
364 * @param {String} data
368 encodeURIComponent : function (data)
371 return encodeURIComponent(data);
372 } catch(e) {} // should be an uri encode error.
374 if (data == '' || data == null){
377 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
378 function nibble_to_hex(nibble){
379 var chars = '0123456789ABCDEF';
380 return chars.charAt(nibble);
382 data = data.toString();
384 for(var i=0; i<data.length; i++){
385 var c = data.charCodeAt(i);
386 var bs = new Array();
389 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
390 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
391 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
392 bs[3] = 0x80 | (c & 0x3F);
393 }else if (c > 0x800){
395 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
396 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
397 bs[2] = 0x80 | (c & 0x3F);
400 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
401 bs[1] = 0x80 | (c & 0x3F);
406 for(var j=0; j<bs.length; j++){
408 var hex = nibble_to_hex((b & 0xF0) >>> 4)
409 + nibble_to_hex(b &0x0F);
418 * 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]}.
419 * @param {String} string
420 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
421 * @return {Object} A literal with members
423 urlDecode : function(string, overwrite){
424 if(!string || !string.length){
428 var pairs = string.split('&');
429 var pair, name, value;
430 for(var i = 0, len = pairs.length; i < len; i++){
431 pair = pairs[i].split('=');
432 name = decodeURIComponent(pair[0]);
433 value = decodeURIComponent(pair[1]);
434 if(overwrite !== true){
435 if(typeof obj[name] == "undefined"){
437 }else if(typeof obj[name] == "string"){
438 obj[name] = [obj[name]];
439 obj[name].push(value);
441 obj[name].push(value);
451 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
452 * passed array is not really an array, your function is called once with it.
453 * The supplied function is called with (Object item, Number index, Array allItems).
454 * @param {Array/NodeList/Mixed} array
455 * @param {Function} fn
456 * @param {Object} scope
458 each : function(array, fn, scope){
459 if(typeof array.length == "undefined" || typeof array == "string"){
462 for(var i = 0, len = array.length; i < len; i++){
463 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
468 combine : function(){
469 var as = arguments, l = as.length, r = [];
470 for(var i = 0; i < l; i++){
472 if(a instanceof Array){
474 }else if(a.length !== undefined && !a.substr){
475 r = r.concat(Array.prototype.slice.call(a, 0));
484 * Escapes the passed string for use in a regular expression
485 * @param {String} str
488 escapeRe : function(s) {
489 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
493 callback : function(cb, scope, args, delay){
494 if(typeof cb == "function"){
496 cb.defer(delay, scope, args || []);
498 cb.apply(scope, args || []);
504 * Return the dom node for the passed string (id), dom node, or Roo.Element
505 * @param {String/HTMLElement/Roo.Element} el
506 * @return HTMLElement
508 getDom : function(el){
512 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
516 * Shorthand for {@link Roo.ComponentMgr#get}
518 * @return Roo.Component
520 getCmp : function(id){
521 return Roo.ComponentMgr.get(id);
524 num : function(v, defaultValue){
525 if(typeof v != 'number'){
531 destroy : function(){
532 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
536 as.removeAllListeners();
540 if(typeof as.purgeListeners == 'function'){
543 if(typeof as.destroy == 'function'){
550 // inpired by a similar function in mootools library
552 * Returns the type of object that is passed in. If the object passed in is null or undefined it
553 * return false otherwise it returns one of the following values:<ul>
554 * <li><b>string</b>: If the object passed is a string</li>
555 * <li><b>number</b>: If the object passed is a number</li>
556 * <li><b>boolean</b>: If the object passed is a boolean value</li>
557 * <li><b>function</b>: If the object passed is a function reference</li>
558 * <li><b>object</b>: If the object passed is an object</li>
559 * <li><b>array</b>: If the object passed is an array</li>
560 * <li><b>regexp</b>: If the object passed is a regular expression</li>
561 * <li><b>element</b>: If the object passed is a DOM Element</li>
562 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
563 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
564 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
565 * @param {Mixed} object
569 if(o === undefined || o === null){
576 if(t == 'object' && o.nodeName) {
578 case 1: return 'element';
579 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
582 if(t == 'object' || t == 'function') {
583 switch(o.constructor) {
584 case Array: return 'array';
585 case RegExp: return 'regexp';
587 if(typeof o.length == 'number' && typeof o.item == 'function') {
595 * Returns true if the passed value is null, undefined or an empty string (optional).
596 * @param {Mixed} value The value to test
597 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
600 isEmpty : function(v, allowBlank){
601 return v === null || v === undefined || (!allowBlank ? v === '' : false);
615 isBorderBox : isBorderBox,
617 isWindows : isWindows,
626 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
627 * you may want to set this to true.
630 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
635 * Selects a single element as a Roo Element
636 * This is about as close as you can get to jQuery's $('do crazy stuff')
637 * @param {String} selector The selector/xpath query
638 * @param {Node} root (optional) The start of the query (defaults to document).
639 * @return {Roo.Element}
641 selectNode : function(selector, root)
643 var node = Roo.DomQuery.selectNode(selector,root);
644 return node ? Roo.get(node) : new Roo.Element(false);
652 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
653 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
656 * Ext JS Library 1.1.1
657 * Copyright(c) 2006-2007, Ext JS, LLC.
659 * Originally Released Under LGPL - original licence link has changed is not relivant.
662 * <script type="text/javascript">
666 // wrappedn so fnCleanup is not in global scope...
668 function fnCleanUp() {
669 var p = Function.prototype;
670 delete p.createSequence;
672 delete p.createDelegate;
673 delete p.createCallback;
674 delete p.createInterceptor;
676 window.detachEvent("onunload", fnCleanUp);
678 window.attachEvent("onunload", fnCleanUp);
685 * These functions are available on every Function object (any JavaScript function).
687 Roo.apply(Function.prototype, {
689 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
690 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
691 * Will create a function that is bound to those 2 args.
692 * @return {Function} The new function
694 createCallback : function(/*args...*/){
695 // make args available, in function below
696 var args = arguments;
699 return method.apply(window, args);
704 * Creates a delegate (callback) that sets the scope to obj.
705 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
706 * Will create a function that is automatically scoped to this.
707 * @param {Object} obj (optional) The object for which the scope is set
708 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
709 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
710 * if a number the args are inserted at the specified position
711 * @return {Function} The new function
713 createDelegate : function(obj, args, appendArgs){
716 var callArgs = args || arguments;
717 if(appendArgs === true){
718 callArgs = Array.prototype.slice.call(arguments, 0);
719 callArgs = callArgs.concat(args);
720 }else if(typeof appendArgs == "number"){
721 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
722 var applyArgs = [appendArgs, 0].concat(args); // create method call params
723 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
725 return method.apply(obj || window, callArgs);
730 * Calls this function after the number of millseconds specified.
731 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
732 * @param {Object} obj (optional) The object for which the scope is set
733 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
734 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
735 * if a number the args are inserted at the specified position
736 * @return {Number} The timeout id that can be used with clearTimeout
738 defer : function(millis, obj, args, appendArgs){
739 var fn = this.createDelegate(obj, args, appendArgs);
741 return setTimeout(fn, millis);
747 * Create a combined function call sequence of the original function + the passed function.
748 * The resulting function returns the results of the original function.
749 * The passed fcn is called with the parameters of the original function
750 * @param {Function} fcn The function to sequence
751 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
752 * @return {Function} The new function
754 createSequence : function(fcn, scope){
755 if(typeof fcn != "function"){
760 var retval = method.apply(this || window, arguments);
761 fcn.apply(scope || this || window, arguments);
767 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
768 * The resulting function returns the results of the original function.
769 * The passed fcn is called with the parameters of the original function.
771 * @param {Function} fcn The function to call before the original
772 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
773 * @return {Function} The new function
775 createInterceptor : function(fcn, scope){
776 if(typeof fcn != "function"){
783 if(fcn.apply(scope || this || window, arguments) === false){
786 return method.apply(this || window, arguments);
792 * Ext JS Library 1.1.1
793 * Copyright(c) 2006-2007, Ext JS, LLC.
795 * Originally Released Under LGPL - original licence link has changed is not relivant.
798 * <script type="text/javascript">
801 Roo.applyIf(String, {
806 * Escapes the passed string for ' and \
807 * @param {String} string The string to escape
808 * @return {String} The escaped string
811 escape : function(string) {
812 return string.replace(/('|\\)/g, "\\$1");
816 * Pads the left side of a string with a specified character. This is especially useful
817 * for normalizing number and date strings. Example usage:
819 var s = String.leftPad('123', 5, '0');
820 // s now contains the string: '00123'
822 * @param {String} string The original string
823 * @param {Number} size The total length of the output string
824 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
825 * @return {String} The padded string
828 leftPad : function (val, size, ch) {
829 var result = new String(val);
830 if(ch === null || ch === undefined || ch === '') {
833 while (result.length < size) {
834 result = ch + result;
840 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
841 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
843 var cls = 'my-class', text = 'Some text';
844 var s = String.format('<div class="{0}">{1}</div>', cls, text);
845 // s now contains the string: '<div class="my-class">Some text</div>'
847 * @param {String} string The tokenized string to be formatted
848 * @param {String} value1 The value to replace token {0}
849 * @param {String} value2 Etc...
850 * @return {String} The formatted string
853 format : function(format){
854 var args = Array.prototype.slice.call(arguments, 1);
855 return format.replace(/\{(\d+)\}/g, function(m, i){
856 return Roo.util.Format.htmlEncode(args[i]);
862 * Utility function that allows you to easily switch a string between two alternating values. The passed value
863 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
864 * they are already different, the first value passed in is returned. Note that this method returns the new value
865 * but does not change the current string.
867 // alternate sort directions
868 sort = sort.toggle('ASC', 'DESC');
870 // instead of conditional logic:
871 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
873 * @param {String} value The value to compare to the current string
874 * @param {String} other The new value to use if the string already equals the first value passed in
875 * @return {String} The new value
878 String.prototype.toggle = function(value, other){
879 return this == value ? other : value;
882 * Ext JS Library 1.1.1
883 * Copyright(c) 2006-2007, Ext JS, LLC.
885 * Originally Released Under LGPL - original licence link has changed is not relivant.
888 * <script type="text/javascript">
894 Roo.applyIf(Number.prototype, {
896 * Checks whether or not the current number is within a desired range. If the number is already within the
897 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
898 * exceeded. Note that this method returns the constrained value but does not change the current number.
899 * @param {Number} min The minimum number in the range
900 * @param {Number} max The maximum number in the range
901 * @return {Number} The constrained value if outside the range, otherwise the current value
903 constrain : function(min, max){
904 return Math.min(Math.max(this, min), max);
908 * Ext JS Library 1.1.1
909 * Copyright(c) 2006-2007, Ext JS, LLC.
911 * Originally Released Under LGPL - original licence link has changed is not relivant.
914 * <script type="text/javascript">
919 Roo.applyIf(Array.prototype, {
921 * Checks whether or not the specified object exists in the array.
922 * @param {Object} o The object to check for
923 * @return {Number} The index of o in the array (or -1 if it is not found)
925 indexOf : function(o){
926 for (var i = 0, len = this.length; i < len; i++){
927 if(this[i] == o) return i;
933 * Removes the specified object from the array. If the object is not found nothing happens.
934 * @param {Object} o The object to remove
936 remove : function(o){
937 var index = this.indexOf(o);
939 this.splice(index, 1);
943 * Map (JS 1.6 compatibility)
944 * @param {Function} function to call
948 var len = this.length >>> 0;
949 if (typeof fun != "function")
950 throw new TypeError();
952 var res = new Array(len);
953 var thisp = arguments[1];
954 for (var i = 0; i < len; i++)
957 res[i] = fun.call(thisp, this[i], i, this);
968 * Ext JS Library 1.1.1
969 * Copyright(c) 2006-2007, Ext JS, LLC.
971 * Originally Released Under LGPL - original licence link has changed is not relivant.
974 * <script type="text/javascript">
980 * The date parsing and format syntax is a subset of
981 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
982 * supported will provide results equivalent to their PHP versions.
984 * Following is the list of all currently supported formats:
987 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
989 Format Output Description
990 ------ ---------- --------------------------------------------------------------
991 d 10 Day of the month, 2 digits with leading zeros
992 D Wed A textual representation of a day, three letters
993 j 10 Day of the month without leading zeros
994 l Wednesday A full textual representation of the day of the week
995 S th English ordinal day of month suffix, 2 chars (use with j)
996 w 3 Numeric representation of the day of the week
997 z 9 The julian date, or day of the year (0-365)
998 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
999 F January A full textual representation of the month
1000 m 01 Numeric representation of a month, with leading zeros
1001 M Jan Month name abbreviation, three letters
1002 n 1 Numeric representation of a month, without leading zeros
1003 t 31 Number of days in the given month
1004 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1005 Y 2007 A full numeric representation of a year, 4 digits
1006 y 07 A two digit representation of a year
1007 a pm Lowercase Ante meridiem and Post meridiem
1008 A PM Uppercase Ante meridiem and Post meridiem
1009 g 3 12-hour format of an hour without leading zeros
1010 G 15 24-hour format of an hour without leading zeros
1011 h 03 12-hour format of an hour with leading zeros
1012 H 15 24-hour format of an hour with leading zeros
1013 i 05 Minutes with leading zeros
1014 s 01 Seconds, with leading zeros
1015 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1016 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1017 T CST Timezone setting of the machine running the code
1018 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1021 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1023 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1024 document.write(dt.format('Y-m-d')); //2007-01-10
1025 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1026 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
1029 * Here are some standard date/time patterns that you might find helpful. They
1030 * are not part of the source of Date.js, but to use them you can simply copy this
1031 * block of code into any script that is included after Date.js and they will also become
1032 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1035 ISO8601Long:"Y-m-d H:i:s",
1036 ISO8601Short:"Y-m-d",
1038 LongDate: "l, F d, Y",
1039 FullDateTime: "l, F d, Y g:i:s A",
1042 LongTime: "g:i:s A",
1043 SortableDateTime: "Y-m-d\\TH:i:s",
1044 UniversalSortableDateTime: "Y-m-d H:i:sO",
1051 var dt = new Date();
1052 document.write(dt.format(Date.patterns.ShortDate));
1057 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1058 * They generate precompiled functions from date formats instead of parsing and
1059 * processing the pattern every time you format a date. These functions are available
1060 * on every Date object (any javascript function).
1062 * The original article and download are here:
1063 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1070 Returns the number of milliseconds between this date and date
1071 @param {Date} date (optional) Defaults to now
1072 @return {Number} The diff in milliseconds
1073 @member Date getElapsed
1075 Date.prototype.getElapsed = function(date) {
1076 return Math.abs((date || new Date()).getTime()-this.getTime());
1078 // was in date file..
1082 Date.parseFunctions = {count:0};
1084 Date.parseRegexes = [];
1086 Date.formatFunctions = {count:0};
1089 Date.prototype.dateFormat = function(format) {
1090 if (Date.formatFunctions[format] == null) {
1091 Date.createNewFormat(format);
1093 var func = Date.formatFunctions[format];
1094 return this[func]();
1099 * Formats a date given the supplied format string
1100 * @param {String} format The format string
1101 * @return {String} The formatted date
1104 Date.prototype.format = Date.prototype.dateFormat;
1107 Date.createNewFormat = function(format) {
1108 var funcName = "format" + Date.formatFunctions.count++;
1109 Date.formatFunctions[format] = funcName;
1110 var code = "Date.prototype." + funcName + " = function(){return ";
1111 var special = false;
1113 for (var i = 0; i < format.length; ++i) {
1114 ch = format.charAt(i);
1115 if (!special && ch == "\\") {
1120 code += "'" + String.escape(ch) + "' + ";
1123 code += Date.getFormatCode(ch);
1126 /** eval:var:zzzzzzzzzzzzz */
1127 eval(code.substring(0, code.length - 3) + ";}");
1131 Date.getFormatCode = function(character) {
1132 switch (character) {
1134 return "String.leftPad(this.getDate(), 2, '0') + ";
1136 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1138 return "this.getDate() + ";
1140 return "Date.dayNames[this.getDay()] + ";
1142 return "this.getSuffix() + ";
1144 return "this.getDay() + ";
1146 return "this.getDayOfYear() + ";
1148 return "this.getWeekOfYear() + ";
1150 return "Date.monthNames[this.getMonth()] + ";
1152 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1154 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1156 return "(this.getMonth() + 1) + ";
1158 return "this.getDaysInMonth() + ";
1160 return "(this.isLeapYear() ? 1 : 0) + ";
1162 return "this.getFullYear() + ";
1164 return "('' + this.getFullYear()).substring(2, 4) + ";
1166 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1168 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1170 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1172 return "this.getHours() + ";
1174 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1176 return "String.leftPad(this.getHours(), 2, '0') + ";
1178 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1180 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1182 return "this.getGMTOffset() + ";
1184 return "this.getGMTColonOffset() + ";
1186 return "this.getTimezone() + ";
1188 return "(this.getTimezoneOffset() * -60) + ";
1190 return "'" + String.escape(character) + "' + ";
1195 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1196 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1197 * the date format that is not specified will default to the current date value for that part. Time parts can also
1198 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1199 * string or the parse operation will fail.
1202 //dt = Fri May 25 2007 (current date)
1203 var dt = new Date();
1205 //dt = Thu May 25 2006 (today's month/day in 2006)
1206 dt = Date.parseDate("2006", "Y");
1208 //dt = Sun Jan 15 2006 (all date parts specified)
1209 dt = Date.parseDate("2006-1-15", "Y-m-d");
1211 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1212 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1214 * @param {String} input The unparsed date as a string
1215 * @param {String} format The format the date is in
1216 * @return {Date} The parsed date
1219 Date.parseDate = function(input, format) {
1220 if (Date.parseFunctions[format] == null) {
1221 Date.createParser(format);
1223 var func = Date.parseFunctions[format];
1224 return Date[func](input);
1229 Date.createParser = function(format) {
1230 var funcName = "parse" + Date.parseFunctions.count++;
1231 var regexNum = Date.parseRegexes.length;
1232 var currentGroup = 1;
1233 Date.parseFunctions[format] = funcName;
1235 var code = "Date." + funcName + " = function(input){\n"
1236 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1237 + "var d = new Date();\n"
1238 + "y = d.getFullYear();\n"
1239 + "m = d.getMonth();\n"
1240 + "d = d.getDate();\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;
6052 var fireDocReady = function(){
6054 docReadyState = true;
6057 clearInterval(docReadyProcId);
6059 if(Roo.isGecko || Roo.isOpera) {
6060 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6063 var defer = document.getElementById("ie-deferred-loader");
6065 defer.onreadystatechange = null;
6066 defer.parentNode.removeChild(defer);
6070 docReadyEvent.fire();
6071 docReadyEvent.clearListeners();
6076 var initDocReady = function(){
6077 docReadyEvent = new Roo.util.Event();
6078 if(Roo.isGecko || Roo.isOpera) {
6079 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6081 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6082 var defer = document.getElementById("ie-deferred-loader");
6083 defer.onreadystatechange = function(){
6084 if(this.readyState == "complete"){
6088 }else if(Roo.isSafari){
6089 docReadyProcId = setInterval(function(){
6090 var rs = document.readyState;
6091 if(rs == "complete") {
6096 // no matter what, make sure it fires on load
6097 E.on(window, "load", fireDocReady);
6100 var createBuffered = function(h, o){
6101 var task = new Roo.util.DelayedTask(h);
6103 // create new event object impl so new events don't wipe out properties
6104 e = new Roo.EventObjectImpl(e);
6105 task.delay(o.buffer, h, null, [e]);
6109 var createSingle = function(h, el, ename, fn){
6111 Roo.EventManager.removeListener(el, ename, fn);
6116 var createDelayed = function(h, o){
6118 // create new event object impl so new events don't wipe out properties
6119 e = new Roo.EventObjectImpl(e);
6120 setTimeout(function(){
6126 var listen = function(element, ename, opt, fn, scope){
6127 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6128 fn = fn || o.fn; scope = scope || o.scope;
6129 var el = Roo.getDom(element);
6131 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6133 var h = function(e){
6134 e = Roo.EventObject.setEvent(e);
6137 t = e.getTarget(o.delegate, el);
6144 if(o.stopEvent === true){
6147 if(o.preventDefault === true){
6150 if(o.stopPropagation === true){
6151 e.stopPropagation();
6154 if(o.normalized === false){
6158 fn.call(scope || el, e, t, o);
6161 h = createDelayed(h, o);
6164 h = createSingle(h, el, ename, fn);
6167 h = createBuffered(h, o);
6169 fn._handlers = fn._handlers || [];
6170 fn._handlers.push([Roo.id(el), ename, h]);
6173 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6174 el.addEventListener("DOMMouseScroll", h, false);
6175 E.on(window, 'unload', function(){
6176 el.removeEventListener("DOMMouseScroll", h, false);
6179 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6180 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6185 var stopListening = function(el, ename, fn){
6186 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6188 for(var i = 0, len = hds.length; i < len; i++){
6190 if(h[0] == id && h[1] == ename){
6197 E.un(el, ename, hd);
6198 el = Roo.getDom(el);
6199 if(ename == "mousewheel" && el.addEventListener){
6200 el.removeEventListener("DOMMouseScroll", hd, false);
6202 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6203 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6207 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6214 * @scope Roo.EventManager
6219 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6220 * object with a Roo.EventObject
6221 * @param {Function} fn The method the event invokes
6222 * @param {Object} scope An object that becomes the scope of the handler
6223 * @param {boolean} override If true, the obj passed in becomes
6224 * the execution scope of the listener
6225 * @return {Function} The wrapped function
6228 wrap : function(fn, scope, override){
6230 Roo.EventObject.setEvent(e);
6231 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6236 * Appends an event handler to an element (shorthand for addListener)
6237 * @param {String/HTMLElement} element The html element or id to assign the
6238 * @param {String} eventName The type of event to listen for
6239 * @param {Function} handler The method the event invokes
6240 * @param {Object} scope (optional) The scope in which to execute the handler
6241 * function. The handler function's "this" context.
6242 * @param {Object} options (optional) An object containing handler configuration
6243 * properties. This may contain any of the following properties:<ul>
6244 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6245 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6246 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6247 * <li>preventDefault {Boolean} True to prevent the default action</li>
6248 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6249 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6250 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6251 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6252 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6253 * by the specified number of milliseconds. If the event fires again within that time, the original
6254 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6257 * <b>Combining Options</b><br>
6258 * Using the options argument, it is possible to combine different types of listeners:<br>
6260 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6262 el.on('click', this.onClick, this, {
6269 * <b>Attaching multiple handlers in 1 call</b><br>
6270 * The method also allows for a single argument to be passed which is a config object containing properties
6271 * which specify multiple handlers.
6281 fn: this.onMouseOver
6290 * Or a shorthand syntax:<br>
6293 'click' : this.onClick,
6294 'mouseover' : this.onMouseOver,
6295 'mouseout' : this.onMouseOut
6299 addListener : function(element, eventName, fn, scope, options){
6300 if(typeof eventName == "object"){
6306 if(typeof o[e] == "function"){
6308 listen(element, e, o, o[e], o.scope);
6310 // individual options
6311 listen(element, e, o[e]);
6316 return listen(element, eventName, options, fn, scope);
6320 * Removes an event handler
6322 * @param {String/HTMLElement} element The id or html element to remove the
6324 * @param {String} eventName The type of event
6325 * @param {Function} fn
6326 * @return {Boolean} True if a listener was actually removed
6328 removeListener : function(element, eventName, fn){
6329 return stopListening(element, eventName, fn);
6333 * Fires when the document is ready (before onload and before images are loaded). Can be
6334 * accessed shorthanded Roo.onReady().
6335 * @param {Function} fn The method the event invokes
6336 * @param {Object} scope An object that becomes the scope of the handler
6337 * @param {boolean} options
6339 onDocumentReady : function(fn, scope, options){
6340 if(docReadyState){ // if it already fired
6341 docReadyEvent.addListener(fn, scope, options);
6342 docReadyEvent.fire();
6343 docReadyEvent.clearListeners();
6349 docReadyEvent.addListener(fn, scope, options);
6353 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6354 * @param {Function} fn The method the event invokes
6355 * @param {Object} scope An object that becomes the scope of the handler
6356 * @param {boolean} options
6358 onWindowResize : function(fn, scope, options){
6360 resizeEvent = new Roo.util.Event();
6361 resizeTask = new Roo.util.DelayedTask(function(){
6362 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6364 E.on(window, "resize", function(){
6366 resizeTask.delay(50);
6368 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6372 resizeEvent.addListener(fn, scope, options);
6376 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6377 * @param {Function} fn The method the event invokes
6378 * @param {Object} scope An object that becomes the scope of the handler
6379 * @param {boolean} options
6381 onTextResize : function(fn, scope, options){
6383 textEvent = new Roo.util.Event();
6384 var textEl = new Roo.Element(document.createElement('div'));
6385 textEl.dom.className = 'x-text-resize';
6386 textEl.dom.innerHTML = 'X';
6387 textEl.appendTo(document.body);
6388 textSize = textEl.dom.offsetHeight;
6389 setInterval(function(){
6390 if(textEl.dom.offsetHeight != textSize){
6391 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6393 }, this.textResizeInterval);
6395 textEvent.addListener(fn, scope, options);
6399 * Removes the passed window resize listener.
6400 * @param {Function} fn The method the event invokes
6401 * @param {Object} scope The scope of handler
6403 removeResizeListener : function(fn, scope){
6405 resizeEvent.removeListener(fn, scope);
6410 fireResize : function(){
6412 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6416 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6420 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6422 textResizeInterval : 50
6427 * @scopeAlias pub=Roo.EventManager
6431 * Appends an event handler to an element (shorthand for addListener)
6432 * @param {String/HTMLElement} element The html element or id to assign the
6433 * @param {String} eventName The type of event to listen for
6434 * @param {Function} handler The method the event invokes
6435 * @param {Object} scope (optional) The scope in which to execute the handler
6436 * function. The handler function's "this" context.
6437 * @param {Object} options (optional) An object containing handler configuration
6438 * properties. This may contain any of the following properties:<ul>
6439 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6440 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6441 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6442 * <li>preventDefault {Boolean} True to prevent the default action</li>
6443 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6444 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6445 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6446 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6447 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6448 * by the specified number of milliseconds. If the event fires again within that time, the original
6449 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6452 * <b>Combining Options</b><br>
6453 * Using the options argument, it is possible to combine different types of listeners:<br>
6455 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6457 el.on('click', this.onClick, this, {
6464 * <b>Attaching multiple handlers in 1 call</b><br>
6465 * The method also allows for a single argument to be passed which is a config object containing properties
6466 * which specify multiple handlers.
6476 fn: this.onMouseOver
6485 * Or a shorthand syntax:<br>
6488 'click' : this.onClick,
6489 'mouseover' : this.onMouseOver,
6490 'mouseout' : this.onMouseOut
6494 pub.on = pub.addListener;
6495 pub.un = pub.removeListener;
6497 pub.stoppedMouseDownEvent = new Roo.util.Event();
6501 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6502 * @param {Function} fn The method the event invokes
6503 * @param {Object} scope An object that becomes the scope of the handler
6504 * @param {boolean} override If true, the obj passed in becomes
6505 * the execution scope of the listener
6509 Roo.onReady = Roo.EventManager.onDocumentReady;
6511 Roo.onReady(function(){
6512 var bd = Roo.get(document.body);
6517 : Roo.isGecko ? "roo-gecko"
6518 : Roo.isOpera ? "roo-opera"
6519 : Roo.isSafari ? "roo-safari" : ""];
6522 cls.push("roo-mac");
6525 cls.push("roo-linux");
6527 if(Roo.isBorderBox){
6528 cls.push('roo-border-box');
6530 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6531 var p = bd.dom.parentNode;
6533 p.className += ' roo-strict';
6536 bd.addClass(cls.join(' '));
6540 * @class Roo.EventObject
6541 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6542 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6545 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6547 var target = e.getTarget();
6550 var myDiv = Roo.get("myDiv");
6551 myDiv.on("click", handleClick);
6553 Roo.EventManager.on("myDiv", 'click', handleClick);
6554 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6558 Roo.EventObject = function(){
6560 var E = Roo.lib.Event;
6562 // safari keypress events for special keys return bad keycodes
6565 63235 : 39, // right
6568 63276 : 33, // page up
6569 63277 : 34, // page down
6570 63272 : 46, // delete
6575 // normalize button clicks
6576 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6577 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6579 Roo.EventObjectImpl = function(e){
6581 this.setEvent(e.browserEvent || e);
6584 Roo.EventObjectImpl.prototype = {
6586 * Used to fix doc tools.
6587 * @scope Roo.EventObject.prototype
6593 /** The normal browser event */
6594 browserEvent : null,
6595 /** The button pressed in a mouse event */
6597 /** True if the shift key was down during the event */
6599 /** True if the control key was down during the event */
6601 /** True if the alt key was down during the event */
6660 setEvent : function(e){
6661 if(e == this || (e && e.browserEvent)){ // already wrapped
6664 this.browserEvent = e;
6666 // normalize buttons
6667 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6668 if(e.type == 'click' && this.button == -1){
6672 this.shiftKey = e.shiftKey;
6673 // mac metaKey behaves like ctrlKey
6674 this.ctrlKey = e.ctrlKey || e.metaKey;
6675 this.altKey = e.altKey;
6676 // in getKey these will be normalized for the mac
6677 this.keyCode = e.keyCode;
6678 // keyup warnings on firefox.
6679 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6680 // cache the target for the delayed and or buffered events
6681 this.target = E.getTarget(e);
6683 this.xy = E.getXY(e);
6686 this.shiftKey = false;
6687 this.ctrlKey = false;
6688 this.altKey = false;
6698 * Stop the event (preventDefault and stopPropagation)
6700 stopEvent : function(){
6701 if(this.browserEvent){
6702 if(this.browserEvent.type == 'mousedown'){
6703 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6705 E.stopEvent(this.browserEvent);
6710 * Prevents the browsers default handling of the event.
6712 preventDefault : function(){
6713 if(this.browserEvent){
6714 E.preventDefault(this.browserEvent);
6719 isNavKeyPress : function(){
6720 var k = this.keyCode;
6721 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6722 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6725 isSpecialKey : function(){
6726 var k = this.keyCode;
6727 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6728 (k == 16) || (k == 17) ||
6729 (k >= 18 && k <= 20) ||
6730 (k >= 33 && k <= 35) ||
6731 (k >= 36 && k <= 39) ||
6732 (k >= 44 && k <= 45);
6735 * Cancels bubbling of the event.
6737 stopPropagation : function(){
6738 if(this.browserEvent){
6739 if(this.type == 'mousedown'){
6740 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6742 E.stopPropagation(this.browserEvent);
6747 * Gets the key code for the event.
6750 getCharCode : function(){
6751 return this.charCode || this.keyCode;
6755 * Returns a normalized keyCode for the event.
6756 * @return {Number} The key code
6758 getKey : function(){
6759 var k = this.keyCode || this.charCode;
6760 return Roo.isSafari ? (safariKeys[k] || k) : k;
6764 * Gets the x coordinate of the event.
6767 getPageX : function(){
6772 * Gets the y coordinate of the event.
6775 getPageY : function(){
6780 * Gets the time of the event.
6783 getTime : function(){
6784 if(this.browserEvent){
6785 return E.getTime(this.browserEvent);
6791 * Gets the page coordinates of the event.
6792 * @return {Array} The xy values like [x, y]
6799 * Gets the target for the event.
6800 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6801 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6802 search as a number or element (defaults to 10 || document.body)
6803 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6804 * @return {HTMLelement}
6806 getTarget : function(selector, maxDepth, returnEl){
6807 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6810 * Gets the related target.
6811 * @return {HTMLElement}
6813 getRelatedTarget : function(){
6814 if(this.browserEvent){
6815 return E.getRelatedTarget(this.browserEvent);
6821 * Normalizes mouse wheel delta across browsers
6822 * @return {Number} The delta
6824 getWheelDelta : function(){
6825 var e = this.browserEvent;
6827 if(e.wheelDelta){ /* IE/Opera. */
6828 delta = e.wheelDelta/120;
6829 }else if(e.detail){ /* Mozilla case. */
6830 delta = -e.detail/3;
6836 * Returns true if the control, meta, shift or alt key was pressed during this event.
6839 hasModifier : function(){
6840 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6844 * Returns true if the target of this event equals el or is a child of el
6845 * @param {String/HTMLElement/Element} el
6846 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6849 within : function(el, related){
6850 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6851 return t && Roo.fly(el).contains(t);
6854 getPoint : function(){
6855 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6859 return new Roo.EventObjectImpl();
6864 * Ext JS Library 1.1.1
6865 * Copyright(c) 2006-2007, Ext JS, LLC.
6867 * Originally Released Under LGPL - original licence link has changed is not relivant.
6870 * <script type="text/javascript">
6874 // was in Composite Element!??!?!
6877 var D = Roo.lib.Dom;
6878 var E = Roo.lib.Event;
6879 var A = Roo.lib.Anim;
6881 // local style camelizing for speed
6883 var camelRe = /(-[a-z])/gi;
6884 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6885 var view = document.defaultView;
6888 * @class Roo.Element
6889 * Represents an Element in the DOM.<br><br>
6892 var el = Roo.get("my-div");
6895 var el = getEl("my-div");
6897 // or with a DOM element
6898 var el = Roo.get(myDivElement);
6900 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6901 * each call instead of constructing a new one.<br><br>
6902 * <b>Animations</b><br />
6903 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6904 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6906 Option Default Description
6907 --------- -------- ---------------------------------------------
6908 duration .35 The duration of the animation in seconds
6909 easing easeOut The YUI easing method
6910 callback none A function to execute when the anim completes
6911 scope this The scope (this) of the callback function
6913 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6914 * manipulate the animation. Here's an example:
6916 var el = Roo.get("my-div");
6921 // default animation
6922 el.setWidth(100, true);
6924 // animation with some options set
6931 // using the "anim" property to get the Anim object
6937 el.setWidth(100, opt);
6939 if(opt.anim.isAnimated()){
6943 * <b> Composite (Collections of) Elements</b><br />
6944 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6945 * @constructor Create a new Element directly.
6946 * @param {String/HTMLElement} element
6947 * @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).
6949 Roo.Element = function(element, forceNew){
6950 var dom = typeof element == "string" ?
6951 document.getElementById(element) : element;
6952 if(!dom){ // invalid id/element
6956 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6957 return Roo.Element.cache[id];
6967 * The DOM element ID
6970 this.id = id || Roo.id(dom);
6973 var El = Roo.Element;
6977 * The element's default display mode (defaults to "")
6980 originalDisplay : "",
6984 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6989 * Sets the element's visibility mode. When setVisible() is called it
6990 * will use this to determine whether to set the visibility or the display property.
6991 * @param visMode Element.VISIBILITY or Element.DISPLAY
6992 * @return {Roo.Element} this
6994 setVisibilityMode : function(visMode){
6995 this.visibilityMode = visMode;
6999 * Convenience method for setVisibilityMode(Element.DISPLAY)
7000 * @param {String} display (optional) What to set display to when visible
7001 * @return {Roo.Element} this
7003 enableDisplayMode : function(display){
7004 this.setVisibilityMode(El.DISPLAY);
7005 if(typeof display != "undefined") this.originalDisplay = display;
7010 * 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)
7011 * @param {String} selector The simple selector to test
7012 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7013 search as a number or element (defaults to 10 || document.body)
7014 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7015 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7017 findParent : function(simpleSelector, maxDepth, returnEl){
7018 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7019 maxDepth = maxDepth || 50;
7020 if(typeof maxDepth != "number"){
7021 stopEl = Roo.getDom(maxDepth);
7024 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7025 if(dq.is(p, simpleSelector)){
7026 return returnEl ? Roo.get(p) : p;
7036 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7037 * @param {String} selector The simple selector to test
7038 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7039 search as a number or element (defaults to 10 || document.body)
7040 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7041 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7043 findParentNode : function(simpleSelector, maxDepth, returnEl){
7044 var p = Roo.fly(this.dom.parentNode, '_internal');
7045 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7049 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7050 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7051 * @param {String} selector The simple selector to test
7052 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7053 search as a number or element (defaults to 10 || document.body)
7054 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7056 up : function(simpleSelector, maxDepth){
7057 return this.findParentNode(simpleSelector, maxDepth, true);
7063 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7064 * @param {String} selector The simple selector to test
7065 * @return {Boolean} True if this element matches the selector, else false
7067 is : function(simpleSelector){
7068 return Roo.DomQuery.is(this.dom, simpleSelector);
7072 * Perform animation on this element.
7073 * @param {Object} args The YUI animation control args
7074 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7075 * @param {Function} onComplete (optional) Function to call when animation completes
7076 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7077 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7078 * @return {Roo.Element} this
7080 animate : function(args, duration, onComplete, easing, animType){
7081 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7086 * @private Internal animation call
7088 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7089 animType = animType || 'run';
7091 var anim = Roo.lib.Anim[animType](
7093 (opt.duration || defaultDur) || .35,
7094 (opt.easing || defaultEase) || 'easeOut',
7096 Roo.callback(cb, this);
7097 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7105 // private legacy anim prep
7106 preanim : function(a, i){
7107 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7111 * Removes worthless text nodes
7112 * @param {Boolean} forceReclean (optional) By default the element
7113 * keeps track if it has been cleaned already so
7114 * you can call this over and over. However, if you update the element and
7115 * need to force a reclean, you can pass true.
7117 clean : function(forceReclean){
7118 if(this.isCleaned && forceReclean !== true){
7122 var d = this.dom, n = d.firstChild, ni = -1;
7124 var nx = n.nextSibling;
7125 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7132 this.isCleaned = true;
7137 calcOffsetsTo : function(el){
7140 var restorePos = false;
7141 if(el.getStyle('position') == 'static'){
7142 el.position('relative');
7147 while(op && op != d && op.tagName != 'HTML'){
7150 op = op.offsetParent;
7153 el.position('static');
7159 * Scrolls this element into view within the passed container.
7160 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7161 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7162 * @return {Roo.Element} this
7164 scrollIntoView : function(container, hscroll){
7165 var c = Roo.getDom(container) || document.body;
7168 var o = this.calcOffsetsTo(c),
7171 b = t+el.offsetHeight,
7172 r = l+el.offsetWidth;
7174 var ch = c.clientHeight;
7175 var ct = parseInt(c.scrollTop, 10);
7176 var cl = parseInt(c.scrollLeft, 10);
7178 var cr = cl + c.clientWidth;
7186 if(hscroll !== false){
7190 c.scrollLeft = r-c.clientWidth;
7197 scrollChildIntoView : function(child, hscroll){
7198 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7202 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7203 * the new height may not be available immediately.
7204 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7205 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7206 * @param {Function} onComplete (optional) Function to call when animation completes
7207 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7208 * @return {Roo.Element} this
7210 autoHeight : function(animate, duration, onComplete, easing){
7211 var oldHeight = this.getHeight();
7213 this.setHeight(1); // force clipping
7214 setTimeout(function(){
7215 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7217 this.setHeight(height);
7219 if(typeof onComplete == "function"){
7223 this.setHeight(oldHeight); // restore original height
7224 this.setHeight(height, animate, duration, function(){
7226 if(typeof onComplete == "function") onComplete();
7227 }.createDelegate(this), easing);
7229 }.createDelegate(this), 0);
7234 * Returns true if this element is an ancestor of the passed element
7235 * @param {HTMLElement/String} el The element to check
7236 * @return {Boolean} True if this element is an ancestor of el, else false
7238 contains : function(el){
7239 if(!el){return false;}
7240 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7244 * Checks whether the element is currently visible using both visibility and display properties.
7245 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7246 * @return {Boolean} True if the element is currently visible, else false
7248 isVisible : function(deep) {
7249 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7250 if(deep !== true || !vis){
7253 var p = this.dom.parentNode;
7254 while(p && p.tagName.toLowerCase() != "body"){
7255 if(!Roo.fly(p, '_isVisible').isVisible()){
7264 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7265 * @param {String} selector The CSS selector
7266 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7267 * @return {CompositeElement/CompositeElementLite} The composite element
7269 select : function(selector, unique){
7270 return El.select(selector, unique, this.dom);
7274 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7275 * @param {String} selector The CSS selector
7276 * @return {Array} An array of the matched nodes
7278 query : function(selector, unique){
7279 return Roo.DomQuery.select(selector, this.dom);
7283 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7284 * @param {String} selector The CSS selector
7285 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7286 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7288 child : function(selector, returnDom){
7289 var n = Roo.DomQuery.selectNode(selector, this.dom);
7290 return returnDom ? n : Roo.get(n);
7294 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7295 * @param {String} selector The CSS selector
7296 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7297 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7299 down : function(selector, returnDom){
7300 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7301 return returnDom ? n : Roo.get(n);
7305 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7306 * @param {String} group The group the DD object is member of
7307 * @param {Object} config The DD config object
7308 * @param {Object} overrides An object containing methods to override/implement on the DD object
7309 * @return {Roo.dd.DD} The DD object
7311 initDD : function(group, config, overrides){
7312 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7313 return Roo.apply(dd, overrides);
7317 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7318 * @param {String} group The group the DDProxy object is member of
7319 * @param {Object} config The DDProxy config object
7320 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7321 * @return {Roo.dd.DDProxy} The DDProxy object
7323 initDDProxy : function(group, config, overrides){
7324 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7325 return Roo.apply(dd, overrides);
7329 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7330 * @param {String} group The group the DDTarget object is member of
7331 * @param {Object} config The DDTarget config object
7332 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7333 * @return {Roo.dd.DDTarget} The DDTarget object
7335 initDDTarget : function(group, config, overrides){
7336 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7337 return Roo.apply(dd, overrides);
7341 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7342 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7343 * @param {Boolean} visible Whether the element is visible
7344 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7345 * @return {Roo.Element} this
7347 setVisible : function(visible, animate){
7349 if(this.visibilityMode == El.DISPLAY){
7350 this.setDisplayed(visible);
7353 this.dom.style.visibility = visible ? "visible" : "hidden";
7356 // closure for composites
7358 var visMode = this.visibilityMode;
7360 this.setOpacity(.01);
7361 this.setVisible(true);
7363 this.anim({opacity: { to: (visible?1:0) }},
7364 this.preanim(arguments, 1),
7365 null, .35, 'easeIn', function(){
7367 if(visMode == El.DISPLAY){
7368 dom.style.display = "none";
7370 dom.style.visibility = "hidden";
7372 Roo.get(dom).setOpacity(1);
7380 * Returns true if display is not "none"
7383 isDisplayed : function() {
7384 return this.getStyle("display") != "none";
7388 * Toggles the element's visibility or display, depending on visibility mode.
7389 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7390 * @return {Roo.Element} this
7392 toggle : function(animate){
7393 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7398 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7399 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7400 * @return {Roo.Element} this
7402 setDisplayed : function(value) {
7403 if(typeof value == "boolean"){
7404 value = value ? this.originalDisplay : "none";
7406 this.setStyle("display", value);
7411 * Tries to focus the element. Any exceptions are caught and ignored.
7412 * @return {Roo.Element} this
7414 focus : function() {
7422 * Tries to blur the element. Any exceptions are caught and ignored.
7423 * @return {Roo.Element} this
7433 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7434 * @param {String/Array} className The CSS class to add, or an array of classes
7435 * @return {Roo.Element} this
7437 addClass : function(className){
7438 if(className instanceof Array){
7439 for(var i = 0, len = className.length; i < len; i++) {
7440 this.addClass(className[i]);
7443 if(className && !this.hasClass(className)){
7444 this.dom.className = this.dom.className + " " + className;
7451 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7452 * @param {String/Array} className The CSS class to add, or an array of classes
7453 * @return {Roo.Element} this
7455 radioClass : function(className){
7456 var siblings = this.dom.parentNode.childNodes;
7457 for(var i = 0; i < siblings.length; i++) {
7458 var s = siblings[i];
7459 if(s.nodeType == 1){
7460 Roo.get(s).removeClass(className);
7463 this.addClass(className);
7468 * Removes one or more CSS classes from the element.
7469 * @param {String/Array} className The CSS class to remove, or an array of classes
7470 * @return {Roo.Element} this
7472 removeClass : function(className){
7473 if(!className || !this.dom.className){
7476 if(className instanceof Array){
7477 for(var i = 0, len = className.length; i < len; i++) {
7478 this.removeClass(className[i]);
7481 if(this.hasClass(className)){
7482 var re = this.classReCache[className];
7484 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7485 this.classReCache[className] = re;
7487 this.dom.className =
7488 this.dom.className.replace(re, " ");
7498 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7499 * @param {String} className The CSS class to toggle
7500 * @return {Roo.Element} this
7502 toggleClass : function(className){
7503 if(this.hasClass(className)){
7504 this.removeClass(className);
7506 this.addClass(className);
7512 * Checks if the specified CSS class exists on this element's DOM node.
7513 * @param {String} className The CSS class to check for
7514 * @return {Boolean} True if the class exists, else false
7516 hasClass : function(className){
7517 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7521 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7522 * @param {String} oldClassName The CSS class to replace
7523 * @param {String} newClassName The replacement CSS class
7524 * @return {Roo.Element} this
7526 replaceClass : function(oldClassName, newClassName){
7527 this.removeClass(oldClassName);
7528 this.addClass(newClassName);
7533 * Returns an object with properties matching the styles requested.
7534 * For example, el.getStyles('color', 'font-size', 'width') might return
7535 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7536 * @param {String} style1 A style name
7537 * @param {String} style2 A style name
7538 * @param {String} etc.
7539 * @return {Object} The style object
7541 getStyles : function(){
7542 var a = arguments, len = a.length, r = {};
7543 for(var i = 0; i < len; i++){
7544 r[a[i]] = this.getStyle(a[i]);
7550 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7551 * @param {String} property The style property whose value is returned.
7552 * @return {String} The current value of the style property for this element.
7554 getStyle : function(){
7555 return view && view.getComputedStyle ?
7557 var el = this.dom, v, cs, camel;
7558 if(prop == 'float'){
7561 if(el.style && (v = el.style[prop])){
7564 if(cs = view.getComputedStyle(el, "")){
7565 if(!(camel = propCache[prop])){
7566 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7573 var el = this.dom, v, cs, camel;
7574 if(prop == 'opacity'){
7575 if(typeof el.style.filter == 'string'){
7576 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7578 var fv = parseFloat(m[1]);
7580 return fv ? fv / 100 : 0;
7585 }else if(prop == 'float'){
7586 prop = "styleFloat";
7588 if(!(camel = propCache[prop])){
7589 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7591 if(v = el.style[camel]){
7594 if(cs = el.currentStyle){
7602 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7603 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7604 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7605 * @return {Roo.Element} this
7607 setStyle : function(prop, value){
7608 if(typeof prop == "string"){
7610 if (prop == 'float') {
7611 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7616 if(!(camel = propCache[prop])){
7617 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7620 if(camel == 'opacity') {
7621 this.setOpacity(value);
7623 this.dom.style[camel] = value;
7626 for(var style in prop){
7627 if(typeof prop[style] != "function"){
7628 this.setStyle(style, prop[style]);
7636 * More flexible version of {@link #setStyle} for setting style properties.
7637 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7638 * a function which returns such a specification.
7639 * @return {Roo.Element} this
7641 applyStyles : function(style){
7642 Roo.DomHelper.applyStyles(this.dom, style);
7647 * 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).
7648 * @return {Number} The X position of the element
7651 return D.getX(this.dom);
7655 * 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).
7656 * @return {Number} The Y position of the element
7659 return D.getY(this.dom);
7663 * 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).
7664 * @return {Array} The XY position of the element
7667 return D.getXY(this.dom);
7671 * 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).
7672 * @param {Number} The X position of the element
7673 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7674 * @return {Roo.Element} this
7676 setX : function(x, animate){
7678 D.setX(this.dom, x);
7680 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7686 * 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).
7687 * @param {Number} The Y position of the element
7688 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7689 * @return {Roo.Element} this
7691 setY : function(y, animate){
7693 D.setY(this.dom, y);
7695 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7701 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7702 * @param {String} left The left CSS property value
7703 * @return {Roo.Element} this
7705 setLeft : function(left){
7706 this.setStyle("left", this.addUnits(left));
7711 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7712 * @param {String} top The top CSS property value
7713 * @return {Roo.Element} this
7715 setTop : function(top){
7716 this.setStyle("top", this.addUnits(top));
7721 * Sets the element's CSS right style.
7722 * @param {String} right The right CSS property value
7723 * @return {Roo.Element} this
7725 setRight : function(right){
7726 this.setStyle("right", this.addUnits(right));
7731 * Sets the element's CSS bottom style.
7732 * @param {String} bottom The bottom CSS property value
7733 * @return {Roo.Element} this
7735 setBottom : function(bottom){
7736 this.setStyle("bottom", this.addUnits(bottom));
7741 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7742 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7743 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7744 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7745 * @return {Roo.Element} this
7747 setXY : function(pos, animate){
7749 D.setXY(this.dom, pos);
7751 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7757 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7758 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7759 * @param {Number} x X value for new position (coordinates are page-based)
7760 * @param {Number} y Y value for new position (coordinates are page-based)
7761 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7762 * @return {Roo.Element} this
7764 setLocation : function(x, y, animate){
7765 this.setXY([x, y], this.preanim(arguments, 2));
7770 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7771 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7772 * @param {Number} x X value for new position (coordinates are page-based)
7773 * @param {Number} y Y value for new position (coordinates are page-based)
7774 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7775 * @return {Roo.Element} this
7777 moveTo : function(x, y, animate){
7778 this.setXY([x, y], this.preanim(arguments, 2));
7783 * Returns the region of the given element.
7784 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7785 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7787 getRegion : function(){
7788 return D.getRegion(this.dom);
7792 * Returns the offset height of the element
7793 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7794 * @return {Number} The element's height
7796 getHeight : function(contentHeight){
7797 var h = this.dom.offsetHeight || 0;
7798 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7802 * Returns the offset width of the element
7803 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7804 * @return {Number} The element's width
7806 getWidth : function(contentWidth){
7807 var w = this.dom.offsetWidth || 0;
7808 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7812 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7813 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7814 * if a height has not been set using CSS.
7817 getComputedHeight : function(){
7818 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7820 h = parseInt(this.getStyle('height'), 10) || 0;
7821 if(!this.isBorderBox()){
7822 h += this.getFrameWidth('tb');
7829 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7830 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7831 * if a width has not been set using CSS.
7834 getComputedWidth : function(){
7835 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7837 w = parseInt(this.getStyle('width'), 10) || 0;
7838 if(!this.isBorderBox()){
7839 w += this.getFrameWidth('lr');
7846 * Returns the size of the element.
7847 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7848 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7850 getSize : function(contentSize){
7851 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7855 * Returns the width and height of the viewport.
7856 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7858 getViewSize : function(){
7859 var d = this.dom, doc = document, aw = 0, ah = 0;
7860 if(d == doc || d == doc.body){
7861 return {width : D.getViewWidth(), height: D.getViewHeight()};
7864 width : d.clientWidth,
7865 height: d.clientHeight
7871 * Returns the value of the "value" attribute
7872 * @param {Boolean} asNumber true to parse the value as a number
7873 * @return {String/Number}
7875 getValue : function(asNumber){
7876 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7880 adjustWidth : function(width){
7881 if(typeof width == "number"){
7882 if(this.autoBoxAdjust && !this.isBorderBox()){
7883 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7893 adjustHeight : function(height){
7894 if(typeof height == "number"){
7895 if(this.autoBoxAdjust && !this.isBorderBox()){
7896 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7906 * Set the width of the element
7907 * @param {Number} width The new width
7908 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7909 * @return {Roo.Element} this
7911 setWidth : function(width, animate){
7912 width = this.adjustWidth(width);
7914 this.dom.style.width = this.addUnits(width);
7916 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7922 * Set the height of the element
7923 * @param {Number} height The new height
7924 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7925 * @return {Roo.Element} this
7927 setHeight : function(height, animate){
7928 height = this.adjustHeight(height);
7930 this.dom.style.height = this.addUnits(height);
7932 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7938 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7939 * @param {Number} width The new width
7940 * @param {Number} height The new height
7941 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7942 * @return {Roo.Element} this
7944 setSize : function(width, height, animate){
7945 if(typeof width == "object"){ // in case of object from getSize()
7946 height = width.height; width = width.width;
7948 width = this.adjustWidth(width); height = this.adjustHeight(height);
7950 this.dom.style.width = this.addUnits(width);
7951 this.dom.style.height = this.addUnits(height);
7953 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7959 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7960 * @param {Number} x X value for new position (coordinates are page-based)
7961 * @param {Number} y Y value for new position (coordinates are page-based)
7962 * @param {Number} width The new width
7963 * @param {Number} height The new height
7964 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7965 * @return {Roo.Element} this
7967 setBounds : function(x, y, width, height, animate){
7969 this.setSize(width, height);
7970 this.setLocation(x, y);
7972 width = this.adjustWidth(width); height = this.adjustHeight(height);
7973 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7974 this.preanim(arguments, 4), 'motion');
7980 * 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.
7981 * @param {Roo.lib.Region} region The region to fill
7982 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7983 * @return {Roo.Element} this
7985 setRegion : function(region, animate){
7986 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7991 * Appends an event handler
7993 * @param {String} eventName The type of event to append
7994 * @param {Function} fn The method the event invokes
7995 * @param {Object} scope (optional) The scope (this object) of the fn
7996 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7998 addListener : function(eventName, fn, scope, options){
8000 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8005 * Removes an event handler from this element
8006 * @param {String} eventName the type of event to remove
8007 * @param {Function} fn the method the event invokes
8008 * @return {Roo.Element} this
8010 removeListener : function(eventName, fn){
8011 Roo.EventManager.removeListener(this.dom, eventName, fn);
8016 * Removes all previous added listeners from this element
8017 * @return {Roo.Element} this
8019 removeAllListeners : function(){
8020 E.purgeElement(this.dom);
8024 relayEvent : function(eventName, observable){
8025 this.on(eventName, function(e){
8026 observable.fireEvent(eventName, e);
8031 * Set the opacity of the element
8032 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8033 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8034 * @return {Roo.Element} this
8036 setOpacity : function(opacity, animate){
8038 var s = this.dom.style;
8041 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8042 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8044 s.opacity = opacity;
8047 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8053 * Gets the left X coordinate
8054 * @param {Boolean} local True to get the local css position instead of page coordinate
8057 getLeft : function(local){
8061 return parseInt(this.getStyle("left"), 10) || 0;
8066 * Gets the right X coordinate of the element (element X position + element width)
8067 * @param {Boolean} local True to get the local css position instead of page coordinate
8070 getRight : function(local){
8072 return this.getX() + this.getWidth();
8074 return (this.getLeft(true) + this.getWidth()) || 0;
8079 * Gets the top Y coordinate
8080 * @param {Boolean} local True to get the local css position instead of page coordinate
8083 getTop : function(local) {
8087 return parseInt(this.getStyle("top"), 10) || 0;
8092 * Gets the bottom Y coordinate of the element (element Y position + element height)
8093 * @param {Boolean} local True to get the local css position instead of page coordinate
8096 getBottom : function(local){
8098 return this.getY() + this.getHeight();
8100 return (this.getTop(true) + this.getHeight()) || 0;
8105 * Initializes positioning on this element. If a desired position is not passed, it will make the
8106 * the element positioned relative IF it is not already positioned.
8107 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8108 * @param {Number} zIndex (optional) The zIndex to apply
8109 * @param {Number} x (optional) Set the page X position
8110 * @param {Number} y (optional) Set the page Y position
8112 position : function(pos, zIndex, x, y){
8114 if(this.getStyle('position') == 'static'){
8115 this.setStyle('position', 'relative');
8118 this.setStyle("position", pos);
8121 this.setStyle("z-index", zIndex);
8123 if(x !== undefined && y !== undefined){
8125 }else if(x !== undefined){
8127 }else if(y !== undefined){
8133 * Clear positioning back to the default when the document was loaded
8134 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8135 * @return {Roo.Element} this
8137 clearPositioning : function(value){
8145 "position" : "static"
8151 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8152 * snapshot before performing an update and then restoring the element.
8155 getPositioning : function(){
8156 var l = this.getStyle("left");
8157 var t = this.getStyle("top");
8159 "position" : this.getStyle("position"),
8161 "right" : l ? "" : this.getStyle("right"),
8163 "bottom" : t ? "" : this.getStyle("bottom"),
8164 "z-index" : this.getStyle("z-index")
8169 * Gets the width of the border(s) for the specified side(s)
8170 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8171 * passing lr would get the border (l)eft width + the border (r)ight width.
8172 * @return {Number} The width of the sides passed added together
8174 getBorderWidth : function(side){
8175 return this.addStyles(side, El.borders);
8179 * Gets the width of the padding(s) for the specified side(s)
8180 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8181 * passing lr would get the padding (l)eft + the padding (r)ight.
8182 * @return {Number} The padding of the sides passed added together
8184 getPadding : function(side){
8185 return this.addStyles(side, El.paddings);
8189 * Set positioning with an object returned by getPositioning().
8190 * @param {Object} posCfg
8191 * @return {Roo.Element} this
8193 setPositioning : function(pc){
8194 this.applyStyles(pc);
8195 if(pc.right == "auto"){
8196 this.dom.style.right = "";
8198 if(pc.bottom == "auto"){
8199 this.dom.style.bottom = "";
8205 fixDisplay : function(){
8206 if(this.getStyle("display") == "none"){
8207 this.setStyle("visibility", "hidden");
8208 this.setStyle("display", this.originalDisplay); // first try reverting to default
8209 if(this.getStyle("display") == "none"){ // if that fails, default to block
8210 this.setStyle("display", "block");
8216 * Quick set left and top adding default units
8217 * @param {String} left The left CSS property value
8218 * @param {String} top The top CSS property value
8219 * @return {Roo.Element} this
8221 setLeftTop : function(left, top){
8222 this.dom.style.left = this.addUnits(left);
8223 this.dom.style.top = this.addUnits(top);
8228 * Move this element relative to its current position.
8229 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8230 * @param {Number} distance How far to move the element in pixels
8231 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8232 * @return {Roo.Element} this
8234 move : function(direction, distance, animate){
8235 var xy = this.getXY();
8236 direction = direction.toLowerCase();
8240 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8244 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8249 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8254 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8261 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8262 * @return {Roo.Element} this
8265 if(!this.isClipped){
8266 this.isClipped = true;
8267 this.originalClip = {
8268 "o": this.getStyle("overflow"),
8269 "x": this.getStyle("overflow-x"),
8270 "y": this.getStyle("overflow-y")
8272 this.setStyle("overflow", "hidden");
8273 this.setStyle("overflow-x", "hidden");
8274 this.setStyle("overflow-y", "hidden");
8280 * Return clipping (overflow) to original clipping before clip() was called
8281 * @return {Roo.Element} this
8283 unclip : function(){
8285 this.isClipped = false;
8286 var o = this.originalClip;
8287 if(o.o){this.setStyle("overflow", o.o);}
8288 if(o.x){this.setStyle("overflow-x", o.x);}
8289 if(o.y){this.setStyle("overflow-y", o.y);}
8296 * Gets the x,y coordinates specified by the anchor position on the element.
8297 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8298 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8299 * {width: (target width), height: (target height)} (defaults to the element's current size)
8300 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8301 * @return {Array} [x, y] An array containing the element's x and y coordinates
8303 getAnchorXY : function(anchor, local, s){
8304 //Passing a different size is useful for pre-calculating anchors,
8305 //especially for anchored animations that change the el size.
8307 var w, h, vp = false;
8310 if(d == document.body || d == document){
8312 w = D.getViewWidth(); h = D.getViewHeight();
8314 w = this.getWidth(); h = this.getHeight();
8317 w = s.width; h = s.height;
8319 var x = 0, y = 0, r = Math.round;
8320 switch((anchor || "tl").toLowerCase()){
8362 var sc = this.getScroll();
8363 return [x + sc.left, y + sc.top];
8365 //Add the element's offset xy
8366 var o = this.getXY();
8367 return [x+o[0], y+o[1]];
8371 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8372 * supported position values.
8373 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8374 * @param {String} position The position to align to.
8375 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8376 * @return {Array} [x, y]
8378 getAlignToXY : function(el, p, o){
8382 throw "Element.alignTo with an element that doesn't exist";
8384 var c = false; //constrain to viewport
8385 var p1 = "", p2 = "";
8392 }else if(p.indexOf("-") == -1){
8395 p = p.toLowerCase();
8396 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8398 throw "Element.alignTo with an invalid alignment " + p;
8400 p1 = m[1]; p2 = m[2]; c = !!m[3];
8402 //Subtract the aligned el's internal xy from the target's offset xy
8403 //plus custom offset to get the aligned el's new offset xy
8404 var a1 = this.getAnchorXY(p1, true);
8405 var a2 = el.getAnchorXY(p2, false);
8406 var x = a2[0] - a1[0] + o[0];
8407 var y = a2[1] - a1[1] + o[1];
8409 //constrain the aligned el to viewport if necessary
8410 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8411 // 5px of margin for ie
8412 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8414 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8415 //perpendicular to the vp border, allow the aligned el to slide on that border,
8416 //otherwise swap the aligned el to the opposite border of the target.
8417 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8418 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8419 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8420 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8423 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8424 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8426 if((x+w) > dw + scrollX){
8427 x = swapX ? r.left-w : dw+scrollX-w;
8430 x = swapX ? r.right : scrollX;
8432 if((y+h) > dh + scrollY){
8433 y = swapY ? r.top-h : dh+scrollY-h;
8436 y = swapY ? r.bottom : scrollY;
8443 getConstrainToXY : function(){
8444 var os = {top:0, left:0, bottom:0, right: 0};
8446 return function(el, local, offsets, proposedXY){
8448 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8450 var vw, vh, vx = 0, vy = 0;
8451 if(el.dom == document.body || el.dom == document){
8452 vw = Roo.lib.Dom.getViewWidth();
8453 vh = Roo.lib.Dom.getViewHeight();
8455 vw = el.dom.clientWidth;
8456 vh = el.dom.clientHeight;
8458 var vxy = el.getXY();
8464 var s = el.getScroll();
8466 vx += offsets.left + s.left;
8467 vy += offsets.top + s.top;
8469 vw -= offsets.right;
8470 vh -= offsets.bottom;
8475 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8476 var x = xy[0], y = xy[1];
8477 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8479 // only move it if it needs it
8482 // first validate right/bottom
8491 // then make sure top/left isn't negative
8500 return moved ? [x, y] : false;
8505 adjustForConstraints : function(xy, parent, offsets){
8506 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8510 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8511 * document it aligns it to the viewport.
8512 * The position parameter is optional, and can be specified in any one of the following formats:
8514 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8515 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8516 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8517 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8518 * <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
8519 * element's anchor point, and the second value is used as the target's anchor point.</li>
8521 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8522 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8523 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8524 * that specified in order to enforce the viewport constraints.
8525 * Following are all of the supported anchor positions:
8528 ----- -----------------------------
8529 tl The top left corner (default)
8530 t The center of the top edge
8531 tr The top right corner
8532 l The center of the left edge
8533 c In the center of the element
8534 r The center of the right edge
8535 bl The bottom left corner
8536 b The center of the bottom edge
8537 br The bottom right corner
8541 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8542 el.alignTo("other-el");
8544 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8545 el.alignTo("other-el", "tr?");
8547 // align the bottom right corner of el with the center left edge of other-el
8548 el.alignTo("other-el", "br-l?");
8550 // align the center of el with the bottom left corner of other-el and
8551 // adjust the x position by -6 pixels (and the y position by 0)
8552 el.alignTo("other-el", "c-bl", [-6, 0]);
8554 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8555 * @param {String} position The position to align to.
8556 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8557 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8558 * @return {Roo.Element} this
8560 alignTo : function(element, position, offsets, animate){
8561 var xy = this.getAlignToXY(element, position, offsets);
8562 this.setXY(xy, this.preanim(arguments, 3));
8567 * Anchors an element to another element and realigns it when the window is resized.
8568 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8569 * @param {String} position The position to align to.
8570 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8571 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8572 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8573 * is a number, it is used as the buffer delay (defaults to 50ms).
8574 * @param {Function} callback The function to call after the animation finishes
8575 * @return {Roo.Element} this
8577 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8578 var action = function(){
8579 this.alignTo(el, alignment, offsets, animate);
8580 Roo.callback(callback, this);
8582 Roo.EventManager.onWindowResize(action, this);
8583 var tm = typeof monitorScroll;
8584 if(tm != 'undefined'){
8585 Roo.EventManager.on(window, 'scroll', action, this,
8586 {buffer: tm == 'number' ? monitorScroll : 50});
8588 action.call(this); // align immediately
8592 * Clears any opacity settings from this element. Required in some cases for IE.
8593 * @return {Roo.Element} this
8595 clearOpacity : function(){
8596 if (window.ActiveXObject) {
8597 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8598 this.dom.style.filter = "";
8601 this.dom.style.opacity = "";
8602 this.dom.style["-moz-opacity"] = "";
8603 this.dom.style["-khtml-opacity"] = "";
8609 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8610 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8611 * @return {Roo.Element} this
8613 hide : function(animate){
8614 this.setVisible(false, this.preanim(arguments, 0));
8619 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8620 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8621 * @return {Roo.Element} this
8623 show : function(animate){
8624 this.setVisible(true, this.preanim(arguments, 0));
8629 * @private Test if size has a unit, otherwise appends the default
8631 addUnits : function(size){
8632 return Roo.Element.addUnits(size, this.defaultUnit);
8636 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8637 * @return {Roo.Element} this
8639 beginMeasure : function(){
8641 if(el.offsetWidth || el.offsetHeight){
8642 return this; // offsets work already
8645 var p = this.dom, b = document.body; // start with this element
8646 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8647 var pe = Roo.get(p);
8648 if(pe.getStyle('display') == 'none'){
8649 changed.push({el: p, visibility: pe.getStyle("visibility")});
8650 p.style.visibility = "hidden";
8651 p.style.display = "block";
8655 this._measureChanged = changed;
8661 * Restores displays to before beginMeasure was called
8662 * @return {Roo.Element} this
8664 endMeasure : function(){
8665 var changed = this._measureChanged;
8667 for(var i = 0, len = changed.length; i < len; i++) {
8669 r.el.style.visibility = r.visibility;
8670 r.el.style.display = "none";
8672 this._measureChanged = null;
8678 * Update the innerHTML of this element, optionally searching for and processing scripts
8679 * @param {String} html The new HTML
8680 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8681 * @param {Function} callback For async script loading you can be noticed when the update completes
8682 * @return {Roo.Element} this
8684 update : function(html, loadScripts, callback){
8685 if(typeof html == "undefined"){
8688 if(loadScripts !== true){
8689 this.dom.innerHTML = html;
8690 if(typeof callback == "function"){
8698 html += '<span id="' + id + '"></span>';
8700 E.onAvailable(id, function(){
8701 var hd = document.getElementsByTagName("head")[0];
8702 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8703 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8704 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8707 while(match = re.exec(html)){
8708 var attrs = match[1];
8709 var srcMatch = attrs ? attrs.match(srcRe) : false;
8710 if(srcMatch && srcMatch[2]){
8711 var s = document.createElement("script");
8712 s.src = srcMatch[2];
8713 var typeMatch = attrs.match(typeRe);
8714 if(typeMatch && typeMatch[2]){
8715 s.type = typeMatch[2];
8718 }else if(match[2] && match[2].length > 0){
8719 if(window.execScript) {
8720 window.execScript(match[2]);
8728 window.eval(match[2]);
8732 var el = document.getElementById(id);
8733 if(el){el.parentNode.removeChild(el);}
8734 if(typeof callback == "function"){
8738 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8743 * Direct access to the UpdateManager update() method (takes the same parameters).
8744 * @param {String/Function} url The url for this request or a function to call to get the url
8745 * @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}
8746 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8747 * @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.
8748 * @return {Roo.Element} this
8751 var um = this.getUpdateManager();
8752 um.update.apply(um, arguments);
8757 * Gets this element's UpdateManager
8758 * @return {Roo.UpdateManager} The UpdateManager
8760 getUpdateManager : function(){
8761 if(!this.updateManager){
8762 this.updateManager = new Roo.UpdateManager(this);
8764 return this.updateManager;
8768 * Disables text selection for this element (normalized across browsers)
8769 * @return {Roo.Element} this
8771 unselectable : function(){
8772 this.dom.unselectable = "on";
8773 this.swallowEvent("selectstart", true);
8774 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8775 this.addClass("x-unselectable");
8780 * Calculates the x, y to center this element on the screen
8781 * @return {Array} The x, y values [x, y]
8783 getCenterXY : function(){
8784 return this.getAlignToXY(document, 'c-c');
8788 * Centers the Element in either the viewport, or another Element.
8789 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8791 center : function(centerIn){
8792 this.alignTo(centerIn || document, 'c-c');
8797 * Tests various css rules/browsers to determine if this element uses a border box
8800 isBorderBox : function(){
8801 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8805 * Return a box {x, y, width, height} that can be used to set another elements
8806 * size/location to match this element.
8807 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8808 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8809 * @return {Object} box An object in the format {x, y, width, height}
8811 getBox : function(contentBox, local){
8816 var left = parseInt(this.getStyle("left"), 10) || 0;
8817 var top = parseInt(this.getStyle("top"), 10) || 0;
8820 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8822 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8824 var l = this.getBorderWidth("l")+this.getPadding("l");
8825 var r = this.getBorderWidth("r")+this.getPadding("r");
8826 var t = this.getBorderWidth("t")+this.getPadding("t");
8827 var b = this.getBorderWidth("b")+this.getPadding("b");
8828 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)};
8830 bx.right = bx.x + bx.width;
8831 bx.bottom = bx.y + bx.height;
8836 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8837 for more information about the sides.
8838 * @param {String} sides
8841 getFrameWidth : function(sides, onlyContentBox){
8842 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8846 * 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.
8847 * @param {Object} box The box to fill {x, y, width, height}
8848 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8849 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8850 * @return {Roo.Element} this
8852 setBox : function(box, adjust, animate){
8853 var w = box.width, h = box.height;
8854 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8855 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8856 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8858 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8863 * Forces the browser to repaint this element
8864 * @return {Roo.Element} this
8866 repaint : function(){
8868 this.addClass("x-repaint");
8869 setTimeout(function(){
8870 Roo.get(dom).removeClass("x-repaint");
8876 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8877 * then it returns the calculated width of the sides (see getPadding)
8878 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8879 * @return {Object/Number}
8881 getMargins : function(side){
8884 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8885 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8886 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8887 right: parseInt(this.getStyle("margin-right"), 10) || 0
8890 return this.addStyles(side, El.margins);
8895 addStyles : function(sides, styles){
8897 for(var i = 0, len = sides.length; i < len; i++){
8898 v = this.getStyle(styles[sides.charAt(i)]);
8900 w = parseInt(v, 10);
8908 * Creates a proxy element of this element
8909 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8910 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8911 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8912 * @return {Roo.Element} The new proxy element
8914 createProxy : function(config, renderTo, matchBox){
8916 renderTo = Roo.getDom(renderTo);
8918 renderTo = document.body;
8920 config = typeof config == "object" ?
8921 config : {tag : "div", cls: config};
8922 var proxy = Roo.DomHelper.append(renderTo, config, true);
8924 proxy.setBox(this.getBox());
8930 * Puts a mask over this element to disable user interaction. Requires core.css.
8931 * This method can only be applied to elements which accept child nodes.
8932 * @param {String} msg (optional) A message to display in the mask
8933 * @param {String} msgCls (optional) A css class to apply to the msg element
8934 * @return {Element} The mask element
8936 mask : function(msg, msgCls)
8938 if(this.getStyle("position") == "static"){
8939 this.setStyle("position", "relative");
8942 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8944 this.addClass("x-masked");
8945 this._mask.setDisplayed(true);
8950 while (dom && dom.style) {
8951 if (!isNaN(parseInt(dom.style.zIndex))) {
8952 z = Math.max(z, parseInt(dom.style.zIndex));
8954 dom = dom.parentNode;
8956 // if we are masking the body - then it hides everything..
8957 if (this.dom == document.body) {
8959 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
8960 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
8963 if(typeof msg == 'string'){
8965 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8967 var mm = this._maskMsg;
8968 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8969 mm.dom.firstChild.innerHTML = msg;
8970 mm.setDisplayed(true);
8972 mm.setStyle('z-index', z + 102);
8974 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8975 this._mask.setHeight(this.getHeight());
8977 this._mask.setStyle('z-index', z + 100);
8983 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8984 * it is cached for reuse.
8986 unmask : function(removeEl){
8988 if(removeEl === true){
8989 this._mask.remove();
8992 this._maskMsg.remove();
8993 delete this._maskMsg;
8996 this._mask.setDisplayed(false);
8998 this._maskMsg.setDisplayed(false);
9002 this.removeClass("x-masked");
9006 * Returns true if this element is masked
9009 isMasked : function(){
9010 return this._mask && this._mask.isVisible();
9014 * Creates an iframe shim for this element to keep selects and other windowed objects from
9016 * @return {Roo.Element} The new shim element
9018 createShim : function(){
9019 var el = document.createElement('iframe');
9020 el.frameBorder = 'no';
9021 el.className = 'roo-shim';
9022 if(Roo.isIE && Roo.isSecure){
9023 el.src = Roo.SSL_SECURE_URL;
9025 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9026 shim.autoBoxAdjust = false;
9031 * Removes this element from the DOM and deletes it from the cache
9033 remove : function(){
9034 if(this.dom.parentNode){
9035 this.dom.parentNode.removeChild(this.dom);
9037 delete El.cache[this.dom.id];
9041 * Sets up event handlers to add and remove a css class when the mouse is over this element
9042 * @param {String} className
9043 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9044 * mouseout events for children elements
9045 * @return {Roo.Element} this
9047 addClassOnOver : function(className, preventFlicker){
9048 this.on("mouseover", function(){
9049 Roo.fly(this, '_internal').addClass(className);
9051 var removeFn = function(e){
9052 if(preventFlicker !== true || !e.within(this, true)){
9053 Roo.fly(this, '_internal').removeClass(className);
9056 this.on("mouseout", removeFn, this.dom);
9061 * Sets up event handlers to add and remove a css class when this element has the focus
9062 * @param {String} className
9063 * @return {Roo.Element} this
9065 addClassOnFocus : function(className){
9066 this.on("focus", function(){
9067 Roo.fly(this, '_internal').addClass(className);
9069 this.on("blur", function(){
9070 Roo.fly(this, '_internal').removeClass(className);
9075 * 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)
9076 * @param {String} className
9077 * @return {Roo.Element} this
9079 addClassOnClick : function(className){
9081 this.on("mousedown", function(){
9082 Roo.fly(dom, '_internal').addClass(className);
9083 var d = Roo.get(document);
9084 var fn = function(){
9085 Roo.fly(dom, '_internal').removeClass(className);
9086 d.removeListener("mouseup", fn);
9088 d.on("mouseup", fn);
9094 * Stops the specified event from bubbling and optionally prevents the default action
9095 * @param {String} eventName
9096 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9097 * @return {Roo.Element} this
9099 swallowEvent : function(eventName, preventDefault){
9100 var fn = function(e){
9101 e.stopPropagation();
9106 if(eventName instanceof Array){
9107 for(var i = 0, len = eventName.length; i < len; i++){
9108 this.on(eventName[i], fn);
9112 this.on(eventName, fn);
9119 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9122 * Sizes this element to its parent element's dimensions performing
9123 * neccessary box adjustments.
9124 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9125 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9126 * @return {Roo.Element} this
9128 fitToParent : function(monitorResize, targetParent) {
9129 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9130 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9131 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9134 var p = Roo.get(targetParent || this.dom.parentNode);
9135 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9136 if (monitorResize === true) {
9137 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9138 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9144 * Gets the next sibling, skipping text nodes
9145 * @return {HTMLElement} The next sibling or null
9147 getNextSibling : function(){
9148 var n = this.dom.nextSibling;
9149 while(n && n.nodeType != 1){
9156 * Gets the previous sibling, skipping text nodes
9157 * @return {HTMLElement} The previous sibling or null
9159 getPrevSibling : function(){
9160 var n = this.dom.previousSibling;
9161 while(n && n.nodeType != 1){
9162 n = n.previousSibling;
9169 * Appends the passed element(s) to this element
9170 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9171 * @return {Roo.Element} this
9173 appendChild: function(el){
9180 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9181 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9182 * automatically generated with the specified attributes.
9183 * @param {HTMLElement} insertBefore (optional) a child element of this element
9184 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9185 * @return {Roo.Element} The new child element
9187 createChild: function(config, insertBefore, returnDom){
9188 config = config || {tag:'div'};
9190 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9192 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9196 * Appends this element to the passed element
9197 * @param {String/HTMLElement/Element} el The new parent element
9198 * @return {Roo.Element} this
9200 appendTo: function(el){
9201 el = Roo.getDom(el);
9202 el.appendChild(this.dom);
9207 * Inserts this element before the passed element in the DOM
9208 * @param {String/HTMLElement/Element} el The element to insert before
9209 * @return {Roo.Element} this
9211 insertBefore: function(el){
9212 el = Roo.getDom(el);
9213 el.parentNode.insertBefore(this.dom, el);
9218 * Inserts this element after the passed element in the DOM
9219 * @param {String/HTMLElement/Element} el The element to insert after
9220 * @return {Roo.Element} this
9222 insertAfter: function(el){
9223 el = Roo.getDom(el);
9224 el.parentNode.insertBefore(this.dom, el.nextSibling);
9229 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9230 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9231 * @return {Roo.Element} The new child
9233 insertFirst: function(el, returnDom){
9235 if(typeof el == 'object' && !el.nodeType){ // dh config
9236 return this.createChild(el, this.dom.firstChild, returnDom);
9238 el = Roo.getDom(el);
9239 this.dom.insertBefore(el, this.dom.firstChild);
9240 return !returnDom ? Roo.get(el) : el;
9245 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9246 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9247 * @param {String} where (optional) 'before' or 'after' defaults to before
9248 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9249 * @return {Roo.Element} the inserted Element
9251 insertSibling: function(el, where, returnDom){
9252 where = where ? where.toLowerCase() : 'before';
9254 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9256 if(typeof el == 'object' && !el.nodeType){ // dh config
9257 if(where == 'after' && !this.dom.nextSibling){
9258 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9260 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9264 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9265 where == 'before' ? this.dom : this.dom.nextSibling);
9274 * Creates and wraps this element with another element
9275 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9276 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9277 * @return {HTMLElement/Element} The newly created wrapper element
9279 wrap: function(config, returnDom){
9281 config = {tag: "div"};
9283 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9284 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9289 * Replaces the passed element with this element
9290 * @param {String/HTMLElement/Element} el The element to replace
9291 * @return {Roo.Element} this
9293 replace: function(el){
9295 this.insertBefore(el);
9301 * Inserts an html fragment into this element
9302 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9303 * @param {String} html The HTML fragment
9304 * @param {Boolean} returnEl True to return an Roo.Element
9305 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9307 insertHtml : function(where, html, returnEl){
9308 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9309 return returnEl ? Roo.get(el) : el;
9313 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9314 * @param {Object} o The object with the attributes
9315 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9316 * @return {Roo.Element} this
9318 set : function(o, useSet){
9320 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9322 if(attr == "style" || typeof o[attr] == "function") continue;
9324 el.className = o["cls"];
9326 if(useSet) el.setAttribute(attr, o[attr]);
9327 else el[attr] = o[attr];
9331 Roo.DomHelper.applyStyles(el, o.style);
9337 * Convenience method for constructing a KeyMap
9338 * @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:
9339 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9340 * @param {Function} fn The function to call
9341 * @param {Object} scope (optional) The scope of the function
9342 * @return {Roo.KeyMap} The KeyMap created
9344 addKeyListener : function(key, fn, scope){
9346 if(typeof key != "object" || key instanceof Array){
9362 return new Roo.KeyMap(this, config);
9366 * Creates a KeyMap for this element
9367 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9368 * @return {Roo.KeyMap} The KeyMap created
9370 addKeyMap : function(config){
9371 return new Roo.KeyMap(this, config);
9375 * Returns true if this element is scrollable.
9378 isScrollable : function(){
9380 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9384 * 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().
9385 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9386 * @param {Number} value The new scroll value
9387 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9388 * @return {Element} this
9391 scrollTo : function(side, value, animate){
9392 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9394 this.dom[prop] = value;
9396 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9397 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9403 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9404 * within this element's scrollable range.
9405 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9406 * @param {Number} distance How far to scroll the element in pixels
9407 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9408 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9409 * was scrolled as far as it could go.
9411 scroll : function(direction, distance, animate){
9412 if(!this.isScrollable()){
9416 var l = el.scrollLeft, t = el.scrollTop;
9417 var w = el.scrollWidth, h = el.scrollHeight;
9418 var cw = el.clientWidth, ch = el.clientHeight;
9419 direction = direction.toLowerCase();
9420 var scrolled = false;
9421 var a = this.preanim(arguments, 2);
9426 var v = Math.min(l + distance, w-cw);
9427 this.scrollTo("left", v, a);
9434 var v = Math.max(l - distance, 0);
9435 this.scrollTo("left", v, a);
9443 var v = Math.max(t - distance, 0);
9444 this.scrollTo("top", v, a);
9452 var v = Math.min(t + distance, h-ch);
9453 this.scrollTo("top", v, a);
9462 * Translates the passed page coordinates into left/top css values for this element
9463 * @param {Number/Array} x The page x or an array containing [x, y]
9464 * @param {Number} y The page y
9465 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9467 translatePoints : function(x, y){
9468 if(typeof x == 'object' || x instanceof Array){
9471 var p = this.getStyle('position');
9472 var o = this.getXY();
9474 var l = parseInt(this.getStyle('left'), 10);
9475 var t = parseInt(this.getStyle('top'), 10);
9478 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9481 t = (p == "relative") ? 0 : this.dom.offsetTop;
9484 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9488 * Returns the current scroll position of the element.
9489 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9491 getScroll : function(){
9492 var d = this.dom, doc = document;
9493 if(d == doc || d == doc.body){
9494 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9495 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9496 return {left: l, top: t};
9498 return {left: d.scrollLeft, top: d.scrollTop};
9503 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9504 * are convert to standard 6 digit hex color.
9505 * @param {String} attr The css attribute
9506 * @param {String} defaultValue The default value to use when a valid color isn't found
9507 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9510 getColor : function(attr, defaultValue, prefix){
9511 var v = this.getStyle(attr);
9512 if(!v || v == "transparent" || v == "inherit") {
9513 return defaultValue;
9515 var color = typeof prefix == "undefined" ? "#" : prefix;
9516 if(v.substr(0, 4) == "rgb("){
9517 var rvs = v.slice(4, v.length -1).split(",");
9518 for(var i = 0; i < 3; i++){
9519 var h = parseInt(rvs[i]).toString(16);
9526 if(v.substr(0, 1) == "#"){
9528 for(var i = 1; i < 4; i++){
9529 var c = v.charAt(i);
9532 }else if(v.length == 7){
9533 color += v.substr(1);
9537 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9541 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9542 * gradient background, rounded corners and a 4-way shadow.
9543 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9544 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9545 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9546 * @return {Roo.Element} this
9548 boxWrap : function(cls){
9549 cls = cls || 'x-box';
9550 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9551 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9556 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9557 * @param {String} namespace The namespace in which to look for the attribute
9558 * @param {String} name The attribute name
9559 * @return {String} The attribute value
9561 getAttributeNS : Roo.isIE ? function(ns, name){
9563 var type = typeof d[ns+":"+name];
9564 if(type != 'undefined' && type != 'unknown'){
9565 return d[ns+":"+name];
9568 } : function(ns, name){
9570 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9575 * Sets or Returns the value the dom attribute value
9576 * @param {String} name The attribute name
9577 * @param {String} value (optional) The value to set the attribute to
9578 * @return {String} The attribute value
9580 attr : function(name){
9581 if (arguments.length > 1) {
9582 this.dom.setAttribute(name, arguments[1]);
9583 return arguments[1];
9585 if (!this.dom.hasAttribute(name)) {
9588 return this.dom.getAttribute(name);
9595 var ep = El.prototype;
9598 * Appends an event handler (Shorthand for addListener)
9599 * @param {String} eventName The type of event to append
9600 * @param {Function} fn The method the event invokes
9601 * @param {Object} scope (optional) The scope (this object) of the fn
9602 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9605 ep.on = ep.addListener;
9607 ep.mon = ep.addListener;
9610 * Removes an event handler from this element (shorthand for removeListener)
9611 * @param {String} eventName the type of event to remove
9612 * @param {Function} fn the method the event invokes
9613 * @return {Roo.Element} this
9616 ep.un = ep.removeListener;
9619 * true to automatically adjust width and height settings for box-model issues (default to true)
9621 ep.autoBoxAdjust = true;
9624 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9627 El.addUnits = function(v, defaultUnit){
9628 if(v === "" || v == "auto"){
9631 if(v === undefined){
9634 if(typeof v == "number" || !El.unitPattern.test(v)){
9635 return v + (defaultUnit || 'px');
9640 // special markup used throughout Roo when box wrapping elements
9641 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>';
9643 * Visibility mode constant - Use visibility to hide element
9649 * Visibility mode constant - Use display to hide element
9655 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9656 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9657 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9669 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9670 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9671 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9672 * @return {Element} The Element object
9675 El.get = function(el){
9677 if(!el){ return null; }
9678 if(typeof el == "string"){ // element id
9679 if(!(elm = document.getElementById(el))){
9682 if(ex = El.cache[el]){
9685 ex = El.cache[el] = new El(elm);
9688 }else if(el.tagName){ // dom element
9692 if(ex = El.cache[id]){
9695 ex = El.cache[id] = new El(el);
9698 }else if(el instanceof El){
9700 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9701 // catch case where it hasn't been appended
9702 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9705 }else if(el.isComposite){
9707 }else if(el instanceof Array){
9708 return El.select(el);
9709 }else if(el == document){
9710 // create a bogus element object representing the document object
9712 var f = function(){};
9713 f.prototype = El.prototype;
9715 docEl.dom = document;
9723 El.uncache = function(el){
9724 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9726 delete El.cache[a[i].id || a[i]];
9732 // Garbage collection - uncache elements/purge listeners on orphaned elements
9733 // so we don't hold a reference and cause the browser to retain them
9734 El.garbageCollect = function(){
9735 if(!Roo.enableGarbageCollector){
9736 clearInterval(El.collectorThread);
9739 for(var eid in El.cache){
9740 var el = El.cache[eid], d = el.dom;
9741 // -------------------------------------------------------
9742 // Determining what is garbage:
9743 // -------------------------------------------------------
9745 // dom node is null, definitely garbage
9746 // -------------------------------------------------------
9748 // no parentNode == direct orphan, definitely garbage
9749 // -------------------------------------------------------
9750 // !d.offsetParent && !document.getElementById(eid)
9751 // display none elements have no offsetParent so we will
9752 // also try to look it up by it's id. However, check
9753 // offsetParent first so we don't do unneeded lookups.
9754 // This enables collection of elements that are not orphans
9755 // directly, but somewhere up the line they have an orphan
9757 // -------------------------------------------------------
9758 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9759 delete El.cache[eid];
9760 if(d && Roo.enableListenerCollection){
9766 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9770 El.Flyweight = function(dom){
9773 El.Flyweight.prototype = El.prototype;
9775 El._flyweights = {};
9777 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9778 * the dom node can be overwritten by other code.
9779 * @param {String/HTMLElement} el The dom node or id
9780 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9781 * prevent conflicts (e.g. internally Roo uses "_internal")
9783 * @return {Element} The shared Element object
9785 El.fly = function(el, named){
9786 named = named || '_global';
9787 el = Roo.getDom(el);
9791 if(!El._flyweights[named]){
9792 El._flyweights[named] = new El.Flyweight();
9794 El._flyweights[named].dom = el;
9795 return El._flyweights[named];
9799 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9800 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9801 * Shorthand of {@link Roo.Element#get}
9802 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9803 * @return {Element} The Element object
9809 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9810 * the dom node can be overwritten by other code.
9811 * Shorthand of {@link Roo.Element#fly}
9812 * @param {String/HTMLElement} el The dom node or id
9813 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9814 * prevent conflicts (e.g. internally Roo uses "_internal")
9816 * @return {Element} The shared Element object
9822 // speedy lookup for elements never to box adjust
9823 var noBoxAdjust = Roo.isStrict ? {
9826 input:1, select:1, textarea:1
9828 if(Roo.isIE || Roo.isGecko){
9829 noBoxAdjust['button'] = 1;
9833 Roo.EventManager.on(window, 'unload', function(){
9835 delete El._flyweights;
9843 Roo.Element.selectorFunction = Roo.DomQuery.select;
9846 Roo.Element.select = function(selector, unique, root){
9848 if(typeof selector == "string"){
9849 els = Roo.Element.selectorFunction(selector, root);
9850 }else if(selector.length !== undefined){
9853 throw "Invalid selector";
9855 if(unique === true){
9856 return new Roo.CompositeElement(els);
9858 return new Roo.CompositeElementLite(els);
9862 * Selects elements based on the passed CSS selector to enable working on them as 1.
9863 * @param {String/Array} selector The CSS selector or an array of elements
9864 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9865 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9866 * @return {CompositeElementLite/CompositeElement}
9870 Roo.select = Roo.Element.select;
9887 * Ext JS Library 1.1.1
9888 * Copyright(c) 2006-2007, Ext JS, LLC.
9890 * Originally Released Under LGPL - original licence link has changed is not relivant.
9893 * <script type="text/javascript">
9898 //Notifies Element that fx methods are available
9899 Roo.enableFx = true;
9903 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9904 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9905 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9906 * Element effects to work.</p><br/>
9908 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9909 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9910 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9911 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9912 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9913 * expected results and should be done with care.</p><br/>
9915 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9916 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9919 ----- -----------------------------
9920 tl The top left corner
9921 t The center of the top edge
9922 tr The top right corner
9923 l The center of the left edge
9924 r The center of the right edge
9925 bl The bottom left corner
9926 b The center of the bottom edge
9927 br The bottom right corner
9929 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9930 * below are common options that can be passed to any Fx method.</b>
9931 * @cfg {Function} callback A function called when the effect is finished
9932 * @cfg {Object} scope The scope of the effect function
9933 * @cfg {String} easing A valid Easing value for the effect
9934 * @cfg {String} afterCls A css class to apply after the effect
9935 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9936 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9937 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9938 * effects that end with the element being visually hidden, ignored otherwise)
9939 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9940 * a function which returns such a specification that will be applied to the Element after the effect finishes
9941 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9942 * @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
9943 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9947 * Slides the element into view. An anchor point can be optionally passed to set the point of
9948 * origin for the slide effect. This function automatically handles wrapping the element with
9949 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9952 // default: slide the element in from the top
9955 // custom: slide the element in from the right with a 2-second duration
9956 el.slideIn('r', { duration: 2 });
9958 // common config options shown with default values
9964 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9965 * @param {Object} options (optional) Object literal with any of the Fx config options
9966 * @return {Roo.Element} The Element
9968 slideIn : function(anchor, o){
9969 var el = this.getFxEl();
9972 el.queueFx(o, function(){
9974 anchor = anchor || "t";
9976 // fix display to visibility
9979 // restore values after effect
9980 var r = this.getFxRestore();
9981 var b = this.getBox();
9982 // fixed size for slide
9986 var wrap = this.fxWrap(r.pos, o, "hidden");
9988 var st = this.dom.style;
9989 st.visibility = "visible";
9990 st.position = "absolute";
9992 // clear out temp styles after slide and unwrap
9993 var after = function(){
9994 el.fxUnwrap(wrap, r.pos, o);
9996 st.height = r.height;
9999 // time to calc the positions
10000 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10002 switch(anchor.toLowerCase()){
10004 wrap.setSize(b.width, 0);
10005 st.left = st.bottom = "0";
10009 wrap.setSize(0, b.height);
10010 st.right = st.top = "0";
10014 wrap.setSize(0, b.height);
10015 wrap.setX(b.right);
10016 st.left = st.top = "0";
10017 a = {width: bw, points: pt};
10020 wrap.setSize(b.width, 0);
10021 wrap.setY(b.bottom);
10022 st.left = st.top = "0";
10023 a = {height: bh, points: pt};
10026 wrap.setSize(0, 0);
10027 st.right = st.bottom = "0";
10028 a = {width: bw, height: bh};
10031 wrap.setSize(0, 0);
10032 wrap.setY(b.y+b.height);
10033 st.right = st.top = "0";
10034 a = {width: bw, height: bh, points: pt};
10037 wrap.setSize(0, 0);
10038 wrap.setXY([b.right, b.bottom]);
10039 st.left = st.top = "0";
10040 a = {width: bw, height: bh, points: pt};
10043 wrap.setSize(0, 0);
10044 wrap.setX(b.x+b.width);
10045 st.left = st.bottom = "0";
10046 a = {width: bw, height: bh, points: pt};
10049 this.dom.style.visibility = "visible";
10052 arguments.callee.anim = wrap.fxanim(a,
10062 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10063 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10064 * 'hidden') but block elements will still take up space in the document. The element must be removed
10065 * from the DOM using the 'remove' config option if desired. This function automatically handles
10066 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10069 // default: slide the element out to the top
10072 // custom: slide the element out to the right with a 2-second duration
10073 el.slideOut('r', { duration: 2 });
10075 // common config options shown with default values
10083 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10084 * @param {Object} options (optional) Object literal with any of the Fx config options
10085 * @return {Roo.Element} The Element
10087 slideOut : function(anchor, o){
10088 var el = this.getFxEl();
10091 el.queueFx(o, function(){
10093 anchor = anchor || "t";
10095 // restore values after effect
10096 var r = this.getFxRestore();
10098 var b = this.getBox();
10099 // fixed size for slide
10103 var wrap = this.fxWrap(r.pos, o, "visible");
10105 var st = this.dom.style;
10106 st.visibility = "visible";
10107 st.position = "absolute";
10111 var after = function(){
10113 el.setDisplayed(false);
10118 el.fxUnwrap(wrap, r.pos, o);
10120 st.width = r.width;
10121 st.height = r.height;
10126 var a, zero = {to: 0};
10127 switch(anchor.toLowerCase()){
10129 st.left = st.bottom = "0";
10130 a = {height: zero};
10133 st.right = st.top = "0";
10137 st.left = st.top = "0";
10138 a = {width: zero, points: {to:[b.right, b.y]}};
10141 st.left = st.top = "0";
10142 a = {height: zero, points: {to:[b.x, b.bottom]}};
10145 st.right = st.bottom = "0";
10146 a = {width: zero, height: zero};
10149 st.right = st.top = "0";
10150 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10153 st.left = st.top = "0";
10154 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10157 st.left = st.bottom = "0";
10158 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10162 arguments.callee.anim = wrap.fxanim(a,
10172 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10173 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10174 * The element must be removed from the DOM using the 'remove' config option if desired.
10180 // common config options shown with default values
10188 * @param {Object} options (optional) Object literal with any of the Fx config options
10189 * @return {Roo.Element} The Element
10191 puff : function(o){
10192 var el = this.getFxEl();
10195 el.queueFx(o, function(){
10196 this.clearOpacity();
10199 // restore values after effect
10200 var r = this.getFxRestore();
10201 var st = this.dom.style;
10203 var after = function(){
10205 el.setDisplayed(false);
10212 el.setPositioning(r.pos);
10213 st.width = r.width;
10214 st.height = r.height;
10219 var width = this.getWidth();
10220 var height = this.getHeight();
10222 arguments.callee.anim = this.fxanim({
10223 width : {to: this.adjustWidth(width * 2)},
10224 height : {to: this.adjustHeight(height * 2)},
10225 points : {by: [-(width * .5), -(height * .5)]},
10227 fontSize: {to:200, unit: "%"}
10238 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10239 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10240 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10246 // all config options shown with default values
10254 * @param {Object} options (optional) Object literal with any of the Fx config options
10255 * @return {Roo.Element} The Element
10257 switchOff : function(o){
10258 var el = this.getFxEl();
10261 el.queueFx(o, function(){
10262 this.clearOpacity();
10265 // restore values after effect
10266 var r = this.getFxRestore();
10267 var st = this.dom.style;
10269 var after = function(){
10271 el.setDisplayed(false);
10277 el.setPositioning(r.pos);
10278 st.width = r.width;
10279 st.height = r.height;
10284 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10285 this.clearOpacity();
10289 points:{by:[0, this.getHeight() * .5]}
10290 }, o, 'motion', 0.3, 'easeIn', after);
10291 }).defer(100, this);
10298 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10299 * changed using the "attr" config option) and then fading back to the original color. If no original
10300 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10303 // default: highlight background to yellow
10306 // custom: highlight foreground text to blue for 2 seconds
10307 el.highlight("0000ff", { attr: 'color', duration: 2 });
10309 // common config options shown with default values
10310 el.highlight("ffff9c", {
10311 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10312 endColor: (current color) or "ffffff",
10317 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10318 * @param {Object} options (optional) Object literal with any of the Fx config options
10319 * @return {Roo.Element} The Element
10321 highlight : function(color, o){
10322 var el = this.getFxEl();
10325 el.queueFx(o, function(){
10326 color = color || "ffff9c";
10327 attr = o.attr || "backgroundColor";
10329 this.clearOpacity();
10332 var origColor = this.getColor(attr);
10333 var restoreColor = this.dom.style[attr];
10334 endColor = (o.endColor || origColor) || "ffffff";
10336 var after = function(){
10337 el.dom.style[attr] = restoreColor;
10342 a[attr] = {from: color, to: endColor};
10343 arguments.callee.anim = this.fxanim(a,
10353 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10356 // default: a single light blue ripple
10359 // custom: 3 red ripples lasting 3 seconds total
10360 el.frame("ff0000", 3, { duration: 3 });
10362 // common config options shown with default values
10363 el.frame("C3DAF9", 1, {
10364 duration: 1 //duration of entire animation (not each individual ripple)
10365 // Note: Easing is not configurable and will be ignored if included
10368 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10369 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10370 * @param {Object} options (optional) Object literal with any of the Fx config options
10371 * @return {Roo.Element} The Element
10373 frame : function(color, count, o){
10374 var el = this.getFxEl();
10377 el.queueFx(o, function(){
10378 color = color || "#C3DAF9";
10379 if(color.length == 6){
10380 color = "#" + color;
10382 count = count || 1;
10383 duration = o.duration || 1;
10386 var b = this.getBox();
10387 var animFn = function(){
10388 var proxy = this.createProxy({
10391 visbility:"hidden",
10392 position:"absolute",
10393 "z-index":"35000", // yee haw
10394 border:"0px solid " + color
10397 var scale = Roo.isBorderBox ? 2 : 1;
10399 top:{from:b.y, to:b.y - 20},
10400 left:{from:b.x, to:b.x - 20},
10401 borderWidth:{from:0, to:10},
10402 opacity:{from:1, to:0},
10403 height:{from:b.height, to:(b.height + (20*scale))},
10404 width:{from:b.width, to:(b.width + (20*scale))}
10405 }, duration, function(){
10409 animFn.defer((duration/2)*1000, this);
10420 * Creates a pause before any subsequent queued effects begin. If there are
10421 * no effects queued after the pause it will have no effect.
10426 * @param {Number} seconds The length of time to pause (in seconds)
10427 * @return {Roo.Element} The Element
10429 pause : function(seconds){
10430 var el = this.getFxEl();
10433 el.queueFx(o, function(){
10434 setTimeout(function(){
10436 }, seconds * 1000);
10442 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10443 * using the "endOpacity" config option.
10446 // default: fade in from opacity 0 to 100%
10449 // custom: fade in from opacity 0 to 75% over 2 seconds
10450 el.fadeIn({ endOpacity: .75, duration: 2});
10452 // common config options shown with default values
10454 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10459 * @param {Object} options (optional) Object literal with any of the Fx config options
10460 * @return {Roo.Element} The Element
10462 fadeIn : function(o){
10463 var el = this.getFxEl();
10465 el.queueFx(o, function(){
10466 this.setOpacity(0);
10468 this.dom.style.visibility = 'visible';
10469 var to = o.endOpacity || 1;
10470 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10471 o, null, .5, "easeOut", function(){
10473 this.clearOpacity();
10482 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10483 * using the "endOpacity" config option.
10486 // default: fade out from the element's current opacity to 0
10489 // custom: fade out from the element's current opacity to 25% over 2 seconds
10490 el.fadeOut({ endOpacity: .25, duration: 2});
10492 // common config options shown with default values
10494 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10501 * @param {Object} options (optional) Object literal with any of the Fx config options
10502 * @return {Roo.Element} The Element
10504 fadeOut : function(o){
10505 var el = this.getFxEl();
10507 el.queueFx(o, function(){
10508 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10509 o, null, .5, "easeOut", function(){
10510 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10511 this.dom.style.display = "none";
10513 this.dom.style.visibility = "hidden";
10515 this.clearOpacity();
10523 * Animates the transition of an element's dimensions from a starting height/width
10524 * to an ending height/width.
10527 // change height and width to 100x100 pixels
10528 el.scale(100, 100);
10530 // common config options shown with default values. The height and width will default to
10531 // the element's existing values if passed as null.
10534 [element's height], {
10539 * @param {Number} width The new width (pass undefined to keep the original width)
10540 * @param {Number} height The new height (pass undefined to keep the original height)
10541 * @param {Object} options (optional) Object literal with any of the Fx config options
10542 * @return {Roo.Element} The Element
10544 scale : function(w, h, o){
10545 this.shift(Roo.apply({}, o, {
10553 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10554 * Any of these properties not specified in the config object will not be changed. This effect
10555 * requires that at least one new dimension, position or opacity setting must be passed in on
10556 * the config object in order for the function to have any effect.
10559 // slide the element horizontally to x position 200 while changing the height and opacity
10560 el.shift({ x: 200, height: 50, opacity: .8 });
10562 // common config options shown with default values.
10564 width: [element's width],
10565 height: [element's height],
10566 x: [element's x position],
10567 y: [element's y position],
10568 opacity: [element's opacity],
10573 * @param {Object} options Object literal with any of the Fx config options
10574 * @return {Roo.Element} The Element
10576 shift : function(o){
10577 var el = this.getFxEl();
10579 el.queueFx(o, function(){
10580 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10581 if(w !== undefined){
10582 a.width = {to: this.adjustWidth(w)};
10584 if(h !== undefined){
10585 a.height = {to: this.adjustHeight(h)};
10587 if(x !== undefined || y !== undefined){
10589 x !== undefined ? x : this.getX(),
10590 y !== undefined ? y : this.getY()
10593 if(op !== undefined){
10594 a.opacity = {to: op};
10596 if(o.xy !== undefined){
10597 a.points = {to: o.xy};
10599 arguments.callee.anim = this.fxanim(a,
10600 o, 'motion', .35, "easeOut", function(){
10608 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10609 * ending point of the effect.
10612 // default: slide the element downward while fading out
10615 // custom: slide the element out to the right with a 2-second duration
10616 el.ghost('r', { duration: 2 });
10618 // common config options shown with default values
10626 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10627 * @param {Object} options (optional) Object literal with any of the Fx config options
10628 * @return {Roo.Element} The Element
10630 ghost : function(anchor, o){
10631 var el = this.getFxEl();
10634 el.queueFx(o, function(){
10635 anchor = anchor || "b";
10637 // restore values after effect
10638 var r = this.getFxRestore();
10639 var w = this.getWidth(),
10640 h = this.getHeight();
10642 var st = this.dom.style;
10644 var after = function(){
10646 el.setDisplayed(false);
10652 el.setPositioning(r.pos);
10653 st.width = r.width;
10654 st.height = r.height;
10659 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10660 switch(anchor.toLowerCase()){
10687 arguments.callee.anim = this.fxanim(a,
10697 * Ensures that all effects queued after syncFx is called on the element are
10698 * run concurrently. This is the opposite of {@link #sequenceFx}.
10699 * @return {Roo.Element} The Element
10701 syncFx : function(){
10702 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10711 * Ensures that all effects queued after sequenceFx is called on the element are
10712 * run in sequence. This is the opposite of {@link #syncFx}.
10713 * @return {Roo.Element} The Element
10715 sequenceFx : function(){
10716 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10718 concurrent : false,
10725 nextFx : function(){
10726 var ef = this.fxQueue[0];
10733 * Returns true if the element has any effects actively running or queued, else returns false.
10734 * @return {Boolean} True if element has active effects, else false
10736 hasActiveFx : function(){
10737 return this.fxQueue && this.fxQueue[0];
10741 * Stops any running effects and clears the element's internal effects queue if it contains
10742 * any additional effects that haven't started yet.
10743 * @return {Roo.Element} The Element
10745 stopFx : function(){
10746 if(this.hasActiveFx()){
10747 var cur = this.fxQueue[0];
10748 if(cur && cur.anim && cur.anim.isAnimated()){
10749 this.fxQueue = [cur]; // clear out others
10750 cur.anim.stop(true);
10757 beforeFx : function(o){
10758 if(this.hasActiveFx() && !o.concurrent){
10769 * Returns true if the element is currently blocking so that no other effect can be queued
10770 * until this effect is finished, else returns false if blocking is not set. This is commonly
10771 * used to ensure that an effect initiated by a user action runs to completion prior to the
10772 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10773 * @return {Boolean} True if blocking, else false
10775 hasFxBlock : function(){
10776 var q = this.fxQueue;
10777 return q && q[0] && q[0].block;
10781 queueFx : function(o, fn){
10785 if(!this.hasFxBlock()){
10786 Roo.applyIf(o, this.fxDefaults);
10788 var run = this.beforeFx(o);
10789 fn.block = o.block;
10790 this.fxQueue.push(fn);
10802 fxWrap : function(pos, o, vis){
10804 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10807 wrapXY = this.getXY();
10809 var div = document.createElement("div");
10810 div.style.visibility = vis;
10811 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10812 wrap.setPositioning(pos);
10813 if(wrap.getStyle("position") == "static"){
10814 wrap.position("relative");
10816 this.clearPositioning('auto');
10818 wrap.dom.appendChild(this.dom);
10820 wrap.setXY(wrapXY);
10827 fxUnwrap : function(wrap, pos, o){
10828 this.clearPositioning();
10829 this.setPositioning(pos);
10831 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10837 getFxRestore : function(){
10838 var st = this.dom.style;
10839 return {pos: this.getPositioning(), width: st.width, height : st.height};
10843 afterFx : function(o){
10845 this.applyStyles(o.afterStyle);
10848 this.addClass(o.afterCls);
10850 if(o.remove === true){
10853 Roo.callback(o.callback, o.scope, [this]);
10855 this.fxQueue.shift();
10861 getFxEl : function(){ // support for composite element fx
10862 return Roo.get(this.dom);
10866 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10867 animType = animType || 'run';
10869 var anim = Roo.lib.Anim[animType](
10871 (opt.duration || defaultDur) || .35,
10872 (opt.easing || defaultEase) || 'easeOut',
10874 Roo.callback(cb, this);
10883 // backwords compat
10884 Roo.Fx.resize = Roo.Fx.scale;
10886 //When included, Roo.Fx is automatically applied to Element so that all basic
10887 //effects are available directly via the Element API
10888 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10890 * Ext JS Library 1.1.1
10891 * Copyright(c) 2006-2007, Ext JS, LLC.
10893 * Originally Released Under LGPL - original licence link has changed is not relivant.
10896 * <script type="text/javascript">
10901 * @class Roo.CompositeElement
10902 * Standard composite class. Creates a Roo.Element for every element in the collection.
10904 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10905 * actions will be performed on all the elements in this collection.</b>
10907 * All methods return <i>this</i> and can be chained.
10909 var els = Roo.select("#some-el div.some-class", true);
10910 // or select directly from an existing element
10911 var el = Roo.get('some-el');
10912 el.select('div.some-class', true);
10914 els.setWidth(100); // all elements become 100 width
10915 els.hide(true); // all elements fade out and hide
10917 els.setWidth(100).hide(true);
10920 Roo.CompositeElement = function(els){
10921 this.elements = [];
10922 this.addElements(els);
10924 Roo.CompositeElement.prototype = {
10926 addElements : function(els){
10927 if(!els) return this;
10928 if(typeof els == "string"){
10929 els = Roo.Element.selectorFunction(els);
10931 var yels = this.elements;
10932 var index = yels.length-1;
10933 for(var i = 0, len = els.length; i < len; i++) {
10934 yels[++index] = Roo.get(els[i]);
10940 * Clears this composite and adds the elements returned by the passed selector.
10941 * @param {String/Array} els A string CSS selector, an array of elements or an element
10942 * @return {CompositeElement} this
10944 fill : function(els){
10945 this.elements = [];
10951 * Filters this composite to only elements that match the passed selector.
10952 * @param {String} selector A string CSS selector
10953 * @return {CompositeElement} this
10955 filter : function(selector){
10957 this.each(function(el){
10958 if(el.is(selector)){
10959 els[els.length] = el.dom;
10966 invoke : function(fn, args){
10967 var els = this.elements;
10968 for(var i = 0, len = els.length; i < len; i++) {
10969 Roo.Element.prototype[fn].apply(els[i], args);
10974 * Adds elements to this composite.
10975 * @param {String/Array} els A string CSS selector, an array of elements or an element
10976 * @return {CompositeElement} this
10978 add : function(els){
10979 if(typeof els == "string"){
10980 this.addElements(Roo.Element.selectorFunction(els));
10981 }else if(els.length !== undefined){
10982 this.addElements(els);
10984 this.addElements([els]);
10989 * Calls the passed function passing (el, this, index) for each element in this composite.
10990 * @param {Function} fn The function to call
10991 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10992 * @return {CompositeElement} this
10994 each : function(fn, scope){
10995 var els = this.elements;
10996 for(var i = 0, len = els.length; i < len; i++){
10997 if(fn.call(scope || els[i], els[i], this, i) === false) {
11005 * Returns the Element object at the specified index
11006 * @param {Number} index
11007 * @return {Roo.Element}
11009 item : function(index){
11010 return this.elements[index] || null;
11014 * Returns the first Element
11015 * @return {Roo.Element}
11017 first : function(){
11018 return this.item(0);
11022 * Returns the last Element
11023 * @return {Roo.Element}
11026 return this.item(this.elements.length-1);
11030 * Returns the number of elements in this composite
11033 getCount : function(){
11034 return this.elements.length;
11038 * Returns true if this composite contains the passed element
11041 contains : function(el){
11042 return this.indexOf(el) !== -1;
11046 * Returns true if this composite contains the passed element
11049 indexOf : function(el){
11050 return this.elements.indexOf(Roo.get(el));
11055 * Removes the specified element(s).
11056 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11057 * or an array of any of those.
11058 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11059 * @return {CompositeElement} this
11061 removeElement : function(el, removeDom){
11062 if(el instanceof Array){
11063 for(var i = 0, len = el.length; i < len; i++){
11064 this.removeElement(el[i]);
11068 var index = typeof el == 'number' ? el : this.indexOf(el);
11071 var d = this.elements[index];
11075 d.parentNode.removeChild(d);
11078 this.elements.splice(index, 1);
11084 * Replaces the specified element with the passed element.
11085 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11087 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11088 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11089 * @return {CompositeElement} this
11091 replaceElement : function(el, replacement, domReplace){
11092 var index = typeof el == 'number' ? el : this.indexOf(el);
11095 this.elements[index].replaceWith(replacement);
11097 this.elements.splice(index, 1, Roo.get(replacement))
11104 * Removes all elements.
11106 clear : function(){
11107 this.elements = [];
11111 Roo.CompositeElement.createCall = function(proto, fnName){
11112 if(!proto[fnName]){
11113 proto[fnName] = function(){
11114 return this.invoke(fnName, arguments);
11118 for(var fnName in Roo.Element.prototype){
11119 if(typeof Roo.Element.prototype[fnName] == "function"){
11120 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11126 * Ext JS Library 1.1.1
11127 * Copyright(c) 2006-2007, Ext JS, LLC.
11129 * Originally Released Under LGPL - original licence link has changed is not relivant.
11132 * <script type="text/javascript">
11136 * @class Roo.CompositeElementLite
11137 * @extends Roo.CompositeElement
11138 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11140 var els = Roo.select("#some-el div.some-class");
11141 // or select directly from an existing element
11142 var el = Roo.get('some-el');
11143 el.select('div.some-class');
11145 els.setWidth(100); // all elements become 100 width
11146 els.hide(true); // all elements fade out and hide
11148 els.setWidth(100).hide(true);
11149 </code></pre><br><br>
11150 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11151 * actions will be performed on all the elements in this collection.</b>
11153 Roo.CompositeElementLite = function(els){
11154 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11155 this.el = new Roo.Element.Flyweight();
11157 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11158 addElements : function(els){
11160 if(els instanceof Array){
11161 this.elements = this.elements.concat(els);
11163 var yels = this.elements;
11164 var index = yels.length-1;
11165 for(var i = 0, len = els.length; i < len; i++) {
11166 yels[++index] = els[i];
11172 invoke : function(fn, args){
11173 var els = this.elements;
11175 for(var i = 0, len = els.length; i < len; i++) {
11177 Roo.Element.prototype[fn].apply(el, args);
11182 * Returns a flyweight Element of the dom element object at the specified index
11183 * @param {Number} index
11184 * @return {Roo.Element}
11186 item : function(index){
11187 if(!this.elements[index]){
11190 this.el.dom = this.elements[index];
11194 // fixes scope with flyweight
11195 addListener : function(eventName, handler, scope, opt){
11196 var els = this.elements;
11197 for(var i = 0, len = els.length; i < len; i++) {
11198 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11204 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11205 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11206 * a reference to the dom node, use el.dom.</b>
11207 * @param {Function} fn The function to call
11208 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11209 * @return {CompositeElement} this
11211 each : function(fn, scope){
11212 var els = this.elements;
11214 for(var i = 0, len = els.length; i < len; i++){
11216 if(fn.call(scope || el, el, this, i) === false){
11223 indexOf : function(el){
11224 return this.elements.indexOf(Roo.getDom(el));
11227 replaceElement : function(el, replacement, domReplace){
11228 var index = typeof el == 'number' ? el : this.indexOf(el);
11230 replacement = Roo.getDom(replacement);
11232 var d = this.elements[index];
11233 d.parentNode.insertBefore(replacement, d);
11234 d.parentNode.removeChild(d);
11236 this.elements.splice(index, 1, replacement);
11241 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11245 * Ext JS Library 1.1.1
11246 * Copyright(c) 2006-2007, Ext JS, LLC.
11248 * Originally Released Under LGPL - original licence link has changed is not relivant.
11251 * <script type="text/javascript">
11257 * @class Roo.data.Connection
11258 * @extends Roo.util.Observable
11259 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11260 * either to a configured URL, or to a URL specified at request time.<br><br>
11262 * Requests made by this class are asynchronous, and will return immediately. No data from
11263 * the server will be available to the statement immediately following the {@link #request} call.
11264 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11266 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11267 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11268 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11269 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11270 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11271 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11272 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11273 * standard DOM methods.
11275 * @param {Object} config a configuration object.
11277 Roo.data.Connection = function(config){
11278 Roo.apply(this, config);
11281 * @event beforerequest
11282 * Fires before a network request is made to retrieve a data object.
11283 * @param {Connection} conn This Connection object.
11284 * @param {Object} options The options config object passed to the {@link #request} method.
11286 "beforerequest" : true,
11288 * @event requestcomplete
11289 * Fires if the request was successfully completed.
11290 * @param {Connection} conn This Connection object.
11291 * @param {Object} response The XHR object containing the response data.
11292 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11293 * @param {Object} options The options config object passed to the {@link #request} method.
11295 "requestcomplete" : true,
11297 * @event requestexception
11298 * Fires if an error HTTP status was returned from the server.
11299 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11300 * @param {Connection} conn This Connection object.
11301 * @param {Object} response The XHR object containing the response data.
11302 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11303 * @param {Object} options The options config object passed to the {@link #request} method.
11305 "requestexception" : true
11307 Roo.data.Connection.superclass.constructor.call(this);
11310 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11312 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11315 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11316 * extra parameters to each request made by this object. (defaults to undefined)
11319 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11320 * to each request made by this object. (defaults to undefined)
11323 * @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)
11326 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11330 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11336 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11339 disableCaching: true,
11342 * Sends an HTTP request to a remote server.
11343 * @param {Object} options An object which may contain the following properties:<ul>
11344 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11345 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11346 * request, a url encoded string or a function to call to get either.</li>
11347 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11348 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11349 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11350 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11351 * <li>options {Object} The parameter to the request call.</li>
11352 * <li>success {Boolean} True if the request succeeded.</li>
11353 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11355 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11356 * The callback is passed the following parameters:<ul>
11357 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11358 * <li>options {Object} The parameter to the request call.</li>
11360 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11361 * The callback is passed the following parameters:<ul>
11362 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11363 * <li>options {Object} The parameter to the request call.</li>
11365 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11366 * for the callback function. Defaults to the browser window.</li>
11367 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11368 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11369 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11370 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11371 * params for the post data. Any params will be appended to the URL.</li>
11372 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11374 * @return {Number} transactionId
11376 request : function(o){
11377 if(this.fireEvent("beforerequest", this, o) !== false){
11380 if(typeof p == "function"){
11381 p = p.call(o.scope||window, o);
11383 if(typeof p == "object"){
11384 p = Roo.urlEncode(o.params);
11386 if(this.extraParams){
11387 var extras = Roo.urlEncode(this.extraParams);
11388 p = p ? (p + '&' + extras) : extras;
11391 var url = o.url || this.url;
11392 if(typeof url == 'function'){
11393 url = url.call(o.scope||window, o);
11397 var form = Roo.getDom(o.form);
11398 url = url || form.action;
11400 var enctype = form.getAttribute("enctype");
11401 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11402 return this.doFormUpload(o, p, url);
11404 var f = Roo.lib.Ajax.serializeForm(form);
11405 p = p ? (p + '&' + f) : f;
11408 var hs = o.headers;
11409 if(this.defaultHeaders){
11410 hs = Roo.apply(hs || {}, this.defaultHeaders);
11417 success: this.handleResponse,
11418 failure: this.handleFailure,
11420 argument: {options: o},
11421 timeout : o.timeout || this.timeout
11424 var method = o.method||this.method||(p ? "POST" : "GET");
11426 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11427 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11430 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11434 }else if(this.autoAbort !== false){
11438 if((method == 'GET' && p) || o.xmlData){
11439 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11442 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11443 return this.transId;
11445 Roo.callback(o.callback, o.scope, [o, null, null]);
11451 * Determine whether this object has a request outstanding.
11452 * @param {Number} transactionId (Optional) defaults to the last transaction
11453 * @return {Boolean} True if there is an outstanding request.
11455 isLoading : function(transId){
11457 return Roo.lib.Ajax.isCallInProgress(transId);
11459 return this.transId ? true : false;
11464 * Aborts any outstanding request.
11465 * @param {Number} transactionId (Optional) defaults to the last transaction
11467 abort : function(transId){
11468 if(transId || this.isLoading()){
11469 Roo.lib.Ajax.abort(transId || this.transId);
11474 handleResponse : function(response){
11475 this.transId = false;
11476 var options = response.argument.options;
11477 response.argument = options ? options.argument : null;
11478 this.fireEvent("requestcomplete", this, response, options);
11479 Roo.callback(options.success, options.scope, [response, options]);
11480 Roo.callback(options.callback, options.scope, [options, true, response]);
11484 handleFailure : function(response, e){
11485 this.transId = false;
11486 var options = response.argument.options;
11487 response.argument = options ? options.argument : null;
11488 this.fireEvent("requestexception", this, response, options, e);
11489 Roo.callback(options.failure, options.scope, [response, options]);
11490 Roo.callback(options.callback, options.scope, [options, false, response]);
11494 doFormUpload : function(o, ps, url){
11496 var frame = document.createElement('iframe');
11499 frame.className = 'x-hidden';
11501 frame.src = Roo.SSL_SECURE_URL;
11503 document.body.appendChild(frame);
11506 document.frames[id].name = id;
11509 var form = Roo.getDom(o.form);
11511 form.method = 'POST';
11512 form.enctype = form.encoding = 'multipart/form-data';
11518 if(ps){ // add dynamic params
11520 ps = Roo.urlDecode(ps, false);
11522 if(ps.hasOwnProperty(k)){
11523 hd = document.createElement('input');
11524 hd.type = 'hidden';
11527 form.appendChild(hd);
11534 var r = { // bogus response object
11539 r.argument = o ? o.argument : null;
11544 doc = frame.contentWindow.document;
11546 doc = (frame.contentDocument || window.frames[id].document);
11548 if(doc && doc.body){
11549 r.responseText = doc.body.innerHTML;
11551 if(doc && doc.XMLDocument){
11552 r.responseXML = doc.XMLDocument;
11554 r.responseXML = doc;
11561 Roo.EventManager.removeListener(frame, 'load', cb, this);
11563 this.fireEvent("requestcomplete", this, r, o);
11564 Roo.callback(o.success, o.scope, [r, o]);
11565 Roo.callback(o.callback, o.scope, [o, true, r]);
11567 setTimeout(function(){document.body.removeChild(frame);}, 100);
11570 Roo.EventManager.on(frame, 'load', cb, this);
11573 if(hiddens){ // remove dynamic params
11574 for(var i = 0, len = hiddens.length; i < len; i++){
11575 form.removeChild(hiddens[i]);
11582 * Ext JS Library 1.1.1
11583 * Copyright(c) 2006-2007, Ext JS, LLC.
11585 * Originally Released Under LGPL - original licence link has changed is not relivant.
11588 * <script type="text/javascript">
11592 * Global Ajax request class.
11595 * @extends Roo.data.Connection
11598 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11599 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11600 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11601 * @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)
11602 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11603 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11604 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11606 Roo.Ajax = new Roo.data.Connection({
11615 * Serialize the passed form into a url encoded string
11617 * @param {String/HTMLElement} form
11620 serializeForm : function(form){
11621 return Roo.lib.Ajax.serializeForm(form);
11625 * Ext JS Library 1.1.1
11626 * Copyright(c) 2006-2007, Ext JS, LLC.
11628 * Originally Released Under LGPL - original licence link has changed is not relivant.
11631 * <script type="text/javascript">
11636 * @class Roo.UpdateManager
11637 * @extends Roo.util.Observable
11638 * Provides AJAX-style update for Element object.<br><br>
11641 * // Get it from a Roo.Element object
11642 * var el = Roo.get("foo");
11643 * var mgr = el.getUpdateManager();
11644 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11646 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11648 * // or directly (returns the same UpdateManager instance)
11649 * var mgr = new Roo.UpdateManager("myElementId");
11650 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11651 * mgr.on("update", myFcnNeedsToKnow);
11653 // short handed call directly from the element object
11654 Roo.get("foo").load({
11658 text: "Loading Foo..."
11662 * Create new UpdateManager directly.
11663 * @param {String/HTMLElement/Roo.Element} el The element to update
11664 * @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).
11666 Roo.UpdateManager = function(el, forceNew){
11668 if(!forceNew && el.updateManager){
11669 return el.updateManager;
11672 * The Element object
11673 * @type Roo.Element
11677 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11680 this.defaultUrl = null;
11684 * @event beforeupdate
11685 * Fired before an update is made, return false from your handler and the update is cancelled.
11686 * @param {Roo.Element} el
11687 * @param {String/Object/Function} url
11688 * @param {String/Object} params
11690 "beforeupdate": true,
11693 * Fired after successful update is made.
11694 * @param {Roo.Element} el
11695 * @param {Object} oResponseObject The response Object
11700 * Fired on update failure.
11701 * @param {Roo.Element} el
11702 * @param {Object} oResponseObject The response Object
11706 var d = Roo.UpdateManager.defaults;
11708 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11711 this.sslBlankUrl = d.sslBlankUrl;
11713 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11716 this.disableCaching = d.disableCaching;
11718 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11721 this.indicatorText = d.indicatorText;
11723 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11726 this.showLoadIndicator = d.showLoadIndicator;
11728 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11731 this.timeout = d.timeout;
11734 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11737 this.loadScripts = d.loadScripts;
11740 * Transaction object of current executing transaction
11742 this.transaction = null;
11747 this.autoRefreshProcId = null;
11749 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11752 this.refreshDelegate = this.refresh.createDelegate(this);
11754 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11757 this.updateDelegate = this.update.createDelegate(this);
11759 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11762 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11766 this.successDelegate = this.processSuccess.createDelegate(this);
11770 this.failureDelegate = this.processFailure.createDelegate(this);
11772 if(!this.renderer){
11774 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11776 this.renderer = new Roo.UpdateManager.BasicRenderer();
11779 Roo.UpdateManager.superclass.constructor.call(this);
11782 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11784 * Get the Element this UpdateManager is bound to
11785 * @return {Roo.Element} The element
11787 getEl : function(){
11791 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11792 * @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:
11795 url: "your-url.php",<br/>
11796 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11797 callback: yourFunction,<br/>
11798 scope: yourObject, //(optional scope) <br/>
11799 discardUrl: false, <br/>
11800 nocache: false,<br/>
11801 text: "Loading...",<br/>
11803 scripts: false<br/>
11806 * The only required property is url. The optional properties nocache, text and scripts
11807 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11808 * @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}
11809 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11810 * @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.
11812 update : function(url, params, callback, discardUrl){
11813 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11814 var method = this.method,
11816 if(typeof url == "object"){ // must be config object
11819 params = params || cfg.params;
11820 callback = callback || cfg.callback;
11821 discardUrl = discardUrl || cfg.discardUrl;
11822 if(callback && cfg.scope){
11823 callback = callback.createDelegate(cfg.scope);
11825 if(typeof cfg.method != "undefined"){method = cfg.method;};
11826 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11827 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11828 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11829 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11831 this.showLoading();
11833 this.defaultUrl = url;
11835 if(typeof url == "function"){
11836 url = url.call(this);
11839 method = method || (params ? "POST" : "GET");
11840 if(method == "GET"){
11841 url = this.prepareUrl(url);
11844 var o = Roo.apply(cfg ||{}, {
11847 success: this.successDelegate,
11848 failure: this.failureDelegate,
11849 callback: undefined,
11850 timeout: (this.timeout*1000),
11851 argument: {"url": url, "form": null, "callback": callback, "params": params}
11853 Roo.log("updated manager called with timeout of " + o.timeout);
11854 this.transaction = Roo.Ajax.request(o);
11859 * 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.
11860 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11861 * @param {String/HTMLElement} form The form Id or form element
11862 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11863 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11864 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11866 formUpdate : function(form, url, reset, callback){
11867 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11868 if(typeof url == "function"){
11869 url = url.call(this);
11871 form = Roo.getDom(form);
11872 this.transaction = Roo.Ajax.request({
11875 success: this.successDelegate,
11876 failure: this.failureDelegate,
11877 timeout: (this.timeout*1000),
11878 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11880 this.showLoading.defer(1, this);
11885 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11886 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11888 refresh : function(callback){
11889 if(this.defaultUrl == null){
11892 this.update(this.defaultUrl, null, callback, true);
11896 * Set this element to auto refresh.
11897 * @param {Number} interval How often to update (in seconds).
11898 * @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)
11899 * @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}
11900 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11901 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11903 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11905 this.update(url || this.defaultUrl, params, callback, true);
11907 if(this.autoRefreshProcId){
11908 clearInterval(this.autoRefreshProcId);
11910 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11914 * Stop auto refresh on this element.
11916 stopAutoRefresh : function(){
11917 if(this.autoRefreshProcId){
11918 clearInterval(this.autoRefreshProcId);
11919 delete this.autoRefreshProcId;
11923 isAutoRefreshing : function(){
11924 return this.autoRefreshProcId ? true : false;
11927 * Called to update the element to "Loading" state. Override to perform custom action.
11929 showLoading : function(){
11930 if(this.showLoadIndicator){
11931 this.el.update(this.indicatorText);
11936 * Adds unique parameter to query string if disableCaching = true
11939 prepareUrl : function(url){
11940 if(this.disableCaching){
11941 var append = "_dc=" + (new Date().getTime());
11942 if(url.indexOf("?") !== -1){
11943 url += "&" + append;
11945 url += "?" + append;
11954 processSuccess : function(response){
11955 this.transaction = null;
11956 if(response.argument.form && response.argument.reset){
11957 try{ // put in try/catch since some older FF releases had problems with this
11958 response.argument.form.reset();
11961 if(this.loadScripts){
11962 this.renderer.render(this.el, response, this,
11963 this.updateComplete.createDelegate(this, [response]));
11965 this.renderer.render(this.el, response, this);
11966 this.updateComplete(response);
11970 updateComplete : function(response){
11971 this.fireEvent("update", this.el, response);
11972 if(typeof response.argument.callback == "function"){
11973 response.argument.callback(this.el, true, response);
11980 processFailure : function(response){
11981 this.transaction = null;
11982 this.fireEvent("failure", this.el, response);
11983 if(typeof response.argument.callback == "function"){
11984 response.argument.callback(this.el, false, response);
11989 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11990 * @param {Object} renderer The object implementing the render() method
11992 setRenderer : function(renderer){
11993 this.renderer = renderer;
11996 getRenderer : function(){
11997 return this.renderer;
12001 * Set the defaultUrl used for updates
12002 * @param {String/Function} defaultUrl The url or a function to call to get the url
12004 setDefaultUrl : function(defaultUrl){
12005 this.defaultUrl = defaultUrl;
12009 * Aborts the executing transaction
12011 abort : function(){
12012 if(this.transaction){
12013 Roo.Ajax.abort(this.transaction);
12018 * Returns true if an update is in progress
12019 * @return {Boolean}
12021 isUpdating : function(){
12022 if(this.transaction){
12023 return Roo.Ajax.isLoading(this.transaction);
12030 * @class Roo.UpdateManager.defaults
12031 * @static (not really - but it helps the doc tool)
12032 * The defaults collection enables customizing the default properties of UpdateManager
12034 Roo.UpdateManager.defaults = {
12036 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12042 * True to process scripts by default (Defaults to false).
12045 loadScripts : false,
12048 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12051 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12053 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12056 disableCaching : false,
12058 * Whether to show indicatorText when loading (Defaults to true).
12061 showLoadIndicator : true,
12063 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12066 indicatorText : '<div class="loading-indicator">Loading...</div>'
12070 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12072 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12073 * @param {String/HTMLElement/Roo.Element} el The element to update
12074 * @param {String} url The url
12075 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12076 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12079 * @member Roo.UpdateManager
12081 Roo.UpdateManager.updateElement = function(el, url, params, options){
12082 var um = Roo.get(el, true).getUpdateManager();
12083 Roo.apply(um, options);
12084 um.update(url, params, options ? options.callback : null);
12086 // alias for backwards compat
12087 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12089 * @class Roo.UpdateManager.BasicRenderer
12090 * Default Content renderer. Updates the elements innerHTML with the responseText.
12092 Roo.UpdateManager.BasicRenderer = function(){};
12094 Roo.UpdateManager.BasicRenderer.prototype = {
12096 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12097 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12098 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12099 * @param {Roo.Element} el The element being rendered
12100 * @param {Object} response The YUI Connect response object
12101 * @param {UpdateManager} updateManager The calling update manager
12102 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12104 render : function(el, response, updateManager, callback){
12105 el.update(response.responseText, updateManager.loadScripts, callback);
12111 * (c)) Alan Knowles
12117 * @class Roo.DomTemplate
12118 * @extends Roo.Template
12119 * An effort at a dom based template engine..
12121 * Similar to XTemplate, except it uses dom parsing to create the template..
12123 * Supported features:
12128 {a_variable} - output encoded.
12129 {a_variable.format:("Y-m-d")} - call a method on the variable
12130 {a_variable:raw} - unencoded output
12131 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12132 {a_variable:this.method_on_template(...)} - call a method on the template object.
12137 <div roo-for="a_variable or condition.."></div>
12138 <div roo-if="a_variable or condition"></div>
12139 <div roo-exec="some javascript"></div>
12140 <div roo-name="named_template"></div>
12145 Roo.DomTemplate = function()
12147 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12154 Roo.extend(Roo.DomTemplate, Roo.Template, {
12156 * id counter for sub templates.
12160 * flag to indicate if dom parser is inside a pre,
12161 * it will strip whitespace if not.
12166 * The various sub templates
12174 * basic tag replacing syntax
12177 * // you can fake an object call by doing this
12181 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12182 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12184 iterChild : function (node, method) {
12186 var oldPre = this.inPre;
12187 if (node.tagName == 'PRE') {
12190 for( var i = 0; i < node.childNodes.length; i++) {
12191 method.call(this, node.childNodes[i]);
12193 this.inPre = oldPre;
12199 * compile the template
12201 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12204 compile: function()
12208 // covert the html into DOM...
12212 doc = document.implementation.createHTMLDocument("");
12213 doc.documentElement.innerHTML = this.html ;
12214 div = doc.documentElement;
12216 // old IE... - nasty -- it causes all sorts of issues.. with
12217 // images getting pulled from server..
12218 div = document.createElement('div');
12219 div.innerHTML = this.html;
12221 //doc.documentElement.innerHTML = htmlBody
12227 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12229 var tpls = this.tpls;
12231 // create a top level template from the snippet..
12233 //Roo.log(div.innerHTML);
12240 body : div.innerHTML,
12253 Roo.each(tpls, function(tp){
12254 this.compileTpl(tp);
12255 this.tpls[tp.id] = tp;
12258 this.master = tpls[0];
12264 compileNode : function(node, istop) {
12269 // skip anything not a tag..
12270 if (node.nodeType != 1) {
12271 if (node.nodeType == 3 && !this.inPre) {
12272 // reduce white space..
12273 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12296 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12297 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12298 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12299 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12305 // just itterate children..
12306 this.iterChild(node,this.compileNode);
12309 tpl.uid = this.id++;
12310 tpl.value = node.getAttribute('roo-' + tpl.attr);
12311 node.removeAttribute('roo-'+ tpl.attr);
12312 if (tpl.attr != 'name') {
12313 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12314 node.parentNode.replaceChild(placeholder, node);
12317 var placeholder = document.createElement('span');
12318 placeholder.className = 'roo-tpl-' + tpl.value;
12319 node.parentNode.replaceChild(placeholder, node);
12322 // parent now sees '{domtplXXXX}
12323 this.iterChild(node,this.compileNode);
12325 // we should now have node body...
12326 var div = document.createElement('div');
12327 div.appendChild(node);
12329 // this has the unfortunate side effect of converting tagged attributes
12330 // eg. href="{...}" into %7C...%7D
12331 // this has been fixed by searching for those combo's although it's a bit hacky..
12334 tpl.body = div.innerHTML;
12341 switch (tpl.value) {
12342 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12343 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12344 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12349 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12353 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12357 tpl.id = tpl.value; // replace non characters???
12363 this.tpls.push(tpl);
12373 * Compile a segment of the template into a 'sub-template'
12379 compileTpl : function(tpl)
12381 var fm = Roo.util.Format;
12382 var useF = this.disableFormats !== true;
12384 var sep = Roo.isGecko ? "+\n" : ",\n";
12386 var undef = function(str) {
12387 Roo.debug && Roo.log("Property not found :" + str);
12391 //Roo.log(tpl.body);
12395 var fn = function(m, lbrace, name, format, args)
12398 //Roo.log(arguments);
12399 args = args ? args.replace(/\\'/g,"'") : args;
12400 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12401 if (typeof(format) == 'undefined') {
12402 format = 'htmlEncode';
12404 if (format == 'raw' ) {
12408 if(name.substr(0, 6) == 'domtpl'){
12409 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12412 // build an array of options to determine if value is undefined..
12414 // basically get 'xxxx.yyyy' then do
12415 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12416 // (function () { Roo.log("Property not found"); return ''; })() :
12421 Roo.each(name.split('.'), function(st) {
12422 lookfor += (lookfor.length ? '.': '') + st;
12423 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12426 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12429 if(format && useF){
12431 args = args ? ',' + args : "";
12433 if(format.substr(0, 5) != "this."){
12434 format = "fm." + format + '(';
12436 format = 'this.call("'+ format.substr(5) + '", ';
12440 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12443 if (args && args.length) {
12444 // called with xxyx.yuu:(test,test)
12446 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12448 // raw.. - :raw modifier..
12449 return "'"+ sep + udef_st + name + ")"+sep+"'";
12453 // branched to use + in gecko and [].join() in others
12455 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12456 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12459 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12460 body.push(tpl.body.replace(/(\r\n|\n)/g,
12461 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12462 body.push("'].join('');};};");
12463 body = body.join('');
12466 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12468 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12475 * same as applyTemplate, except it's done to one of the subTemplates
12476 * when using named templates, you can do:
12478 * var str = pl.applySubTemplate('your-name', values);
12481 * @param {Number} id of the template
12482 * @param {Object} values to apply to template
12483 * @param {Object} parent (normaly the instance of this object)
12485 applySubTemplate : function(id, values, parent)
12489 var t = this.tpls[id];
12493 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12494 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12498 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12505 if(t.execCall && t.execCall.call(this, values, parent)){
12509 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12515 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12516 parent = t.target ? values : parent;
12517 if(t.forCall && vs instanceof Array){
12519 for(var i = 0, len = vs.length; i < len; i++){
12521 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12523 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12525 //Roo.log(t.compiled);
12529 return buf.join('');
12532 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12537 return t.compiled.call(this, vs, parent);
12539 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12541 //Roo.log(t.compiled);
12549 applyTemplate : function(values){
12550 return this.master.compiled.call(this, values, {});
12551 //var s = this.subs;
12554 apply : function(){
12555 return this.applyTemplate.apply(this, arguments);
12560 Roo.DomTemplate.from = function(el){
12561 el = Roo.getDom(el);
12562 return new Roo.Domtemplate(el.value || el.innerHTML);
12565 * Ext JS Library 1.1.1
12566 * Copyright(c) 2006-2007, Ext JS, LLC.
12568 * Originally Released Under LGPL - original licence link has changed is not relivant.
12571 * <script type="text/javascript">
12575 * @class Roo.util.DelayedTask
12576 * Provides a convenient method of performing setTimeout where a new
12577 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12578 * You can use this class to buffer
12579 * the keypress events for a certain number of milliseconds, and perform only if they stop
12580 * for that amount of time.
12581 * @constructor The parameters to this constructor serve as defaults and are not required.
12582 * @param {Function} fn (optional) The default function to timeout
12583 * @param {Object} scope (optional) The default scope of that timeout
12584 * @param {Array} args (optional) The default Array of arguments
12586 Roo.util.DelayedTask = function(fn, scope, args){
12587 var id = null, d, t;
12589 var call = function(){
12590 var now = new Date().getTime();
12594 fn.apply(scope, args || []);
12598 * Cancels any pending timeout and queues a new one
12599 * @param {Number} delay The milliseconds to delay
12600 * @param {Function} newFn (optional) Overrides function passed to constructor
12601 * @param {Object} newScope (optional) Overrides scope passed to constructor
12602 * @param {Array} newArgs (optional) Overrides args passed to constructor
12604 this.delay = function(delay, newFn, newScope, newArgs){
12605 if(id && delay != d){
12609 t = new Date().getTime();
12611 scope = newScope || scope;
12612 args = newArgs || args;
12614 id = setInterval(call, d);
12619 * Cancel the last queued timeout
12621 this.cancel = function(){
12629 * Ext JS Library 1.1.1
12630 * Copyright(c) 2006-2007, Ext JS, LLC.
12632 * Originally Released Under LGPL - original licence link has changed is not relivant.
12635 * <script type="text/javascript">
12639 Roo.util.TaskRunner = function(interval){
12640 interval = interval || 10;
12641 var tasks = [], removeQueue = [];
12643 var running = false;
12645 var stopThread = function(){
12651 var startThread = function(){
12654 id = setInterval(runTasks, interval);
12658 var removeTask = function(task){
12659 removeQueue.push(task);
12665 var runTasks = function(){
12666 if(removeQueue.length > 0){
12667 for(var i = 0, len = removeQueue.length; i < len; i++){
12668 tasks.remove(removeQueue[i]);
12671 if(tasks.length < 1){
12676 var now = new Date().getTime();
12677 for(var i = 0, len = tasks.length; i < len; ++i){
12679 var itime = now - t.taskRunTime;
12680 if(t.interval <= itime){
12681 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12682 t.taskRunTime = now;
12683 if(rt === false || t.taskRunCount === t.repeat){
12688 if(t.duration && t.duration <= (now - t.taskStartTime)){
12695 * Queues a new task.
12696 * @param {Object} task
12698 this.start = function(task){
12700 task.taskStartTime = new Date().getTime();
12701 task.taskRunTime = 0;
12702 task.taskRunCount = 0;
12707 this.stop = function(task){
12712 this.stopAll = function(){
12714 for(var i = 0, len = tasks.length; i < len; i++){
12715 if(tasks[i].onStop){
12724 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12726 * Ext JS Library 1.1.1
12727 * Copyright(c) 2006-2007, Ext JS, LLC.
12729 * Originally Released Under LGPL - original licence link has changed is not relivant.
12732 * <script type="text/javascript">
12737 * @class Roo.util.MixedCollection
12738 * @extends Roo.util.Observable
12739 * A Collection class that maintains both numeric indexes and keys and exposes events.
12741 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12742 * collection (defaults to false)
12743 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12744 * and return the key value for that item. This is used when available to look up the key on items that
12745 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12746 * equivalent to providing an implementation for the {@link #getKey} method.
12748 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12756 * Fires when the collection is cleared.
12761 * Fires when an item is added to the collection.
12762 * @param {Number} index The index at which the item was added.
12763 * @param {Object} o The item added.
12764 * @param {String} key The key associated with the added item.
12769 * Fires when an item is replaced in the collection.
12770 * @param {String} key he key associated with the new added.
12771 * @param {Object} old The item being replaced.
12772 * @param {Object} new The new item.
12777 * Fires when an item is removed from the collection.
12778 * @param {Object} o The item being removed.
12779 * @param {String} key (optional) The key associated with the removed item.
12784 this.allowFunctions = allowFunctions === true;
12786 this.getKey = keyFn;
12788 Roo.util.MixedCollection.superclass.constructor.call(this);
12791 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12792 allowFunctions : false,
12795 * Adds an item to the collection.
12796 * @param {String} key The key to associate with the item
12797 * @param {Object} o The item to add.
12798 * @return {Object} The item added.
12800 add : function(key, o){
12801 if(arguments.length == 1){
12803 key = this.getKey(o);
12805 if(typeof key == "undefined" || key === null){
12807 this.items.push(o);
12808 this.keys.push(null);
12810 var old = this.map[key];
12812 return this.replace(key, o);
12815 this.items.push(o);
12817 this.keys.push(key);
12819 this.fireEvent("add", this.length-1, o, key);
12824 * MixedCollection has a generic way to fetch keys if you implement getKey.
12827 var mc = new Roo.util.MixedCollection();
12828 mc.add(someEl.dom.id, someEl);
12829 mc.add(otherEl.dom.id, otherEl);
12833 var mc = new Roo.util.MixedCollection();
12834 mc.getKey = function(el){
12840 // or via the constructor
12841 var mc = new Roo.util.MixedCollection(false, function(el){
12847 * @param o {Object} The item for which to find the key.
12848 * @return {Object} The key for the passed item.
12850 getKey : function(o){
12855 * Replaces an item in the collection.
12856 * @param {String} key The key associated with the item to replace, or the item to replace.
12857 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12858 * @return {Object} The new item.
12860 replace : function(key, o){
12861 if(arguments.length == 1){
12863 key = this.getKey(o);
12865 var old = this.item(key);
12866 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12867 return this.add(key, o);
12869 var index = this.indexOfKey(key);
12870 this.items[index] = o;
12872 this.fireEvent("replace", key, old, o);
12877 * Adds all elements of an Array or an Object to the collection.
12878 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12879 * an Array of values, each of which are added to the collection.
12881 addAll : function(objs){
12882 if(arguments.length > 1 || objs instanceof Array){
12883 var args = arguments.length > 1 ? arguments : objs;
12884 for(var i = 0, len = args.length; i < len; i++){
12888 for(var key in objs){
12889 if(this.allowFunctions || typeof objs[key] != "function"){
12890 this.add(key, objs[key]);
12897 * Executes the specified function once for every item in the collection, passing each
12898 * item as the first and only parameter. returning false from the function will stop the iteration.
12899 * @param {Function} fn The function to execute for each item.
12900 * @param {Object} scope (optional) The scope in which to execute the function.
12902 each : function(fn, scope){
12903 var items = [].concat(this.items); // each safe for removal
12904 for(var i = 0, len = items.length; i < len; i++){
12905 if(fn.call(scope || items[i], items[i], i, len) === false){
12912 * Executes the specified function once for every key in the collection, passing each
12913 * key, and its associated item as the first two parameters.
12914 * @param {Function} fn The function to execute for each item.
12915 * @param {Object} scope (optional) The scope in which to execute the function.
12917 eachKey : function(fn, scope){
12918 for(var i = 0, len = this.keys.length; i < len; i++){
12919 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12924 * Returns the first item in the collection which elicits a true return value from the
12925 * passed selection function.
12926 * @param {Function} fn The selection function to execute for each item.
12927 * @param {Object} scope (optional) The scope in which to execute the function.
12928 * @return {Object} The first item in the collection which returned true from the selection function.
12930 find : function(fn, scope){
12931 for(var i = 0, len = this.items.length; i < len; i++){
12932 if(fn.call(scope || window, this.items[i], this.keys[i])){
12933 return this.items[i];
12940 * Inserts an item at the specified index in the collection.
12941 * @param {Number} index The index to insert the item at.
12942 * @param {String} key The key to associate with the new item, or the item itself.
12943 * @param {Object} o (optional) If the second parameter was a key, the new item.
12944 * @return {Object} The item inserted.
12946 insert : function(index, key, o){
12947 if(arguments.length == 2){
12949 key = this.getKey(o);
12951 if(index >= this.length){
12952 return this.add(key, o);
12955 this.items.splice(index, 0, o);
12956 if(typeof key != "undefined" && key != null){
12959 this.keys.splice(index, 0, key);
12960 this.fireEvent("add", index, o, key);
12965 * Removed an item from the collection.
12966 * @param {Object} o The item to remove.
12967 * @return {Object} The item removed.
12969 remove : function(o){
12970 return this.removeAt(this.indexOf(o));
12974 * Remove an item from a specified index in the collection.
12975 * @param {Number} index The index within the collection of the item to remove.
12977 removeAt : function(index){
12978 if(index < this.length && index >= 0){
12980 var o = this.items[index];
12981 this.items.splice(index, 1);
12982 var key = this.keys[index];
12983 if(typeof key != "undefined"){
12984 delete this.map[key];
12986 this.keys.splice(index, 1);
12987 this.fireEvent("remove", o, key);
12992 * Removed an item associated with the passed key fom the collection.
12993 * @param {String} key The key of the item to remove.
12995 removeKey : function(key){
12996 return this.removeAt(this.indexOfKey(key));
13000 * Returns the number of items in the collection.
13001 * @return {Number} the number of items in the collection.
13003 getCount : function(){
13004 return this.length;
13008 * Returns index within the collection of the passed Object.
13009 * @param {Object} o The item to find the index of.
13010 * @return {Number} index of the item.
13012 indexOf : function(o){
13013 if(!this.items.indexOf){
13014 for(var i = 0, len = this.items.length; i < len; i++){
13015 if(this.items[i] == o) return i;
13019 return this.items.indexOf(o);
13024 * Returns index within the collection of the passed key.
13025 * @param {String} key The key to find the index of.
13026 * @return {Number} index of the key.
13028 indexOfKey : function(key){
13029 if(!this.keys.indexOf){
13030 for(var i = 0, len = this.keys.length; i < len; i++){
13031 if(this.keys[i] == key) return i;
13035 return this.keys.indexOf(key);
13040 * Returns the item associated with the passed key OR index. Key has priority over index.
13041 * @param {String/Number} key The key or index of the item.
13042 * @return {Object} The item associated with the passed key.
13044 item : function(key){
13045 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13046 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13050 * Returns the item at the specified index.
13051 * @param {Number} index The index of the item.
13054 itemAt : function(index){
13055 return this.items[index];
13059 * Returns the item associated with the passed key.
13060 * @param {String/Number} key The key of the item.
13061 * @return {Object} The item associated with the passed key.
13063 key : function(key){
13064 return this.map[key];
13068 * Returns true if the collection contains the passed Object as an item.
13069 * @param {Object} o The Object to look for in the collection.
13070 * @return {Boolean} True if the collection contains the Object as an item.
13072 contains : function(o){
13073 return this.indexOf(o) != -1;
13077 * Returns true if the collection contains the passed Object as a key.
13078 * @param {String} key The key to look for in the collection.
13079 * @return {Boolean} True if the collection contains the Object as a key.
13081 containsKey : function(key){
13082 return typeof this.map[key] != "undefined";
13086 * Removes all items from the collection.
13088 clear : function(){
13093 this.fireEvent("clear");
13097 * Returns the first item in the collection.
13098 * @return {Object} the first item in the collection..
13100 first : function(){
13101 return this.items[0];
13105 * Returns the last item in the collection.
13106 * @return {Object} the last item in the collection..
13109 return this.items[this.length-1];
13112 _sort : function(property, dir, fn){
13113 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13114 fn = fn || function(a, b){
13117 var c = [], k = this.keys, items = this.items;
13118 for(var i = 0, len = items.length; i < len; i++){
13119 c[c.length] = {key: k[i], value: items[i], index: i};
13121 c.sort(function(a, b){
13122 var v = fn(a[property], b[property]) * dsc;
13124 v = (a.index < b.index ? -1 : 1);
13128 for(var i = 0, len = c.length; i < len; i++){
13129 items[i] = c[i].value;
13132 this.fireEvent("sort", this);
13136 * Sorts this collection with the passed comparison function
13137 * @param {String} direction (optional) "ASC" or "DESC"
13138 * @param {Function} fn (optional) comparison function
13140 sort : function(dir, fn){
13141 this._sort("value", dir, fn);
13145 * Sorts this collection by keys
13146 * @param {String} direction (optional) "ASC" or "DESC"
13147 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13149 keySort : function(dir, fn){
13150 this._sort("key", dir, fn || function(a, b){
13151 return String(a).toUpperCase()-String(b).toUpperCase();
13156 * Returns a range of items in this collection
13157 * @param {Number} startIndex (optional) defaults to 0
13158 * @param {Number} endIndex (optional) default to the last item
13159 * @return {Array} An array of items
13161 getRange : function(start, end){
13162 var items = this.items;
13163 if(items.length < 1){
13166 start = start || 0;
13167 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13170 for(var i = start; i <= end; i++) {
13171 r[r.length] = items[i];
13174 for(var i = start; i >= end; i--) {
13175 r[r.length] = items[i];
13182 * Filter the <i>objects</i> in this collection by a specific property.
13183 * Returns a new collection that has been filtered.
13184 * @param {String} property A property on your objects
13185 * @param {String/RegExp} value Either string that the property values
13186 * should start with or a RegExp to test against the property
13187 * @return {MixedCollection} The new filtered collection
13189 filter : function(property, value){
13190 if(!value.exec){ // not a regex
13191 value = String(value);
13192 if(value.length == 0){
13193 return this.clone();
13195 value = new RegExp("^" + Roo.escapeRe(value), "i");
13197 return this.filterBy(function(o){
13198 return o && value.test(o[property]);
13203 * Filter by a function. * Returns a new collection that has been filtered.
13204 * The passed function will be called with each
13205 * object in the collection. If the function returns true, the value is included
13206 * otherwise it is filtered.
13207 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13208 * @param {Object} scope (optional) The scope of the function (defaults to this)
13209 * @return {MixedCollection} The new filtered collection
13211 filterBy : function(fn, scope){
13212 var r = new Roo.util.MixedCollection();
13213 r.getKey = this.getKey;
13214 var k = this.keys, it = this.items;
13215 for(var i = 0, len = it.length; i < len; i++){
13216 if(fn.call(scope||this, it[i], k[i])){
13217 r.add(k[i], it[i]);
13224 * Creates a duplicate of this collection
13225 * @return {MixedCollection}
13227 clone : function(){
13228 var r = new Roo.util.MixedCollection();
13229 var k = this.keys, it = this.items;
13230 for(var i = 0, len = it.length; i < len; i++){
13231 r.add(k[i], it[i]);
13233 r.getKey = this.getKey;
13238 * Returns the item associated with the passed key or index.
13240 * @param {String/Number} key The key or index of the item.
13241 * @return {Object} The item associated with the passed key.
13243 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13245 * Ext JS Library 1.1.1
13246 * Copyright(c) 2006-2007, Ext JS, LLC.
13248 * Originally Released Under LGPL - original licence link has changed is not relivant.
13251 * <script type="text/javascript">
13254 * @class Roo.util.JSON
13255 * Modified version of Douglas Crockford"s json.js that doesn"t
13256 * mess with the Object prototype
13257 * http://www.json.org/js.html
13260 Roo.util.JSON = new (function(){
13261 var useHasOwn = {}.hasOwnProperty ? true : false;
13263 // crashes Safari in some instances
13264 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13266 var pad = function(n) {
13267 return n < 10 ? "0" + n : n;
13280 var encodeString = function(s){
13281 if (/["\\\x00-\x1f]/.test(s)) {
13282 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13287 c = b.charCodeAt();
13289 Math.floor(c / 16).toString(16) +
13290 (c % 16).toString(16);
13293 return '"' + s + '"';
13296 var encodeArray = function(o){
13297 var a = ["["], b, i, l = o.length, v;
13298 for (i = 0; i < l; i += 1) {
13300 switch (typeof v) {
13309 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13317 var encodeDate = function(o){
13318 return '"' + o.getFullYear() + "-" +
13319 pad(o.getMonth() + 1) + "-" +
13320 pad(o.getDate()) + "T" +
13321 pad(o.getHours()) + ":" +
13322 pad(o.getMinutes()) + ":" +
13323 pad(o.getSeconds()) + '"';
13327 * Encodes an Object, Array or other value
13328 * @param {Mixed} o The variable to encode
13329 * @return {String} The JSON string
13331 this.encode = function(o)
13333 // should this be extended to fully wrap stringify..
13335 if(typeof o == "undefined" || o === null){
13337 }else if(o instanceof Array){
13338 return encodeArray(o);
13339 }else if(o instanceof Date){
13340 return encodeDate(o);
13341 }else if(typeof o == "string"){
13342 return encodeString(o);
13343 }else if(typeof o == "number"){
13344 return isFinite(o) ? String(o) : "null";
13345 }else if(typeof o == "boolean"){
13348 var a = ["{"], b, i, v;
13350 if(!useHasOwn || o.hasOwnProperty(i)) {
13352 switch (typeof v) {
13361 a.push(this.encode(i), ":",
13362 v === null ? "null" : this.encode(v));
13373 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13374 * @param {String} json The JSON string
13375 * @return {Object} The resulting object
13377 this.decode = function(json){
13379 return /** eval:var:json */ eval("(" + json + ')');
13383 * Shorthand for {@link Roo.util.JSON#encode}
13384 * @member Roo encode
13386 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13388 * Shorthand for {@link Roo.util.JSON#decode}
13389 * @member Roo decode
13391 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13394 * Ext JS Library 1.1.1
13395 * Copyright(c) 2006-2007, Ext JS, LLC.
13397 * Originally Released Under LGPL - original licence link has changed is not relivant.
13400 * <script type="text/javascript">
13404 * @class Roo.util.Format
13405 * Reusable data formatting functions
13408 Roo.util.Format = function(){
13409 var trimRe = /^\s+|\s+$/g;
13412 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13413 * @param {String} value The string to truncate
13414 * @param {Number} length The maximum length to allow before truncating
13415 * @return {String} The converted text
13417 ellipsis : function(value, len){
13418 if(value && value.length > len){
13419 return value.substr(0, len-3)+"...";
13425 * Checks a reference and converts it to empty string if it is undefined
13426 * @param {Mixed} value Reference to check
13427 * @return {Mixed} Empty string if converted, otherwise the original value
13429 undef : function(value){
13430 return typeof value != "undefined" ? value : "";
13434 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13435 * @param {String} value The string to encode
13436 * @return {String} The encoded text
13438 htmlEncode : function(value){
13439 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13443 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13444 * @param {String} value The string to decode
13445 * @return {String} The decoded text
13447 htmlDecode : function(value){
13448 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13452 * Trims any whitespace from either side of a string
13453 * @param {String} value The text to trim
13454 * @return {String} The trimmed text
13456 trim : function(value){
13457 return String(value).replace(trimRe, "");
13461 * Returns a substring from within an original string
13462 * @param {String} value The original text
13463 * @param {Number} start The start index of the substring
13464 * @param {Number} length The length of the substring
13465 * @return {String} The substring
13467 substr : function(value, start, length){
13468 return String(value).substr(start, length);
13472 * Converts a string to all lower case letters
13473 * @param {String} value The text to convert
13474 * @return {String} The converted text
13476 lowercase : function(value){
13477 return String(value).toLowerCase();
13481 * Converts a string to all upper case letters
13482 * @param {String} value The text to convert
13483 * @return {String} The converted text
13485 uppercase : function(value){
13486 return String(value).toUpperCase();
13490 * Converts the first character only of a string to upper case
13491 * @param {String} value The text to convert
13492 * @return {String} The converted text
13494 capitalize : function(value){
13495 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13499 call : function(value, fn){
13500 if(arguments.length > 2){
13501 var args = Array.prototype.slice.call(arguments, 2);
13502 args.unshift(value);
13504 return /** eval:var:value */ eval(fn).apply(window, args);
13506 /** eval:var:value */
13507 return /** eval:var:value */ eval(fn).call(window, value);
13513 * safer version of Math.toFixed..??/
13514 * @param {Number/String} value The numeric value to format
13515 * @param {Number/String} value Decimal places
13516 * @return {String} The formatted currency string
13518 toFixed : function(v, n)
13520 // why not use to fixed - precision is buggered???
13522 return Math.round(v-0);
13524 var fact = Math.pow(10,n+1);
13525 v = (Math.round((v-0)*fact))/fact;
13526 var z = (''+fact).substring(2);
13527 if (v == Math.floor(v)) {
13528 return Math.floor(v) + '.' + z;
13531 // now just padd decimals..
13532 var ps = String(v).split('.');
13533 var fd = (ps[1] + z);
13534 var r = fd.substring(0,n);
13535 var rm = fd.substring(n);
13537 return ps[0] + '.' + r;
13539 r*=1; // turn it into a number;
13541 if (String(r).length != n) {
13544 r = String(r).substring(1); // chop the end off.
13547 return ps[0] + '.' + r;
13552 * Format a number as US currency
13553 * @param {Number/String} value The numeric value to format
13554 * @return {String} The formatted currency string
13556 usMoney : function(v){
13557 return '$' + Roo.util.Format.number(v);
13562 * eventually this should probably emulate php's number_format
13563 * @param {Number/String} value The numeric value to format
13564 * @param {Number} decimals number of decimal places
13565 * @return {String} The formatted currency string
13567 number : function(v,decimals)
13569 // multiply and round.
13570 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13571 var mul = Math.pow(10, decimals);
13572 var zero = String(mul).substring(1);
13573 v = (Math.round((v-0)*mul))/mul;
13575 // if it's '0' number.. then
13577 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13579 var ps = v.split('.');
13583 var r = /(\d+)(\d{3})/;
13585 while (r.test(whole)) {
13586 whole = whole.replace(r, '$1' + ',' + '$2');
13592 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13593 // does not have decimals
13594 (decimals ? ('.' + zero) : '');
13597 return whole + sub ;
13601 * Parse a value into a formatted date using the specified format pattern.
13602 * @param {Mixed} value The value to format
13603 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13604 * @return {String} The formatted date string
13606 date : function(v, format){
13610 if(!(v instanceof Date)){
13611 v = new Date(Date.parse(v));
13613 return v.dateFormat(format || Roo.util.Format.defaults.date);
13617 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13618 * @param {String} format Any valid date format string
13619 * @return {Function} The date formatting function
13621 dateRenderer : function(format){
13622 return function(v){
13623 return Roo.util.Format.date(v, format);
13628 stripTagsRE : /<\/?[^>]+>/gi,
13631 * Strips all HTML tags
13632 * @param {Mixed} value The text from which to strip tags
13633 * @return {String} The stripped text
13635 stripTags : function(v){
13636 return !v ? v : String(v).replace(this.stripTagsRE, "");
13640 Roo.util.Format.defaults = {
13644 * Ext JS Library 1.1.1
13645 * Copyright(c) 2006-2007, Ext JS, LLC.
13647 * Originally Released Under LGPL - original licence link has changed is not relivant.
13650 * <script type="text/javascript">
13657 * @class Roo.MasterTemplate
13658 * @extends Roo.Template
13659 * Provides a template that can have child templates. The syntax is:
13661 var t = new Roo.MasterTemplate(
13662 '<select name="{name}">',
13663 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13666 t.add('options', {value: 'foo', text: 'bar'});
13667 // or you can add multiple child elements in one shot
13668 t.addAll('options', [
13669 {value: 'foo', text: 'bar'},
13670 {value: 'foo2', text: 'bar2'},
13671 {value: 'foo3', text: 'bar3'}
13673 // then append, applying the master template values
13674 t.append('my-form', {name: 'my-select'});
13676 * A name attribute for the child template is not required if you have only one child
13677 * template or you want to refer to them by index.
13679 Roo.MasterTemplate = function(){
13680 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13681 this.originalHtml = this.html;
13683 var m, re = this.subTemplateRe;
13686 while(m = re.exec(this.html)){
13687 var name = m[1], content = m[2];
13692 tpl : new Roo.Template(content)
13695 st[name] = st[subIndex];
13697 st[subIndex].tpl.compile();
13698 st[subIndex].tpl.call = this.call.createDelegate(this);
13701 this.subCount = subIndex;
13704 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13706 * The regular expression used to match sub templates
13710 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13713 * Applies the passed values to a child template.
13714 * @param {String/Number} name (optional) The name or index of the child template
13715 * @param {Array/Object} values The values to be applied to the template
13716 * @return {MasterTemplate} this
13718 add : function(name, values){
13719 if(arguments.length == 1){
13720 values = arguments[0];
13723 var s = this.subs[name];
13724 s.buffer[s.buffer.length] = s.tpl.apply(values);
13729 * Applies all the passed values to a child template.
13730 * @param {String/Number} name (optional) The name or index of the child template
13731 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13732 * @param {Boolean} reset (optional) True to reset the template first
13733 * @return {MasterTemplate} this
13735 fill : function(name, values, reset){
13737 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13745 for(var i = 0, len = values.length; i < len; i++){
13746 this.add(name, values[i]);
13752 * Resets the template for reuse
13753 * @return {MasterTemplate} this
13755 reset : function(){
13757 for(var i = 0; i < this.subCount; i++){
13763 applyTemplate : function(values){
13765 var replaceIndex = -1;
13766 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13767 return s[++replaceIndex].buffer.join("");
13769 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13772 apply : function(){
13773 return this.applyTemplate.apply(this, arguments);
13776 compile : function(){return this;}
13780 * Alias for fill().
13783 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13785 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13786 * var tpl = Roo.MasterTemplate.from('element-id');
13787 * @param {String/HTMLElement} el
13788 * @param {Object} config
13791 Roo.MasterTemplate.from = function(el, config){
13792 el = Roo.getDom(el);
13793 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13796 * Ext JS Library 1.1.1
13797 * Copyright(c) 2006-2007, Ext JS, LLC.
13799 * Originally Released Under LGPL - original licence link has changed is not relivant.
13802 * <script type="text/javascript">
13807 * @class Roo.util.CSS
13808 * Utility class for manipulating CSS rules
13811 Roo.util.CSS = function(){
13813 var doc = document;
13815 var camelRe = /(-[a-z])/gi;
13816 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13820 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13821 * tag and appended to the HEAD of the document.
13822 * @param {String|Object} cssText The text containing the css rules
13823 * @param {String} id An id to add to the stylesheet for later removal
13824 * @return {StyleSheet}
13826 createStyleSheet : function(cssText, id){
13828 var head = doc.getElementsByTagName("head")[0];
13829 var nrules = doc.createElement("style");
13830 nrules.setAttribute("type", "text/css");
13832 nrules.setAttribute("id", id);
13834 if (typeof(cssText) != 'string') {
13835 // support object maps..
13836 // not sure if this a good idea..
13837 // perhaps it should be merged with the general css handling
13838 // and handle js style props.
13839 var cssTextNew = [];
13840 for(var n in cssText) {
13842 for(var k in cssText[n]) {
13843 citems.push( k + ' : ' +cssText[n][k] + ';' );
13845 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13848 cssText = cssTextNew.join("\n");
13854 head.appendChild(nrules);
13855 ss = nrules.styleSheet;
13856 ss.cssText = cssText;
13859 nrules.appendChild(doc.createTextNode(cssText));
13861 nrules.cssText = cssText;
13863 head.appendChild(nrules);
13864 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13866 this.cacheStyleSheet(ss);
13871 * Removes a style or link tag by id
13872 * @param {String} id The id of the tag
13874 removeStyleSheet : function(id){
13875 var existing = doc.getElementById(id);
13877 existing.parentNode.removeChild(existing);
13882 * Dynamically swaps an existing stylesheet reference for a new one
13883 * @param {String} id The id of an existing link tag to remove
13884 * @param {String} url The href of the new stylesheet to include
13886 swapStyleSheet : function(id, url){
13887 this.removeStyleSheet(id);
13888 var ss = doc.createElement("link");
13889 ss.setAttribute("rel", "stylesheet");
13890 ss.setAttribute("type", "text/css");
13891 ss.setAttribute("id", id);
13892 ss.setAttribute("href", url);
13893 doc.getElementsByTagName("head")[0].appendChild(ss);
13897 * Refresh the rule cache if you have dynamically added stylesheets
13898 * @return {Object} An object (hash) of rules indexed by selector
13900 refreshCache : function(){
13901 return this.getRules(true);
13905 cacheStyleSheet : function(stylesheet){
13909 try{// try catch for cross domain access issue
13910 var ssRules = stylesheet.cssRules || stylesheet.rules;
13911 for(var j = ssRules.length-1; j >= 0; --j){
13912 rules[ssRules[j].selectorText] = ssRules[j];
13918 * Gets all css rules for the document
13919 * @param {Boolean} refreshCache true to refresh the internal cache
13920 * @return {Object} An object (hash) of rules indexed by selector
13922 getRules : function(refreshCache){
13923 if(rules == null || refreshCache){
13925 var ds = doc.styleSheets;
13926 for(var i =0, len = ds.length; i < len; i++){
13928 this.cacheStyleSheet(ds[i]);
13936 * Gets an an individual CSS rule by selector(s)
13937 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13938 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13939 * @return {CSSRule} The CSS rule or null if one is not found
13941 getRule : function(selector, refreshCache){
13942 var rs = this.getRules(refreshCache);
13943 if(!(selector instanceof Array)){
13944 return rs[selector];
13946 for(var i = 0; i < selector.length; i++){
13947 if(rs[selector[i]]){
13948 return rs[selector[i]];
13956 * Updates a rule property
13957 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13958 * @param {String} property The css property
13959 * @param {String} value The new value for the property
13960 * @return {Boolean} true If a rule was found and updated
13962 updateRule : function(selector, property, value){
13963 if(!(selector instanceof Array)){
13964 var rule = this.getRule(selector);
13966 rule.style[property.replace(camelRe, camelFn)] = value;
13970 for(var i = 0; i < selector.length; i++){
13971 if(this.updateRule(selector[i], property, value)){
13981 * Ext JS Library 1.1.1
13982 * Copyright(c) 2006-2007, Ext JS, LLC.
13984 * Originally Released Under LGPL - original licence link has changed is not relivant.
13987 * <script type="text/javascript">
13993 * @class Roo.util.ClickRepeater
13994 * @extends Roo.util.Observable
13996 * A wrapper class which can be applied to any element. Fires a "click" event while the
13997 * mouse is pressed. The interval between firings may be specified in the config but
13998 * defaults to 10 milliseconds.
14000 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14002 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14003 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14004 * Similar to an autorepeat key delay.
14005 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14006 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14007 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14008 * "interval" and "delay" are ignored. "immediate" is honored.
14009 * @cfg {Boolean} preventDefault True to prevent the default click event
14010 * @cfg {Boolean} stopDefault True to stop the default click event
14013 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14014 * 2007-02-02 jvs Renamed to ClickRepeater
14015 * 2007-02-03 jvs Modifications for FF Mac and Safari
14018 * @param {String/HTMLElement/Element} el The element to listen on
14019 * @param {Object} config
14021 Roo.util.ClickRepeater = function(el, config)
14023 this.el = Roo.get(el);
14024 this.el.unselectable();
14026 Roo.apply(this, config);
14031 * Fires when the mouse button is depressed.
14032 * @param {Roo.util.ClickRepeater} this
14034 "mousedown" : true,
14037 * Fires on a specified interval during the time the element is pressed.
14038 * @param {Roo.util.ClickRepeater} this
14043 * Fires when the mouse key is released.
14044 * @param {Roo.util.ClickRepeater} this
14049 this.el.on("mousedown", this.handleMouseDown, this);
14050 if(this.preventDefault || this.stopDefault){
14051 this.el.on("click", function(e){
14052 if(this.preventDefault){
14053 e.preventDefault();
14055 if(this.stopDefault){
14061 // allow inline handler
14063 this.on("click", this.handler, this.scope || this);
14066 Roo.util.ClickRepeater.superclass.constructor.call(this);
14069 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14072 preventDefault : true,
14073 stopDefault : false,
14077 handleMouseDown : function(){
14078 clearTimeout(this.timer);
14080 if(this.pressClass){
14081 this.el.addClass(this.pressClass);
14083 this.mousedownTime = new Date();
14085 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14086 this.el.on("mouseout", this.handleMouseOut, this);
14088 this.fireEvent("mousedown", this);
14089 this.fireEvent("click", this);
14091 this.timer = this.click.defer(this.delay || this.interval, this);
14095 click : function(){
14096 this.fireEvent("click", this);
14097 this.timer = this.click.defer(this.getInterval(), this);
14101 getInterval: function(){
14102 if(!this.accelerate){
14103 return this.interval;
14105 var pressTime = this.mousedownTime.getElapsed();
14106 if(pressTime < 500){
14108 }else if(pressTime < 1700){
14110 }else if(pressTime < 2600){
14112 }else if(pressTime < 3500){
14114 }else if(pressTime < 4400){
14116 }else if(pressTime < 5300){
14118 }else if(pressTime < 6200){
14126 handleMouseOut : function(){
14127 clearTimeout(this.timer);
14128 if(this.pressClass){
14129 this.el.removeClass(this.pressClass);
14131 this.el.on("mouseover", this.handleMouseReturn, this);
14135 handleMouseReturn : function(){
14136 this.el.un("mouseover", this.handleMouseReturn);
14137 if(this.pressClass){
14138 this.el.addClass(this.pressClass);
14144 handleMouseUp : function(){
14145 clearTimeout(this.timer);
14146 this.el.un("mouseover", this.handleMouseReturn);
14147 this.el.un("mouseout", this.handleMouseOut);
14148 Roo.get(document).un("mouseup", this.handleMouseUp);
14149 this.el.removeClass(this.pressClass);
14150 this.fireEvent("mouseup", this);
14154 * Ext JS Library 1.1.1
14155 * Copyright(c) 2006-2007, Ext JS, LLC.
14157 * Originally Released Under LGPL - original licence link has changed is not relivant.
14160 * <script type="text/javascript">
14165 * @class Roo.KeyNav
14166 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14167 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14168 * way to implement custom navigation schemes for any UI component.</p>
14169 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14170 * pageUp, pageDown, del, home, end. Usage:</p>
14172 var nav = new Roo.KeyNav("my-element", {
14173 "left" : function(e){
14174 this.moveLeft(e.ctrlKey);
14176 "right" : function(e){
14177 this.moveRight(e.ctrlKey);
14179 "enter" : function(e){
14186 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14187 * @param {Object} config The config
14189 Roo.KeyNav = function(el, config){
14190 this.el = Roo.get(el);
14191 Roo.apply(this, config);
14192 if(!this.disabled){
14193 this.disabled = true;
14198 Roo.KeyNav.prototype = {
14200 * @cfg {Boolean} disabled
14201 * True to disable this KeyNav instance (defaults to false)
14205 * @cfg {String} defaultEventAction
14206 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14207 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14208 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14210 defaultEventAction: "stopEvent",
14212 * @cfg {Boolean} forceKeyDown
14213 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14214 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14215 * handle keydown instead of keypress.
14217 forceKeyDown : false,
14220 prepareEvent : function(e){
14221 var k = e.getKey();
14222 var h = this.keyToHandler[k];
14223 //if(h && this[h]){
14224 // e.stopPropagation();
14226 if(Roo.isSafari && h && k >= 37 && k <= 40){
14232 relay : function(e){
14233 var k = e.getKey();
14234 var h = this.keyToHandler[k];
14236 if(this.doRelay(e, this[h], h) !== true){
14237 e[this.defaultEventAction]();
14243 doRelay : function(e, h, hname){
14244 return h.call(this.scope || this, e);
14247 // possible handlers
14261 // quick lookup hash
14278 * Enable this KeyNav
14280 enable: function(){
14282 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14283 // the EventObject will normalize Safari automatically
14284 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14285 this.el.on("keydown", this.relay, this);
14287 this.el.on("keydown", this.prepareEvent, this);
14288 this.el.on("keypress", this.relay, this);
14290 this.disabled = false;
14295 * Disable this KeyNav
14297 disable: function(){
14298 if(!this.disabled){
14299 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14300 this.el.un("keydown", this.relay);
14302 this.el.un("keydown", this.prepareEvent);
14303 this.el.un("keypress", this.relay);
14305 this.disabled = true;
14310 * Ext JS Library 1.1.1
14311 * Copyright(c) 2006-2007, Ext JS, LLC.
14313 * Originally Released Under LGPL - original licence link has changed is not relivant.
14316 * <script type="text/javascript">
14321 * @class Roo.KeyMap
14322 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14323 * The constructor accepts the same config object as defined by {@link #addBinding}.
14324 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14325 * combination it will call the function with this signature (if the match is a multi-key
14326 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14327 * A KeyMap can also handle a string representation of keys.<br />
14330 // map one key by key code
14331 var map = new Roo.KeyMap("my-element", {
14332 key: 13, // or Roo.EventObject.ENTER
14337 // map multiple keys to one action by string
14338 var map = new Roo.KeyMap("my-element", {
14344 // map multiple keys to multiple actions by strings and array of codes
14345 var map = new Roo.KeyMap("my-element", [
14348 fn: function(){ alert("Return was pressed"); }
14351 fn: function(){ alert('a, b or c was pressed'); }
14356 fn: function(){ alert('Control + shift + tab was pressed.'); }
14360 * <b>Note: A KeyMap starts enabled</b>
14362 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14363 * @param {Object} config The config (see {@link #addBinding})
14364 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14366 Roo.KeyMap = function(el, config, eventName){
14367 this.el = Roo.get(el);
14368 this.eventName = eventName || "keydown";
14369 this.bindings = [];
14371 this.addBinding(config);
14376 Roo.KeyMap.prototype = {
14378 * True to stop the event from bubbling and prevent the default browser action if the
14379 * key was handled by the KeyMap (defaults to false)
14385 * Add a new binding to this KeyMap. The following config object properties are supported:
14387 Property Type Description
14388 ---------- --------------- ----------------------------------------------------------------------
14389 key String/Array A single keycode or an array of keycodes to handle
14390 shift Boolean True to handle key only when shift is pressed (defaults to false)
14391 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14392 alt Boolean True to handle key only when alt is pressed (defaults to false)
14393 fn Function The function to call when KeyMap finds the expected key combination
14394 scope Object The scope of the callback function
14400 var map = new Roo.KeyMap(document, {
14401 key: Roo.EventObject.ENTER,
14406 //Add a new binding to the existing KeyMap later
14414 * @param {Object/Array} config A single KeyMap config or an array of configs
14416 addBinding : function(config){
14417 if(config instanceof Array){
14418 for(var i = 0, len = config.length; i < len; i++){
14419 this.addBinding(config[i]);
14423 var keyCode = config.key,
14424 shift = config.shift,
14425 ctrl = config.ctrl,
14428 scope = config.scope;
14429 if(typeof keyCode == "string"){
14431 var keyString = keyCode.toUpperCase();
14432 for(var j = 0, len = keyString.length; j < len; j++){
14433 ks.push(keyString.charCodeAt(j));
14437 var keyArray = keyCode instanceof Array;
14438 var handler = function(e){
14439 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14440 var k = e.getKey();
14442 for(var i = 0, len = keyCode.length; i < len; i++){
14443 if(keyCode[i] == k){
14444 if(this.stopEvent){
14447 fn.call(scope || window, k, e);
14453 if(this.stopEvent){
14456 fn.call(scope || window, k, e);
14461 this.bindings.push(handler);
14465 * Shorthand for adding a single key listener
14466 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14467 * following options:
14468 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14469 * @param {Function} fn The function to call
14470 * @param {Object} scope (optional) The scope of the function
14472 on : function(key, fn, scope){
14473 var keyCode, shift, ctrl, alt;
14474 if(typeof key == "object" && !(key instanceof Array)){
14493 handleKeyDown : function(e){
14494 if(this.enabled){ //just in case
14495 var b = this.bindings;
14496 for(var i = 0, len = b.length; i < len; i++){
14497 b[i].call(this, e);
14503 * Returns true if this KeyMap is enabled
14504 * @return {Boolean}
14506 isEnabled : function(){
14507 return this.enabled;
14511 * Enables this KeyMap
14513 enable: function(){
14515 this.el.on(this.eventName, this.handleKeyDown, this);
14516 this.enabled = true;
14521 * Disable this KeyMap
14523 disable: function(){
14525 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14526 this.enabled = false;
14531 * Ext JS Library 1.1.1
14532 * Copyright(c) 2006-2007, Ext JS, LLC.
14534 * Originally Released Under LGPL - original licence link has changed is not relivant.
14537 * <script type="text/javascript">
14542 * @class Roo.util.TextMetrics
14543 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14544 * wide, in pixels, a given block of text will be.
14547 Roo.util.TextMetrics = function(){
14551 * Measures the size of the specified text
14552 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14553 * that can affect the size of the rendered text
14554 * @param {String} text The text to measure
14555 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14556 * in order to accurately measure the text height
14557 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14559 measure : function(el, text, fixedWidth){
14561 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14564 shared.setFixedWidth(fixedWidth || 'auto');
14565 return shared.getSize(text);
14569 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14570 * the overhead of multiple calls to initialize the style properties on each measurement.
14571 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14572 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14573 * in order to accurately measure the text height
14574 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14576 createInstance : function(el, fixedWidth){
14577 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14584 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14585 var ml = new Roo.Element(document.createElement('div'));
14586 document.body.appendChild(ml.dom);
14587 ml.position('absolute');
14588 ml.setLeftTop(-1000, -1000);
14592 ml.setWidth(fixedWidth);
14597 * Returns the size of the specified text based on the internal element's style and width properties
14598 * @memberOf Roo.util.TextMetrics.Instance#
14599 * @param {String} text The text to measure
14600 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14602 getSize : function(text){
14604 var s = ml.getSize();
14610 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14611 * that can affect the size of the rendered text
14612 * @memberOf Roo.util.TextMetrics.Instance#
14613 * @param {String/HTMLElement} el The element, dom node or id
14615 bind : function(el){
14617 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14622 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14623 * to set a fixed width in order to accurately measure the text height.
14624 * @memberOf Roo.util.TextMetrics.Instance#
14625 * @param {Number} width The width to set on the element
14627 setFixedWidth : function(width){
14628 ml.setWidth(width);
14632 * Returns the measured width of the specified text
14633 * @memberOf Roo.util.TextMetrics.Instance#
14634 * @param {String} text The text to measure
14635 * @return {Number} width The width in pixels
14637 getWidth : function(text){
14638 ml.dom.style.width = 'auto';
14639 return this.getSize(text).width;
14643 * Returns the measured height of the specified text. For multiline text, be sure to call
14644 * {@link #setFixedWidth} if necessary.
14645 * @memberOf Roo.util.TextMetrics.Instance#
14646 * @param {String} text The text to measure
14647 * @return {Number} height The height in pixels
14649 getHeight : function(text){
14650 return this.getSize(text).height;
14654 instance.bind(bindTo);
14659 // backwards compat
14660 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14662 * Ext JS Library 1.1.1
14663 * Copyright(c) 2006-2007, Ext JS, LLC.
14665 * Originally Released Under LGPL - original licence link has changed is not relivant.
14668 * <script type="text/javascript">
14672 * @class Roo.state.Provider
14673 * Abstract base class for state provider implementations. This class provides methods
14674 * for encoding and decoding <b>typed</b> variables including dates and defines the
14675 * Provider interface.
14677 Roo.state.Provider = function(){
14679 * @event statechange
14680 * Fires when a state change occurs.
14681 * @param {Provider} this This state provider
14682 * @param {String} key The state key which was changed
14683 * @param {String} value The encoded value for the state
14686 "statechange": true
14689 Roo.state.Provider.superclass.constructor.call(this);
14691 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14693 * Returns the current value for a key
14694 * @param {String} name The key name
14695 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14696 * @return {Mixed} The state data
14698 get : function(name, defaultValue){
14699 return typeof this.state[name] == "undefined" ?
14700 defaultValue : this.state[name];
14704 * Clears a value from the state
14705 * @param {String} name The key name
14707 clear : function(name){
14708 delete this.state[name];
14709 this.fireEvent("statechange", this, name, null);
14713 * Sets the value for a key
14714 * @param {String} name The key name
14715 * @param {Mixed} value The value to set
14717 set : function(name, value){
14718 this.state[name] = value;
14719 this.fireEvent("statechange", this, name, value);
14723 * Decodes a string previously encoded with {@link #encodeValue}.
14724 * @param {String} value The value to decode
14725 * @return {Mixed} The decoded value
14727 decodeValue : function(cookie){
14728 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14729 var matches = re.exec(unescape(cookie));
14730 if(!matches || !matches[1]) return; // non state cookie
14731 var type = matches[1];
14732 var v = matches[2];
14735 return parseFloat(v);
14737 return new Date(Date.parse(v));
14742 var values = v.split("^");
14743 for(var i = 0, len = values.length; i < len; i++){
14744 all.push(this.decodeValue(values[i]));
14749 var values = v.split("^");
14750 for(var i = 0, len = values.length; i < len; i++){
14751 var kv = values[i].split("=");
14752 all[kv[0]] = this.decodeValue(kv[1]);
14761 * Encodes a value including type information. Decode with {@link #decodeValue}.
14762 * @param {Mixed} value The value to encode
14763 * @return {String} The encoded value
14765 encodeValue : function(v){
14767 if(typeof v == "number"){
14769 }else if(typeof v == "boolean"){
14770 enc = "b:" + (v ? "1" : "0");
14771 }else if(v instanceof Date){
14772 enc = "d:" + v.toGMTString();
14773 }else if(v instanceof Array){
14775 for(var i = 0, len = v.length; i < len; i++){
14776 flat += this.encodeValue(v[i]);
14777 if(i != len-1) flat += "^";
14780 }else if(typeof v == "object"){
14783 if(typeof v[key] != "function"){
14784 flat += key + "=" + this.encodeValue(v[key]) + "^";
14787 enc = "o:" + flat.substring(0, flat.length-1);
14791 return escape(enc);
14797 * Ext JS Library 1.1.1
14798 * Copyright(c) 2006-2007, Ext JS, LLC.
14800 * Originally Released Under LGPL - original licence link has changed is not relivant.
14803 * <script type="text/javascript">
14806 * @class Roo.state.Manager
14807 * This is the global state manager. By default all components that are "state aware" check this class
14808 * for state information if you don't pass them a custom state provider. In order for this class
14809 * to be useful, it must be initialized with a provider when your application initializes.
14811 // in your initialization function
14813 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14815 // supposed you have a {@link Roo.BorderLayout}
14816 var layout = new Roo.BorderLayout(...);
14817 layout.restoreState();
14818 // or a {Roo.BasicDialog}
14819 var dialog = new Roo.BasicDialog(...);
14820 dialog.restoreState();
14824 Roo.state.Manager = function(){
14825 var provider = new Roo.state.Provider();
14829 * Configures the default state provider for your application
14830 * @param {Provider} stateProvider The state provider to set
14832 setProvider : function(stateProvider){
14833 provider = stateProvider;
14837 * Returns the current value for a key
14838 * @param {String} name The key name
14839 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14840 * @return {Mixed} The state data
14842 get : function(key, defaultValue){
14843 return provider.get(key, defaultValue);
14847 * Sets the value for a key
14848 * @param {String} name The key name
14849 * @param {Mixed} value The state data
14851 set : function(key, value){
14852 provider.set(key, value);
14856 * Clears a value from the state
14857 * @param {String} name The key name
14859 clear : function(key){
14860 provider.clear(key);
14864 * Gets the currently configured state provider
14865 * @return {Provider} The state provider
14867 getProvider : function(){
14874 * Ext JS Library 1.1.1
14875 * Copyright(c) 2006-2007, Ext JS, LLC.
14877 * Originally Released Under LGPL - original licence link has changed is not relivant.
14880 * <script type="text/javascript">
14883 * @class Roo.state.CookieProvider
14884 * @extends Roo.state.Provider
14885 * The default Provider implementation which saves state via cookies.
14888 var cp = new Roo.state.CookieProvider({
14890 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14891 domain: "roojs.com"
14893 Roo.state.Manager.setProvider(cp);
14895 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14896 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14897 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14898 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14899 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14900 * domain the page is running on including the 'www' like 'www.roojs.com')
14901 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14903 * Create a new CookieProvider
14904 * @param {Object} config The configuration object
14906 Roo.state.CookieProvider = function(config){
14907 Roo.state.CookieProvider.superclass.constructor.call(this);
14909 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14910 this.domain = null;
14911 this.secure = false;
14912 Roo.apply(this, config);
14913 this.state = this.readCookies();
14916 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14918 set : function(name, value){
14919 if(typeof value == "undefined" || value === null){
14923 this.setCookie(name, value);
14924 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14928 clear : function(name){
14929 this.clearCookie(name);
14930 Roo.state.CookieProvider.superclass.clear.call(this, name);
14934 readCookies : function(){
14936 var c = document.cookie + ";";
14937 var re = /\s?(.*?)=(.*?);/g;
14939 while((matches = re.exec(c)) != null){
14940 var name = matches[1];
14941 var value = matches[2];
14942 if(name && name.substring(0,3) == "ys-"){
14943 cookies[name.substr(3)] = this.decodeValue(value);
14950 setCookie : function(name, value){
14951 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14952 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14953 ((this.path == null) ? "" : ("; path=" + this.path)) +
14954 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14955 ((this.secure == true) ? "; secure" : "");
14959 clearCookie : function(name){
14960 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14961 ((this.path == null) ? "" : ("; path=" + this.path)) +
14962 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14963 ((this.secure == true) ? "; secure" : "");
14967 * Ext JS Library 1.1.1
14968 * Copyright(c) 2006-2007, Ext JS, LLC.
14970 * Originally Released Under LGPL - original licence link has changed is not relivant.
14973 * <script type="text/javascript">
14978 * @class Roo.ComponentMgr
14979 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
14982 Roo.ComponentMgr = function(){
14983 var all = new Roo.util.MixedCollection();
14987 * Registers a component.
14988 * @param {Roo.Component} c The component
14990 register : function(c){
14995 * Unregisters a component.
14996 * @param {Roo.Component} c The component
14998 unregister : function(c){
15003 * Returns a component by id
15004 * @param {String} id The component id
15006 get : function(id){
15007 return all.get(id);
15011 * Registers a function that will be called when a specified component is added to ComponentMgr
15012 * @param {String} id The component id
15013 * @param {Funtction} fn The callback function
15014 * @param {Object} scope The scope of the callback
15016 onAvailable : function(id, fn, scope){
15017 all.on("add", function(index, o){
15019 fn.call(scope || o, o);
15020 all.un("add", fn, scope);
15027 * Ext JS Library 1.1.1
15028 * Copyright(c) 2006-2007, Ext JS, LLC.
15030 * Originally Released Under LGPL - original licence link has changed is not relivant.
15033 * <script type="text/javascript">
15037 * @class Roo.Component
15038 * @extends Roo.util.Observable
15039 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15040 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15041 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15042 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15043 * All visual components (widgets) that require rendering into a layout should subclass Component.
15045 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15046 * 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
15047 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15049 Roo.Component = function(config){
15050 config = config || {};
15051 if(config.tagName || config.dom || typeof config == "string"){ // element object
15052 config = {el: config, id: config.id || config};
15054 this.initialConfig = config;
15056 Roo.apply(this, config);
15060 * Fires after the component is disabled.
15061 * @param {Roo.Component} this
15066 * Fires after the component is enabled.
15067 * @param {Roo.Component} this
15071 * @event beforeshow
15072 * Fires before the component is shown. Return false to stop the show.
15073 * @param {Roo.Component} this
15078 * Fires after the component is shown.
15079 * @param {Roo.Component} this
15083 * @event beforehide
15084 * Fires before the component is hidden. Return false to stop the hide.
15085 * @param {Roo.Component} this
15090 * Fires after the component is hidden.
15091 * @param {Roo.Component} this
15095 * @event beforerender
15096 * Fires before the component is rendered. Return false to stop the render.
15097 * @param {Roo.Component} this
15099 beforerender : true,
15102 * Fires after the component is rendered.
15103 * @param {Roo.Component} this
15107 * @event beforedestroy
15108 * Fires before the component is destroyed. Return false to stop the destroy.
15109 * @param {Roo.Component} this
15111 beforedestroy : true,
15114 * Fires after the component is destroyed.
15115 * @param {Roo.Component} this
15120 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
15122 Roo.ComponentMgr.register(this);
15123 Roo.Component.superclass.constructor.call(this);
15124 this.initComponent();
15125 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15126 this.render(this.renderTo);
15127 delete this.renderTo;
15132 Roo.Component.AUTO_ID = 1000;
15134 Roo.extend(Roo.Component, Roo.util.Observable, {
15136 * @scope Roo.Component.prototype
15138 * true if this component is hidden. Read-only.
15143 * true if this component is disabled. Read-only.
15148 * true if this component has been rendered. Read-only.
15152 /** @cfg {String} disableClass
15153 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15155 disabledClass : "x-item-disabled",
15156 /** @cfg {Boolean} allowDomMove
15157 * Whether the component can move the Dom node when rendering (defaults to true).
15159 allowDomMove : true,
15160 /** @cfg {String} hideMode
15161 * How this component should hidden. Supported values are
15162 * "visibility" (css visibility), "offsets" (negative offset position) and
15163 * "display" (css display) - defaults to "display".
15165 hideMode: 'display',
15168 ctype : "Roo.Component",
15171 * @cfg {String} actionMode
15172 * which property holds the element that used for hide() / show() / disable() / enable()
15178 getActionEl : function(){
15179 return this[this.actionMode];
15182 initComponent : Roo.emptyFn,
15184 * If this is a lazy rendering component, render it to its container element.
15185 * @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.
15187 render : function(container, position){
15188 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15189 if(!container && this.el){
15190 this.el = Roo.get(this.el);
15191 container = this.el.dom.parentNode;
15192 this.allowDomMove = false;
15194 this.container = Roo.get(container);
15195 this.rendered = true;
15196 if(position !== undefined){
15197 if(typeof position == 'number'){
15198 position = this.container.dom.childNodes[position];
15200 position = Roo.getDom(position);
15203 this.onRender(this.container, position || null);
15205 this.el.addClass(this.cls);
15209 this.el.applyStyles(this.style);
15212 this.fireEvent("render", this);
15213 this.afterRender(this.container);
15225 // default function is not really useful
15226 onRender : function(ct, position){
15228 this.el = Roo.get(this.el);
15229 if(this.allowDomMove !== false){
15230 ct.dom.insertBefore(this.el.dom, position);
15236 getAutoCreate : function(){
15237 var cfg = typeof this.autoCreate == "object" ?
15238 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15239 if(this.id && !cfg.id){
15246 afterRender : Roo.emptyFn,
15249 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15250 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15252 destroy : function(){
15253 if(this.fireEvent("beforedestroy", this) !== false){
15254 this.purgeListeners();
15255 this.beforeDestroy();
15257 this.el.removeAllListeners();
15259 if(this.actionMode == "container"){
15260 this.container.remove();
15264 Roo.ComponentMgr.unregister(this);
15265 this.fireEvent("destroy", this);
15270 beforeDestroy : function(){
15275 onDestroy : function(){
15280 * Returns the underlying {@link Roo.Element}.
15281 * @return {Roo.Element} The element
15283 getEl : function(){
15288 * Returns the id of this component.
15291 getId : function(){
15296 * Try to focus this component.
15297 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15298 * @return {Roo.Component} this
15300 focus : function(selectText){
15303 if(selectText === true){
15304 this.el.dom.select();
15319 * Disable this component.
15320 * @return {Roo.Component} this
15322 disable : function(){
15326 this.disabled = true;
15327 this.fireEvent("disable", this);
15332 onDisable : function(){
15333 this.getActionEl().addClass(this.disabledClass);
15334 this.el.dom.disabled = true;
15338 * Enable this component.
15339 * @return {Roo.Component} this
15341 enable : function(){
15345 this.disabled = false;
15346 this.fireEvent("enable", this);
15351 onEnable : function(){
15352 this.getActionEl().removeClass(this.disabledClass);
15353 this.el.dom.disabled = false;
15357 * Convenience function for setting disabled/enabled by boolean.
15358 * @param {Boolean} disabled
15360 setDisabled : function(disabled){
15361 this[disabled ? "disable" : "enable"]();
15365 * Show this component.
15366 * @return {Roo.Component} this
15369 if(this.fireEvent("beforeshow", this) !== false){
15370 this.hidden = false;
15374 this.fireEvent("show", this);
15380 onShow : function(){
15381 var ae = this.getActionEl();
15382 if(this.hideMode == 'visibility'){
15383 ae.dom.style.visibility = "visible";
15384 }else if(this.hideMode == 'offsets'){
15385 ae.removeClass('x-hidden');
15387 ae.dom.style.display = "";
15392 * Hide this component.
15393 * @return {Roo.Component} this
15396 if(this.fireEvent("beforehide", this) !== false){
15397 this.hidden = true;
15401 this.fireEvent("hide", this);
15407 onHide : function(){
15408 var ae = this.getActionEl();
15409 if(this.hideMode == 'visibility'){
15410 ae.dom.style.visibility = "hidden";
15411 }else if(this.hideMode == 'offsets'){
15412 ae.addClass('x-hidden');
15414 ae.dom.style.display = "none";
15419 * Convenience function to hide or show this component by boolean.
15420 * @param {Boolean} visible True to show, false to hide
15421 * @return {Roo.Component} this
15423 setVisible: function(visible){
15433 * Returns true if this component is visible.
15435 isVisible : function(){
15436 return this.getActionEl().isVisible();
15439 cloneConfig : function(overrides){
15440 overrides = overrides || {};
15441 var id = overrides.id || Roo.id();
15442 var cfg = Roo.applyIf(overrides, this.initialConfig);
15443 cfg.id = id; // prevent dup id
15444 return new this.constructor(cfg);
15448 * Ext JS Library 1.1.1
15449 * Copyright(c) 2006-2007, Ext JS, LLC.
15451 * Originally Released Under LGPL - original licence link has changed is not relivant.
15454 * <script type="text/javascript">
15458 * @class Roo.BoxComponent
15459 * @extends Roo.Component
15460 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15461 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15462 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15463 * layout containers.
15465 * @param {Roo.Element/String/Object} config The configuration options.
15467 Roo.BoxComponent = function(config){
15468 Roo.Component.call(this, config);
15472 * Fires after the component is resized.
15473 * @param {Roo.Component} this
15474 * @param {Number} adjWidth The box-adjusted width that was set
15475 * @param {Number} adjHeight The box-adjusted height that was set
15476 * @param {Number} rawWidth The width that was originally specified
15477 * @param {Number} rawHeight The height that was originally specified
15482 * Fires after the component is moved.
15483 * @param {Roo.Component} this
15484 * @param {Number} x The new x position
15485 * @param {Number} y The new y position
15491 Roo.extend(Roo.BoxComponent, Roo.Component, {
15492 // private, set in afterRender to signify that the component has been rendered
15494 // private, used to defer height settings to subclasses
15495 deferHeight: false,
15496 /** @cfg {Number} width
15497 * width (optional) size of component
15499 /** @cfg {Number} height
15500 * height (optional) size of component
15504 * Sets the width and height of the component. This method fires the resize event. This method can accept
15505 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15506 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15507 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15508 * @return {Roo.BoxComponent} this
15510 setSize : function(w, h){
15511 // support for standard size objects
15512 if(typeof w == 'object'){
15517 if(!this.boxReady){
15523 // prevent recalcs when not needed
15524 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15527 this.lastSize = {width: w, height: h};
15529 var adj = this.adjustSize(w, h);
15530 var aw = adj.width, ah = adj.height;
15531 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15532 var rz = this.getResizeEl();
15533 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15534 rz.setSize(aw, ah);
15535 }else if(!this.deferHeight && ah !== undefined){
15537 }else if(aw !== undefined){
15540 this.onResize(aw, ah, w, h);
15541 this.fireEvent('resize', this, aw, ah, w, h);
15547 * Gets the current size of the component's underlying element.
15548 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15550 getSize : function(){
15551 return this.el.getSize();
15555 * Gets the current XY position of the component's underlying element.
15556 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15557 * @return {Array} The XY position of the element (e.g., [100, 200])
15559 getPosition : function(local){
15560 if(local === true){
15561 return [this.el.getLeft(true), this.el.getTop(true)];
15563 return this.xy || this.el.getXY();
15567 * Gets the current box measurements of the component's underlying element.
15568 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15569 * @returns {Object} box An object in the format {x, y, width, height}
15571 getBox : function(local){
15572 var s = this.el.getSize();
15574 s.x = this.el.getLeft(true);
15575 s.y = this.el.getTop(true);
15577 var xy = this.xy || this.el.getXY();
15585 * Sets the current box measurements of the component's underlying element.
15586 * @param {Object} box An object in the format {x, y, width, height}
15587 * @returns {Roo.BoxComponent} this
15589 updateBox : function(box){
15590 this.setSize(box.width, box.height);
15591 this.setPagePosition(box.x, box.y);
15596 getResizeEl : function(){
15597 return this.resizeEl || this.el;
15601 getPositionEl : function(){
15602 return this.positionEl || this.el;
15606 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15607 * This method fires the move event.
15608 * @param {Number} left The new left
15609 * @param {Number} top The new top
15610 * @returns {Roo.BoxComponent} this
15612 setPosition : function(x, y){
15615 if(!this.boxReady){
15618 var adj = this.adjustPosition(x, y);
15619 var ax = adj.x, ay = adj.y;
15621 var el = this.getPositionEl();
15622 if(ax !== undefined || ay !== undefined){
15623 if(ax !== undefined && ay !== undefined){
15624 el.setLeftTop(ax, ay);
15625 }else if(ax !== undefined){
15627 }else if(ay !== undefined){
15630 this.onPosition(ax, ay);
15631 this.fireEvent('move', this, ax, ay);
15637 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15638 * This method fires the move event.
15639 * @param {Number} x The new x position
15640 * @param {Number} y The new y position
15641 * @returns {Roo.BoxComponent} this
15643 setPagePosition : function(x, y){
15646 if(!this.boxReady){
15649 if(x === undefined || y === undefined){ // cannot translate undefined points
15652 var p = this.el.translatePoints(x, y);
15653 this.setPosition(p.left, p.top);
15658 onRender : function(ct, position){
15659 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15661 this.resizeEl = Roo.get(this.resizeEl);
15663 if(this.positionEl){
15664 this.positionEl = Roo.get(this.positionEl);
15669 afterRender : function(){
15670 Roo.BoxComponent.superclass.afterRender.call(this);
15671 this.boxReady = true;
15672 this.setSize(this.width, this.height);
15673 if(this.x || this.y){
15674 this.setPosition(this.x, this.y);
15676 if(this.pageX || this.pageY){
15677 this.setPagePosition(this.pageX, this.pageY);
15682 * Force the component's size to recalculate based on the underlying element's current height and width.
15683 * @returns {Roo.BoxComponent} this
15685 syncSize : function(){
15686 delete this.lastSize;
15687 this.setSize(this.el.getWidth(), this.el.getHeight());
15692 * Called after the component is resized, this method is empty by default but can be implemented by any
15693 * subclass that needs to perform custom logic after a resize occurs.
15694 * @param {Number} adjWidth The box-adjusted width that was set
15695 * @param {Number} adjHeight The box-adjusted height that was set
15696 * @param {Number} rawWidth The width that was originally specified
15697 * @param {Number} rawHeight The height that was originally specified
15699 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15704 * Called after the component is moved, this method is empty by default but can be implemented by any
15705 * subclass that needs to perform custom logic after a move occurs.
15706 * @param {Number} x The new x position
15707 * @param {Number} y The new y position
15709 onPosition : function(x, y){
15714 adjustSize : function(w, h){
15715 if(this.autoWidth){
15718 if(this.autoHeight){
15721 return {width : w, height: h};
15725 adjustPosition : function(x, y){
15726 return {x : x, y: y};
15729 * Original code for Roojs - LGPL
15730 * <script type="text/javascript">
15734 * @class Roo.XComponent
15735 * A delayed Element creator...
15736 * Or a way to group chunks of interface together.
15738 * Mypart.xyx = new Roo.XComponent({
15740 parent : 'Mypart.xyz', // empty == document.element.!!
15744 disabled : function() {}
15746 tree : function() { // return an tree of xtype declared components
15750 xtype : 'NestedLayoutPanel',
15757 * It can be used to build a big heiracy, with parent etc.
15758 * or you can just use this to render a single compoent to a dom element
15759 * MYPART.render(Roo.Element | String(id) | dom_element )
15761 * @extends Roo.util.Observable
15763 * @param cfg {Object} configuration of component
15766 Roo.XComponent = function(cfg) {
15767 Roo.apply(this, cfg);
15771 * Fires when this the componnt is built
15772 * @param {Roo.XComponent} c the component
15777 this.region = this.region || 'center'; // default..
15778 Roo.XComponent.register(this);
15779 this.modules = false;
15780 this.el = false; // where the layout goes..
15784 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15787 * The created element (with Roo.factory())
15788 * @type {Roo.Layout}
15794 * for BC - use el in new code
15795 * @type {Roo.Layout}
15801 * for BC - use el in new code
15802 * @type {Roo.Layout}
15807 * @cfg {Function|boolean} disabled
15808 * If this module is disabled by some rule, return true from the funtion
15813 * @cfg {String} parent
15814 * Name of parent element which it get xtype added to..
15819 * @cfg {String} order
15820 * Used to set the order in which elements are created (usefull for multiple tabs)
15825 * @cfg {String} name
15826 * String to display while loading.
15830 * @cfg {String} region
15831 * Region to render component to (defaults to center)
15836 * @cfg {Array} items
15837 * A single item array - the first element is the root of the tree..
15838 * It's done this way to stay compatible with the Xtype system...
15844 * The method that retuns the tree of parts that make up this compoennt
15851 * render element to dom or tree
15852 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
15855 render : function(el)
15859 var hp = this.parent ? 1 : 0;
15861 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
15862 // if parent is a '#.....' string, then let's use that..
15863 var ename = this.parent.substr(1)
15864 this.parent = (this.parent == '#bootstrap') ? { el : true} : false; // flags it as a top module...
15865 el = Roo.get(ename);
15866 if (!el && !this.parent) {
15867 Roo.log("Warning - element can not be found :#" + ename );
15871 var tree = this._tree ? this._tree() : this.tree();
15874 if (!this.parent && typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) {
15875 //el = Roo.get(document.body);
15876 this.parent = { el : true };
15881 if (!this.parent) {
15883 Roo.log("no parent - creating one");
15885 el = el ? Roo.get(el) : false;
15887 // it's a top level one..
15889 el : new Roo.BorderLayout(el || document.body, {
15895 tabPosition: 'top',
15896 //resizeTabs: true,
15897 alwaysShowTabs: el && hp? false : true,
15898 hideTabs: el || !hp ? true : false,
15905 if (!this.parent.el) {
15906 // probably an old style ctor, which has been disabled.
15910 // The 'tree' method is '_tree now'
15912 tree.region = tree.region || this.region;
15914 if (this.parent.el === true) {
15915 // bootstrap... - body..
15916 this.parent.el = Roo.factory(tree);
15919 this.el = this.parent.el.addxtype(tree);
15920 this.fireEvent('built', this);
15922 this.panel = this.el;
15923 this.layout = this.panel.layout;
15924 this.parentLayout = this.parent.layout || false;
15930 Roo.apply(Roo.XComponent, {
15932 * @property hideProgress
15933 * true to disable the building progress bar.. usefull on single page renders.
15936 hideProgress : false,
15938 * @property buildCompleted
15939 * True when the builder has completed building the interface.
15942 buildCompleted : false,
15945 * @property topModule
15946 * the upper most module - uses document.element as it's constructor.
15953 * @property modules
15954 * array of modules to be created by registration system.
15955 * @type {Array} of Roo.XComponent
15960 * @property elmodules
15961 * array of modules to be created by which use #ID
15962 * @type {Array} of Roo.XComponent
15968 * @property build_from_html
15969 * Build elements from html - used by bootstrap HTML stuff
15970 * - this is cleared after build is completed
15971 * @type {boolean} true (default false)
15974 build_from_html : false,
15977 * Register components to be built later.
15979 * This solves the following issues
15980 * - Building is not done on page load, but after an authentication process has occured.
15981 * - Interface elements are registered on page load
15982 * - Parent Interface elements may not be loaded before child, so this handles that..
15989 module : 'Pman.Tab.projectMgr',
15991 parent : 'Pman.layout',
15992 disabled : false, // or use a function..
15995 * * @param {Object} details about module
15997 register : function(obj) {
15999 Roo.XComponent.event.fireEvent('register', obj);
16000 switch(typeof(obj.disabled) ) {
16006 if ( obj.disabled() ) {
16012 if (obj.disabled) {
16018 this.modules.push(obj);
16022 * convert a string to an object..
16023 * eg. 'AAA.BBB' -> finds AAA.BBB
16027 toObject : function(str)
16029 if (!str || typeof(str) == 'object') {
16032 if (str.substring(0,1) == '#') {
16036 var ar = str.split('.');
16041 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16043 throw "Module not found : " + str;
16047 throw "Module not found : " + str;
16049 Roo.each(ar, function(e) {
16050 if (typeof(o[e]) == 'undefined') {
16051 throw "Module not found : " + str;
16062 * move modules into their correct place in the tree..
16065 preBuild : function ()
16068 Roo.each(this.modules , function (obj)
16070 Roo.XComponent.event.fireEvent('beforebuild', obj);
16072 var opar = obj.parent;
16074 obj.parent = this.toObject(opar);
16076 Roo.log("parent:toObject failed: " + e.toString());
16081 Roo.debug && Roo.log("GOT top level module");
16082 Roo.debug && Roo.log(obj);
16083 obj.modules = new Roo.util.MixedCollection(false,
16084 function(o) { return o.order + '' }
16086 this.topModule = obj;
16089 // parent is a string (usually a dom element name..)
16090 if (typeof(obj.parent) == 'string') {
16091 this.elmodules.push(obj);
16094 if (obj.parent.constructor != Roo.XComponent) {
16095 Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16097 if (!obj.parent.modules) {
16098 obj.parent.modules = new Roo.util.MixedCollection(false,
16099 function(o) { return o.order + '' }
16102 if (obj.parent.disabled) {
16103 obj.disabled = true;
16105 obj.parent.modules.add(obj);
16110 * make a list of modules to build.
16111 * @return {Array} list of modules.
16114 buildOrder : function()
16117 var cmp = function(a,b) {
16118 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16120 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16121 throw "No top level modules to build";
16124 // make a flat list in order of modules to build.
16125 var mods = this.topModule ? [ this.topModule ] : [];
16128 // elmodules (is a list of DOM based modules )
16129 Roo.each(this.elmodules, function(e) {
16131 if (!this.topModule &&
16132 typeof(e.parent) == 'string' &&
16133 e.parent.substring(0,1) == '#' &&
16134 Roo.get(e.parent.substr(1))
16137 _this.topModule = e;
16143 // add modules to their parents..
16144 var addMod = function(m) {
16145 Roo.debug && Roo.log("build Order: add: " + m.name);
16148 if (m.modules && !m.disabled) {
16149 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16150 m.modules.keySort('ASC', cmp );
16151 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16153 m.modules.each(addMod);
16155 Roo.debug && Roo.log("build Order: no child modules");
16157 // not sure if this is used any more..
16159 m.finalize.name = m.name + " (clean up) ";
16160 mods.push(m.finalize);
16164 if (this.topModule && this.topModule.modules) {
16165 this.topModule.modules.keySort('ASC', cmp );
16166 this.topModule.modules.each(addMod);
16172 * Build the registered modules.
16173 * @param {Object} parent element.
16174 * @param {Function} optional method to call after module has been added.
16178 build : function(opts)
16181 if (typeof(opts) != 'undefined') {
16182 Roo.apply(this,opts);
16186 var mods = this.buildOrder();
16188 //this.allmods = mods;
16189 //Roo.debug && Roo.log(mods);
16191 if (!mods.length) { // should not happen
16192 throw "NO modules!!!";
16196 var msg = "Building Interface...";
16197 // flash it up as modal - so we store the mask!?
16198 if (!this.hideProgress && Roo.MessageBox) {
16199 Roo.MessageBox.show({ title: 'loading' });
16200 Roo.MessageBox.show({
16201 title: "Please wait...",
16210 var total = mods.length;
16213 var progressRun = function() {
16214 if (!mods.length) {
16215 Roo.debug && Roo.log('hide?');
16216 if (!this.hideProgress && Roo.MessageBox) {
16217 Roo.MessageBox.hide();
16219 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16221 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16227 var m = mods.shift();
16230 Roo.debug && Roo.log(m);
16231 // not sure if this is supported any more.. - modules that are are just function
16232 if (typeof(m) == 'function') {
16234 return progressRun.defer(10, _this);
16238 msg = "Building Interface " + (total - mods.length) +
16240 (m.name ? (' - ' + m.name) : '');
16241 Roo.debug && Roo.log(msg);
16242 if (!this.hideProgress && Roo.MessageBox) {
16243 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16247 // is the module disabled?
16248 var disabled = (typeof(m.disabled) == 'function') ?
16249 m.disabled.call(m.module.disabled) : m.disabled;
16253 return progressRun(); // we do not update the display!
16261 // it's 10 on top level, and 1 on others??? why...
16262 return progressRun.defer(10, _this);
16265 progressRun.defer(1, _this);
16279 * wrapper for event.on - aliased later..
16280 * Typically use to register a event handler for register:
16282 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16291 Roo.XComponent.event = new Roo.util.Observable({
16295 * Fires when an Component is registered,
16296 * set the disable property on the Component to stop registration.
16297 * @param {Roo.XComponent} c the component being registerd.
16302 * @event beforebuild
16303 * Fires before each Component is built
16304 * can be used to apply permissions.
16305 * @param {Roo.XComponent} c the component being registerd.
16308 'beforebuild' : true,
16310 * @event buildcomplete
16311 * Fires on the top level element when all elements have been built
16312 * @param {Roo.XComponent} the top level component.
16314 'buildcomplete' : true
16319 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);