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 isFirefox = ua.indexOf("firefox") > -1,
57 isIE = ua.indexOf("msie") > -1,
58 isIE7 = ua.indexOf("msie 7") > -1,
59 isIE11 = /trident.*rv\:11\./.test(ua),
60 isGecko = !isSafari && ua.indexOf("gecko") > -1,
61 isBorderBox = isIE && !isStrict,
62 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
63 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
64 isLinux = (ua.indexOf("linux") != -1),
65 isSecure = window.location.href.toLowerCase().indexOf("https") === 0,
66 isTouch = (function() {
68 document.createEvent("TouchEvent");
75 // remove css image flicker
78 document.execCommand("BackgroundImageCache", false, true);
84 * True if the browser is in strict mode
89 * True if the page is running over SSL
94 * True when the document is fully initialized and ready for action
99 * Turn on debugging output (currently only the factory uses this)
106 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
109 enableGarbageCollector : true,
112 * True to automatically purge event listeners after uncaching an element (defaults to false).
113 * Note: this only happens if enableGarbageCollector is true.
116 enableListenerCollection:false,
119 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
120 * the IE insecure content warning (defaults to javascript:false).
123 SSL_SECURE_URL : "javascript:false",
126 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
127 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
130 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
132 emptyFn : function(){},
135 * Copies all the properties of config to obj if they don't already exist.
136 * @param {Object} obj The receiver of the properties
137 * @param {Object} config The source of the properties
138 * @return {Object} returns obj
140 applyIf : function(o, c){
143 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
150 * Applies event listeners to elements by selectors when the document is ready.
151 * The event name is specified with an @ suffix.
154 // add a listener for click on all anchors in element with id foo
155 '#foo a@click' : function(e, t){
159 // add the same listener to multiple selectors (separated by comma BEFORE the @)
160 '#foo a, #bar span.some-class@mouseover' : function(){
165 * @param {Object} obj The list of behaviors to apply
167 addBehaviors : function(o){
169 Roo.onReady(function(){
174 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
176 var parts = b.split('@');
177 if(parts[1]){ // for Object prototype breakers
180 cache[s] = Roo.select(s);
182 cache[s].on(parts[1], o[b]);
189 * Generates unique ids. If the element already has an id, it is unchanged
190 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
191 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
192 * @return {String} The generated Id.
194 id : function(el, prefix){
195 prefix = prefix || "roo-gen";
197 var id = prefix + (++idSeed);
198 return el ? (el.id ? el.id : (el.id = id)) : id;
203 * Extends one class with another class and optionally overrides members with the passed literal. This class
204 * also adds the function "override()" to the class that can be used to override
205 * members on an instance.
206 * @param {Object} subclass The class inheriting the functionality
207 * @param {Object} superclass The class being extended
208 * @param {Object} overrides (optional) A literal with members
213 var io = function(o){
218 return function(sb, sp, overrides){
219 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
222 sb = function(){sp.apply(this, arguments);};
224 var F = function(){}, sbp, spp = sp.prototype;
226 sbp = sb.prototype = new F();
230 if(spp.constructor == Object.prototype.constructor){
235 sb.override = function(o){
239 Roo.override(sb, overrides);
245 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
247 Roo.override(MyClass, {
248 newMethod1: function(){
251 newMethod2: function(foo){
256 * @param {Object} origclass The class to override
257 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
258 * containing one or more methods.
261 override : function(origclass, overrides){
263 var p = origclass.prototype;
264 for(var method in overrides){
265 p[method] = overrides[method];
270 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
272 Roo.namespace('Company', 'Company.data');
273 Company.Widget = function() { ... }
274 Company.data.CustomStore = function(config) { ... }
276 * @param {String} namespace1
277 * @param {String} namespace2
278 * @param {String} etc
281 namespace : function(){
282 var a=arguments, o=null, i, j, d, rt;
283 for (i=0; i<a.length; ++i) {
287 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
288 for (j=1; j<d.length; ++j) {
289 o[d[j]]=o[d[j]] || {};
295 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
297 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
298 Roo.factory(conf, Roo.data);
300 * @param {String} classname
301 * @param {String} namespace (optional)
305 factory : function(c, ns)
307 // no xtype, no ns or c.xns - or forced off by c.xns
308 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
311 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
312 if (c.constructor == ns[c.xtype]) {// already created...
316 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
317 var ret = new ns[c.xtype](c);
321 c.xns = false; // prevent recursion..
325 * Logs to console if it can.
327 * @param {String|Object} string
332 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
339 * 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.
343 urlEncode : function(o){
349 var ov = o[key], k = Roo.encodeURIComponent(key);
350 var type = typeof ov;
351 if(type == 'undefined'){
353 }else if(type != "function" && type != "object"){
354 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
355 }else if(ov instanceof Array){
357 for(var i = 0, len = ov.length; i < len; i++) {
358 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
369 * Safe version of encodeURIComponent
370 * @param {String} data
374 encodeURIComponent : function (data)
377 return encodeURIComponent(data);
378 } catch(e) {} // should be an uri encode error.
380 if (data == '' || data == null){
383 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
384 function nibble_to_hex(nibble){
385 var chars = '0123456789ABCDEF';
386 return chars.charAt(nibble);
388 data = data.toString();
390 for(var i=0; i<data.length; i++){
391 var c = data.charCodeAt(i);
392 var bs = new Array();
395 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
396 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
397 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
398 bs[3] = 0x80 | (c & 0x3F);
399 }else if (c > 0x800){
401 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
402 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
403 bs[2] = 0x80 | (c & 0x3F);
406 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
407 bs[1] = 0x80 | (c & 0x3F);
412 for(var j=0; j<bs.length; j++){
414 var hex = nibble_to_hex((b & 0xF0) >>> 4)
415 + nibble_to_hex(b &0x0F);
424 * 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]}.
425 * @param {String} string
426 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
427 * @return {Object} A literal with members
429 urlDecode : function(string, overwrite){
430 if(!string || !string.length){
434 var pairs = string.split('&');
435 var pair, name, value;
436 for(var i = 0, len = pairs.length; i < len; i++){
437 pair = pairs[i].split('=');
438 name = decodeURIComponent(pair[0]);
439 value = decodeURIComponent(pair[1]);
440 if(overwrite !== true){
441 if(typeof obj[name] == "undefined"){
443 }else if(typeof obj[name] == "string"){
444 obj[name] = [obj[name]];
445 obj[name].push(value);
447 obj[name].push(value);
457 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
458 * passed array is not really an array, your function is called once with it.
459 * The supplied function is called with (Object item, Number index, Array allItems).
460 * @param {Array/NodeList/Mixed} array
461 * @param {Function} fn
462 * @param {Object} scope
464 each : function(array, fn, scope){
465 if(typeof array.length == "undefined" || typeof array == "string"){
468 for(var i = 0, len = array.length; i < len; i++){
469 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
474 combine : function(){
475 var as = arguments, l = as.length, r = [];
476 for(var i = 0; i < l; i++){
478 if(a instanceof Array){
480 }else if(a.length !== undefined && !a.substr){
481 r = r.concat(Array.prototype.slice.call(a, 0));
490 * Escapes the passed string for use in a regular expression
491 * @param {String} str
494 escapeRe : function(s) {
495 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
499 callback : function(cb, scope, args, delay){
500 if(typeof cb == "function"){
502 cb.defer(delay, scope, args || []);
504 cb.apply(scope, args || []);
510 * Return the dom node for the passed string (id), dom node, or Roo.Element
511 * @param {String/HTMLElement/Roo.Element} el
512 * @return HTMLElement
514 getDom : function(el){
518 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
522 * Shorthand for {@link Roo.ComponentMgr#get}
524 * @return Roo.Component
526 getCmp : function(id){
527 return Roo.ComponentMgr.get(id);
530 num : function(v, defaultValue){
531 if(typeof v != 'number'){
537 destroy : function(){
538 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
542 as.removeAllListeners();
546 if(typeof as.purgeListeners == 'function'){
549 if(typeof as.destroy == 'function'){
556 // inpired by a similar function in mootools library
558 * Returns the type of object that is passed in. If the object passed in is null or undefined it
559 * return false otherwise it returns one of the following values:<ul>
560 * <li><b>string</b>: If the object passed is a string</li>
561 * <li><b>number</b>: If the object passed is a number</li>
562 * <li><b>boolean</b>: If the object passed is a boolean value</li>
563 * <li><b>function</b>: If the object passed is a function reference</li>
564 * <li><b>object</b>: If the object passed is an object</li>
565 * <li><b>array</b>: If the object passed is an array</li>
566 * <li><b>regexp</b>: If the object passed is a regular expression</li>
567 * <li><b>element</b>: If the object passed is a DOM Element</li>
568 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
569 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
570 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
571 * @param {Mixed} object
575 if(o === undefined || o === null){
582 if(t == 'object' && o.nodeName) {
584 case 1: return 'element';
585 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
588 if(t == 'object' || t == 'function') {
589 switch(o.constructor) {
590 case Array: return 'array';
591 case RegExp: return 'regexp';
593 if(typeof o.length == 'number' && typeof o.item == 'function') {
601 * Returns true if the passed value is null, undefined or an empty string (optional).
602 * @param {Mixed} value The value to test
603 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
606 isEmpty : function(v, allowBlank){
607 return v === null || v === undefined || (!allowBlank ? v === '' : false);
615 isFirefox : isFirefox,
625 isBorderBox : isBorderBox,
627 isWindows : isWindows,
636 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
637 * you may want to set this to true.
640 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
645 * Selects a single element as a Roo Element
646 * This is about as close as you can get to jQuery's $('do crazy stuff')
647 * @param {String} selector The selector/xpath query
648 * @param {Node} root (optional) The start of the query (defaults to document).
649 * @return {Roo.Element}
651 selectNode : function(selector, root)
653 var node = Roo.DomQuery.selectNode(selector,root);
654 return node ? Roo.get(node) : new Roo.Element(false);
662 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
663 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout",
666 "Roo.bootstrap.dash");
669 * Ext JS Library 1.1.1
670 * Copyright(c) 2006-2007, Ext JS, LLC.
672 * Originally Released Under LGPL - original licence link has changed is not relivant.
675 * <script type="text/javascript">
679 // wrappedn so fnCleanup is not in global scope...
681 function fnCleanUp() {
682 var p = Function.prototype;
683 delete p.createSequence;
685 delete p.createDelegate;
686 delete p.createCallback;
687 delete p.createInterceptor;
689 window.detachEvent("onunload", fnCleanUp);
691 window.attachEvent("onunload", fnCleanUp);
698 * These functions are available on every Function object (any JavaScript function).
700 Roo.apply(Function.prototype, {
702 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
703 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
704 * Will create a function that is bound to those 2 args.
705 * @return {Function} The new function
707 createCallback : function(/*args...*/){
708 // make args available, in function below
709 var args = arguments;
712 return method.apply(window, args);
717 * Creates a delegate (callback) that sets the scope to obj.
718 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
719 * Will create a function that is automatically scoped to this.
720 * @param {Object} obj (optional) The object for which the scope is set
721 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
722 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
723 * if a number the args are inserted at the specified position
724 * @return {Function} The new function
726 createDelegate : function(obj, args, appendArgs){
729 var callArgs = args || arguments;
730 if(appendArgs === true){
731 callArgs = Array.prototype.slice.call(arguments, 0);
732 callArgs = callArgs.concat(args);
733 }else if(typeof appendArgs == "number"){
734 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
735 var applyArgs = [appendArgs, 0].concat(args); // create method call params
736 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
738 return method.apply(obj || window, callArgs);
743 * Calls this function after the number of millseconds specified.
744 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
745 * @param {Object} obj (optional) The object for which the scope is set
746 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
747 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
748 * if a number the args are inserted at the specified position
749 * @return {Number} The timeout id that can be used with clearTimeout
751 defer : function(millis, obj, args, appendArgs){
752 var fn = this.createDelegate(obj, args, appendArgs);
754 return setTimeout(fn, millis);
760 * Create a combined function call sequence of the original function + the passed function.
761 * The resulting function returns the results of the original function.
762 * The passed fcn is called with the parameters of the original function
763 * @param {Function} fcn The function to sequence
764 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
765 * @return {Function} The new function
767 createSequence : function(fcn, scope){
768 if(typeof fcn != "function"){
773 var retval = method.apply(this || window, arguments);
774 fcn.apply(scope || this || window, arguments);
780 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
781 * The resulting function returns the results of the original function.
782 * The passed fcn is called with the parameters of the original function.
784 * @param {Function} fcn The function to call before the original
785 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
786 * @return {Function} The new function
788 createInterceptor : function(fcn, scope){
789 if(typeof fcn != "function"){
796 if(fcn.apply(scope || this || window, arguments) === false){
799 return method.apply(this || window, arguments);
805 * Ext JS Library 1.1.1
806 * Copyright(c) 2006-2007, Ext JS, LLC.
808 * Originally Released Under LGPL - original licence link has changed is not relivant.
811 * <script type="text/javascript">
814 Roo.applyIf(String, {
819 * Escapes the passed string for ' and \
820 * @param {String} string The string to escape
821 * @return {String} The escaped string
824 escape : function(string) {
825 return string.replace(/('|\\)/g, "\\$1");
829 * Pads the left side of a string with a specified character. This is especially useful
830 * for normalizing number and date strings. Example usage:
832 var s = String.leftPad('123', 5, '0');
833 // s now contains the string: '00123'
835 * @param {String} string The original string
836 * @param {Number} size The total length of the output string
837 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
838 * @return {String} The padded string
841 leftPad : function (val, size, ch) {
842 var result = new String(val);
843 if(ch === null || ch === undefined || ch === '') {
846 while (result.length < size) {
847 result = ch + result;
853 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
854 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
856 var cls = 'my-class', text = 'Some text';
857 var s = String.format('<div class="{0}">{1}</div>', cls, text);
858 // s now contains the string: '<div class="my-class">Some text</div>'
860 * @param {String} string The tokenized string to be formatted
861 * @param {String} value1 The value to replace token {0}
862 * @param {String} value2 Etc...
863 * @return {String} The formatted string
866 format : function(format){
867 var args = Array.prototype.slice.call(arguments, 1);
868 return format.replace(/\{(\d+)\}/g, function(m, i){
869 return Roo.util.Format.htmlEncode(args[i]);
875 * Utility function that allows you to easily switch a string between two alternating values. The passed value
876 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
877 * they are already different, the first value passed in is returned. Note that this method returns the new value
878 * but does not change the current string.
880 // alternate sort directions
881 sort = sort.toggle('ASC', 'DESC');
883 // instead of conditional logic:
884 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
886 * @param {String} value The value to compare to the current string
887 * @param {String} other The new value to use if the string already equals the first value passed in
888 * @return {String} The new value
891 String.prototype.toggle = function(value, other){
892 return this == value ? other : value;
895 * Ext JS Library 1.1.1
896 * Copyright(c) 2006-2007, Ext JS, LLC.
898 * Originally Released Under LGPL - original licence link has changed is not relivant.
901 * <script type="text/javascript">
907 Roo.applyIf(Number.prototype, {
909 * Checks whether or not the current number is within a desired range. If the number is already within the
910 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
911 * exceeded. Note that this method returns the constrained value but does not change the current number.
912 * @param {Number} min The minimum number in the range
913 * @param {Number} max The maximum number in the range
914 * @return {Number} The constrained value if outside the range, otherwise the current value
916 constrain : function(min, max){
917 return Math.min(Math.max(this, min), max);
921 * Ext JS Library 1.1.1
922 * Copyright(c) 2006-2007, Ext JS, LLC.
924 * Originally Released Under LGPL - original licence link has changed is not relivant.
927 * <script type="text/javascript">
932 Roo.applyIf(Array.prototype, {
935 * Checks whether or not the specified object exists in the array.
936 * @param {Object} o The object to check for
937 * @return {Number} The index of o in the array (or -1 if it is not found)
939 indexOf : function(o){
940 for (var i = 0, len = this.length; i < len; i++){
941 if(this[i] == o) return i;
947 * Removes the specified object from the array. If the object is not found nothing happens.
948 * @param {Object} o The object to remove
950 remove : function(o){
951 var index = this.indexOf(o);
953 this.splice(index, 1);
957 * Map (JS 1.6 compatibility)
958 * @param {Function} function to call
962 var len = this.length >>> 0;
963 if (typeof fun != "function")
964 throw new TypeError();
966 var res = new Array(len);
967 var thisp = arguments[1];
968 for (var i = 0; i < len; i++)
971 res[i] = fun.call(thisp, this[i], i, this);
982 * Ext JS Library 1.1.1
983 * Copyright(c) 2006-2007, Ext JS, LLC.
985 * Originally Released Under LGPL - original licence link has changed is not relivant.
988 * <script type="text/javascript">
994 * The date parsing and format syntax is a subset of
995 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
996 * supported will provide results equivalent to their PHP versions.
998 * Following is the list of all currently supported formats:
1001 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
1003 Format Output Description
1004 ------ ---------- --------------------------------------------------------------
1005 d 10 Day of the month, 2 digits with leading zeros
1006 D Wed A textual representation of a day, three letters
1007 j 10 Day of the month without leading zeros
1008 l Wednesday A full textual representation of the day of the week
1009 S th English ordinal day of month suffix, 2 chars (use with j)
1010 w 3 Numeric representation of the day of the week
1011 z 9 The julian date, or day of the year (0-365)
1012 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
1013 F January A full textual representation of the month
1014 m 01 Numeric representation of a month, with leading zeros
1015 M Jan Month name abbreviation, three letters
1016 n 1 Numeric representation of a month, without leading zeros
1017 t 31 Number of days in the given month
1018 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1019 Y 2007 A full numeric representation of a year, 4 digits
1020 y 07 A two digit representation of a year
1021 a pm Lowercase Ante meridiem and Post meridiem
1022 A PM Uppercase Ante meridiem and Post meridiem
1023 g 3 12-hour format of an hour without leading zeros
1024 G 15 24-hour format of an hour without leading zeros
1025 h 03 12-hour format of an hour with leading zeros
1026 H 15 24-hour format of an hour with leading zeros
1027 i 05 Minutes with leading zeros
1028 s 01 Seconds, with leading zeros
1029 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1030 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1031 T CST Timezone setting of the machine running the code
1032 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1035 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1037 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1038 document.write(dt.format('Y-m-d')); //2007-01-10
1039 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1040 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
1043 * Here are some standard date/time patterns that you might find helpful. They
1044 * are not part of the source of Date.js, but to use them you can simply copy this
1045 * block of code into any script that is included after Date.js and they will also become
1046 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1049 ISO8601Long:"Y-m-d H:i:s",
1050 ISO8601Short:"Y-m-d",
1052 LongDate: "l, F d, Y",
1053 FullDateTime: "l, F d, Y g:i:s A",
1056 LongTime: "g:i:s A",
1057 SortableDateTime: "Y-m-d\\TH:i:s",
1058 UniversalSortableDateTime: "Y-m-d H:i:sO",
1065 var dt = new Date();
1066 document.write(dt.format(Date.patterns.ShortDate));
1071 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1072 * They generate precompiled functions from date formats instead of parsing and
1073 * processing the pattern every time you format a date. These functions are available
1074 * on every Date object (any javascript function).
1076 * The original article and download are here:
1077 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1084 Returns the number of milliseconds between this date and date
1085 @param {Date} date (optional) Defaults to now
1086 @return {Number} The diff in milliseconds
1087 @member Date getElapsed
1089 Date.prototype.getElapsed = function(date) {
1090 return Math.abs((date || new Date()).getTime()-this.getTime());
1092 // was in date file..
1096 Date.parseFunctions = {count:0};
1098 Date.parseRegexes = [];
1100 Date.formatFunctions = {count:0};
1103 Date.prototype.dateFormat = function(format) {
1104 if (Date.formatFunctions[format] == null) {
1105 Date.createNewFormat(format);
1107 var func = Date.formatFunctions[format];
1108 return this[func]();
1113 * Formats a date given the supplied format string
1114 * @param {String} format The format string
1115 * @return {String} The formatted date
1118 Date.prototype.format = Date.prototype.dateFormat;
1121 Date.createNewFormat = function(format) {
1122 var funcName = "format" + Date.formatFunctions.count++;
1123 Date.formatFunctions[format] = funcName;
1124 var code = "Date.prototype." + funcName + " = function(){return ";
1125 var special = false;
1127 for (var i = 0; i < format.length; ++i) {
1128 ch = format.charAt(i);
1129 if (!special && ch == "\\") {
1134 code += "'" + String.escape(ch) + "' + ";
1137 code += Date.getFormatCode(ch);
1140 /** eval:var:zzzzzzzzzzzzz */
1141 eval(code.substring(0, code.length - 3) + ";}");
1145 Date.getFormatCode = function(character) {
1146 switch (character) {
1148 return "String.leftPad(this.getDate(), 2, '0') + ";
1150 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1152 return "this.getDate() + ";
1154 return "Date.dayNames[this.getDay()] + ";
1156 return "this.getSuffix() + ";
1158 return "this.getDay() + ";
1160 return "this.getDayOfYear() + ";
1162 return "this.getWeekOfYear() + ";
1164 return "Date.monthNames[this.getMonth()] + ";
1166 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1168 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1170 return "(this.getMonth() + 1) + ";
1172 return "this.getDaysInMonth() + ";
1174 return "(this.isLeapYear() ? 1 : 0) + ";
1176 return "this.getFullYear() + ";
1178 return "('' + this.getFullYear()).substring(2, 4) + ";
1180 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1182 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1184 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1186 return "this.getHours() + ";
1188 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1190 return "String.leftPad(this.getHours(), 2, '0') + ";
1192 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1194 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1196 return "this.getGMTOffset() + ";
1198 return "this.getGMTColonOffset() + ";
1200 return "this.getTimezone() + ";
1202 return "(this.getTimezoneOffset() * -60) + ";
1204 return "'" + String.escape(character) + "' + ";
1209 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1210 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1211 * the date format that is not specified will default to the current date value for that part. Time parts can also
1212 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1213 * string or the parse operation will fail.
1216 //dt = Fri May 25 2007 (current date)
1217 var dt = new Date();
1219 //dt = Thu May 25 2006 (today's month/day in 2006)
1220 dt = Date.parseDate("2006", "Y");
1222 //dt = Sun Jan 15 2006 (all date parts specified)
1223 dt = Date.parseDate("2006-1-15", "Y-m-d");
1225 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1226 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1228 * @param {String} input The unparsed date as a string
1229 * @param {String} format The format the date is in
1230 * @return {Date} The parsed date
1233 Date.parseDate = function(input, format) {
1234 if (Date.parseFunctions[format] == null) {
1235 Date.createParser(format);
1237 var func = Date.parseFunctions[format];
1238 return Date[func](input);
1244 Date.createParser = function(format) {
1245 var funcName = "parse" + Date.parseFunctions.count++;
1246 var regexNum = Date.parseRegexes.length;
1247 var currentGroup = 1;
1248 Date.parseFunctions[format] = funcName;
1250 var code = "Date." + funcName + " = function(input){\n"
1251 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1252 + "var d = new Date();\n"
1253 + "y = d.getFullYear();\n"
1254 + "m = d.getMonth();\n"
1255 + "d = d.getDate();\n"
1256 + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
1257 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1258 + "if (results && results.length > 0) {";
1261 var special = false;
1263 for (var i = 0; i < format.length; ++i) {
1264 ch = format.charAt(i);
1265 if (!special && ch == "\\") {
1270 regex += String.escape(ch);
1273 var obj = Date.formatCodeToRegex(ch, currentGroup);
1274 currentGroup += obj.g;
1276 if (obj.g && obj.c) {
1282 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1283 + "{v = new Date(y, m, d, h, i, s);}\n"
1284 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1285 + "{v = new Date(y, m, d, h, i);}\n"
1286 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1287 + "{v = new Date(y, m, d, h);}\n"
1288 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1289 + "{v = new Date(y, m, d);}\n"
1290 + "else if (y >= 0 && m >= 0)\n"
1291 + "{v = new Date(y, m);}\n"
1292 + "else if (y >= 0)\n"
1293 + "{v = new Date(y);}\n"
1294 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1295 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1296 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1299 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1300 /** eval:var:zzzzzzzzzzzzz */
1305 Date.formatCodeToRegex = function(character, currentGroup) {
1306 switch (character) {
1310 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1313 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1314 s:"(\\d{1,2})"}; // day of month without leading zeroes
1317 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1318 s:"(\\d{2})"}; // day of month with leading zeroes
1322 s:"(?:" + Date.dayNames.join("|") + ")"};
1326 s:"(?:st|nd|rd|th)"};
1341 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1342 s:"(" + Date.monthNames.join("|") + ")"};
1345 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1346 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1349 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1350 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1353 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1354 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1365 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1369 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1370 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1374 c:"if (results[" + currentGroup + "] == 'am') {\n"
1375 + "if (h == 12) { h = 0; }\n"
1376 + "} else { if (h < 12) { h += 12; }}",
1380 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1381 + "if (h == 12) { h = 0; }\n"
1382 + "} else { if (h < 12) { h += 12; }}",
1387 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1388 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1392 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1393 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1396 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1400 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1405 "o = results[", currentGroup, "];\n",
1406 "var sn = o.substring(0,1);\n", // get + / - sign
1407 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1408 "var mn = o.substring(3,5) % 60;\n", // get minutes
1409 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1410 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1412 s:"([+\-]\\d{2,4})"};
1418 "o = results[", currentGroup, "];\n",
1419 "var sn = o.substring(0,1);\n",
1420 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1421 "var mn = o.substring(4,6) % 60;\n",
1422 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1423 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1429 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1432 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1433 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1434 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1438 s:String.escape(character)};
1443 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1444 * @return {String} The abbreviated timezone name (e.g. 'CST')
1446 Date.prototype.getTimezone = function() {
1447 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1451 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1452 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1454 Date.prototype.getGMTOffset = function() {
1455 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1456 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1457 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1461 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1462 * @return {String} 2-characters representing hours and 2-characters representing minutes
1463 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1465 Date.prototype.getGMTColonOffset = function() {
1466 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1467 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1469 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1473 * Get the numeric day number of the year, adjusted for leap year.
1474 * @return {Number} 0 through 364 (365 in leap years)
1476 Date.prototype.getDayOfYear = function() {
1478 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1479 for (var i = 0; i < this.getMonth(); ++i) {
1480 num += Date.daysInMonth[i];
1482 return num + this.getDate() - 1;
1486 * Get the string representation of the numeric week number of the year
1487 * (equivalent to the format specifier 'W').
1488 * @return {String} '00' through '52'
1490 Date.prototype.getWeekOfYear = function() {
1491 // Skip to Thursday of this week
1492 var now = this.getDayOfYear() + (4 - this.getDay());
1493 // Find the first Thursday of the year
1494 var jan1 = new Date(this.getFullYear(), 0, 1);
1495 var then = (7 - jan1.getDay() + 4);
1496 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1500 * Whether or not the current date is in a leap year.
1501 * @return {Boolean} True if the current date is in a leap year, else false
1503 Date.prototype.isLeapYear = function() {
1504 var year = this.getFullYear();
1505 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1509 * Get the first 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.getFirstDayOfMonth()]); //output: 'Monday'
1517 * @return {Number} The day number (0-6)
1519 Date.prototype.getFirstDayOfMonth = function() {
1520 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1521 return (day < 0) ? (day + 7) : day;
1525 * Get the last day of the current month, adjusted for leap year. The returned value
1526 * is the numeric day index within the week (0-6) which can be used in conjunction with
1527 * the {@link #monthNames} array to retrieve the textual day name.
1530 var dt = new Date('1/10/2007');
1531 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1533 * @return {Number} The day number (0-6)
1535 Date.prototype.getLastDayOfMonth = function() {
1536 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1537 return (day < 0) ? (day + 7) : day;
1542 * Get the first date of this date's month
1545 Date.prototype.getFirstDateOfMonth = function() {
1546 return new Date(this.getFullYear(), this.getMonth(), 1);
1550 * Get the last date of this date's month
1553 Date.prototype.getLastDateOfMonth = function() {
1554 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1557 * Get the number of days in the current month, adjusted for leap year.
1558 * @return {Number} The number of days in the month
1560 Date.prototype.getDaysInMonth = function() {
1561 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1562 return Date.daysInMonth[this.getMonth()];
1566 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1567 * @return {String} 'st, 'nd', 'rd' or 'th'
1569 Date.prototype.getSuffix = function() {
1570 switch (this.getDate()) {
1587 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1590 * An array of textual month names.
1591 * Override these values for international dates, for example...
1592 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1611 * An array of textual day names.
1612 * Override these values for international dates, for example...
1613 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1629 Date.monthNumbers = {
1644 * Creates and returns a new Date instance with the exact same date value as the called instance.
1645 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1646 * variable will also be changed. When the intention is to create a new variable that will not
1647 * modify the original instance, you should create a clone.
1649 * Example of correctly cloning a date:
1652 var orig = new Date('10/1/2006');
1655 document.write(orig); //returns 'Thu Oct 05 2006'!
1658 var orig = new Date('10/1/2006');
1659 var copy = orig.clone();
1661 document.write(orig); //returns 'Thu Oct 01 2006'
1663 * @return {Date} The new Date instance
1665 Date.prototype.clone = function() {
1666 return new Date(this.getTime());
1670 * Clears any time information from this date
1671 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1672 @return {Date} this or the clone
1674 Date.prototype.clearTime = function(clone){
1676 return this.clone().clearTime();
1681 this.setMilliseconds(0);
1686 // safari setMonth is broken
1688 Date.brokenSetMonth = Date.prototype.setMonth;
1689 Date.prototype.setMonth = function(num){
1691 var n = Math.ceil(-num);
1692 var back_year = Math.ceil(n/12);
1693 var month = (n % 12) ? 12 - n % 12 : 0 ;
1694 this.setFullYear(this.getFullYear() - back_year);
1695 return Date.brokenSetMonth.call(this, month);
1697 return Date.brokenSetMonth.apply(this, arguments);
1702 /** Date interval constant
1706 /** Date interval constant
1710 /** Date interval constant
1714 /** Date interval constant
1718 /** Date interval constant
1722 /** Date interval constant
1726 /** Date interval constant
1732 * Provides a convenient method of performing basic date arithmetic. This method
1733 * does not modify the Date instance being called - it creates and returns
1734 * a new Date instance containing the resulting date value.
1739 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1740 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1742 //Negative values will subtract correctly:
1743 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1744 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1746 //You can even chain several calls together in one line!
1747 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1748 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1751 * @param {String} interval A valid date interval enum value
1752 * @param {Number} value The amount to add to the current date
1753 * @return {Date} The new Date instance
1755 Date.prototype.add = function(interval, value){
1756 var d = this.clone();
1757 if (!interval || value === 0) return d;
1758 switch(interval.toLowerCase()){
1760 d.setMilliseconds(this.getMilliseconds() + value);
1763 d.setSeconds(this.getSeconds() + value);
1766 d.setMinutes(this.getMinutes() + value);
1769 d.setHours(this.getHours() + value);
1772 d.setDate(this.getDate() + value);
1775 var day = this.getDate();
1777 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1780 d.setMonth(this.getMonth() + value);
1783 d.setFullYear(this.getFullYear() + value);
1790 * Ext JS Library 1.1.1
1791 * Copyright(c) 2006-2007, Ext JS, LLC.
1793 * Originally Released Under LGPL - original licence link has changed is not relivant.
1796 * <script type="text/javascript">
1800 * @class Roo.lib.Dom
1803 * Dom utils (from YIU afaik)
1808 * Get the view width
1809 * @param {Boolean} full True will get the full document, otherwise it's the view width
1810 * @return {Number} The width
1813 getViewWidth : function(full) {
1814 return full ? this.getDocumentWidth() : this.getViewportWidth();
1817 * Get the view height
1818 * @param {Boolean} full True will get the full document, otherwise it's the view height
1819 * @return {Number} The height
1821 getViewHeight : function(full) {
1822 return full ? this.getDocumentHeight() : this.getViewportHeight();
1825 getDocumentHeight: function() {
1826 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1827 return Math.max(scrollHeight, this.getViewportHeight());
1830 getDocumentWidth: function() {
1831 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1832 return Math.max(scrollWidth, this.getViewportWidth());
1835 getViewportHeight: function() {
1836 var height = self.innerHeight;
1837 var mode = document.compatMode;
1839 if ((mode || Roo.isIE) && !Roo.isOpera) {
1840 height = (mode == "CSS1Compat") ?
1841 document.documentElement.clientHeight :
1842 document.body.clientHeight;
1848 getViewportWidth: function() {
1849 var width = self.innerWidth;
1850 var mode = document.compatMode;
1852 if (mode || Roo.isIE) {
1853 width = (mode == "CSS1Compat") ?
1854 document.documentElement.clientWidth :
1855 document.body.clientWidth;
1860 isAncestor : function(p, c) {
1867 if (p.contains && !Roo.isSafari) {
1868 return p.contains(c);
1869 } else if (p.compareDocumentPosition) {
1870 return !!(p.compareDocumentPosition(c) & 16);
1872 var parent = c.parentNode;
1877 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1880 parent = parent.parentNode;
1886 getRegion : function(el) {
1887 return Roo.lib.Region.getRegion(el);
1890 getY : function(el) {
1891 return this.getXY(el)[1];
1894 getX : function(el) {
1895 return this.getXY(el)[0];
1898 getXY : function(el) {
1899 var p, pe, b, scroll, bd = document.body;
1900 el = Roo.getDom(el);
1901 var fly = Roo.lib.AnimBase.fly;
1902 if (el.getBoundingClientRect) {
1903 b = el.getBoundingClientRect();
1904 scroll = fly(document).getScroll();
1905 return [b.left + scroll.left, b.top + scroll.top];
1911 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1918 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1925 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1926 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1933 if (p != el && pe.getStyle('overflow') != 'visible') {
1941 if (Roo.isSafari && hasAbsolute) {
1946 if (Roo.isGecko && !hasAbsolute) {
1948 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1949 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1953 while (p && p != bd) {
1954 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1966 setXY : function(el, xy) {
1967 el = Roo.fly(el, '_setXY');
1969 var pts = el.translatePoints(xy);
1970 if (xy[0] !== false) {
1971 el.dom.style.left = pts.left + "px";
1973 if (xy[1] !== false) {
1974 el.dom.style.top = pts.top + "px";
1978 setX : function(el, x) {
1979 this.setXY(el, [x, false]);
1982 setY : function(el, y) {
1983 this.setXY(el, [false, y]);
1987 * Portions of this file are based on pieces of Yahoo User Interface Library
1988 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1989 * YUI licensed under the BSD License:
1990 * http://developer.yahoo.net/yui/license.txt
1991 * <script type="text/javascript">
1995 Roo.lib.Event = function() {
1996 var loadComplete = false;
1998 var unloadListeners = [];
2000 var onAvailStack = [];
2002 var lastError = null;
2015 startInterval: function() {
2016 if (!this._interval) {
2018 var callback = function() {
2019 self._tryPreloadAttach();
2021 this._interval = setInterval(callback, this.POLL_INTERVAL);
2026 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2027 onAvailStack.push({ id: p_id,
2030 override: p_override,
2031 checkReady: false });
2033 retryCount = this.POLL_RETRYS;
2034 this.startInterval();
2038 addListener: function(el, eventName, fn) {
2039 el = Roo.getDom(el);
2044 if ("unload" == eventName) {
2045 unloadListeners[unloadListeners.length] =
2046 [el, eventName, fn];
2050 var wrappedFn = function(e) {
2051 return fn(Roo.lib.Event.getEvent(e));
2054 var li = [el, eventName, fn, wrappedFn];
2056 var index = listeners.length;
2057 listeners[index] = li;
2059 this.doAdd(el, eventName, wrappedFn, false);
2065 removeListener: function(el, eventName, fn) {
2068 el = Roo.getDom(el);
2071 return this.purgeElement(el, false, eventName);
2075 if ("unload" == eventName) {
2077 for (i = 0,len = unloadListeners.length; i < len; i++) {
2078 var li = unloadListeners[i];
2081 li[1] == eventName &&
2083 unloadListeners.splice(i, 1);
2091 var cacheItem = null;
2094 var index = arguments[3];
2096 if ("undefined" == typeof index) {
2097 index = this._getCacheIndex(el, eventName, fn);
2101 cacheItem = listeners[index];
2104 if (!el || !cacheItem) {
2108 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2110 delete listeners[index][this.WFN];
2111 delete listeners[index][this.FN];
2112 listeners.splice(index, 1);
2119 getTarget: function(ev, resolveTextNode) {
2120 ev = ev.browserEvent || ev;
2121 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2122 var t = ev.target || ev.srcElement;
2123 return this.resolveTextNode(t);
2127 resolveTextNode: function(node) {
2128 if (Roo.isSafari && node && 3 == node.nodeType) {
2129 return node.parentNode;
2136 getPageX: function(ev) {
2137 ev = ev.browserEvent || ev;
2138 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2140 if (!x && 0 !== x) {
2141 x = ev.clientX || 0;
2144 x += this.getScroll()[1];
2152 getPageY: function(ev) {
2153 ev = ev.browserEvent || ev;
2154 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2156 if (!y && 0 !== y) {
2157 y = ev.clientY || 0;
2160 y += this.getScroll()[0];
2169 getXY: function(ev) {
2170 ev = ev.browserEvent || ev;
2171 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2172 return [this.getPageX(ev), this.getPageY(ev)];
2176 getRelatedTarget: function(ev) {
2177 ev = ev.browserEvent || ev;
2178 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2179 var t = ev.relatedTarget;
2181 if (ev.type == "mouseout") {
2183 } else if (ev.type == "mouseover") {
2188 return this.resolveTextNode(t);
2192 getTime: function(ev) {
2193 ev = ev.browserEvent || ev;
2194 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2196 var t = new Date().getTime();
2200 this.lastError = ex;
2209 stopEvent: function(ev) {
2210 this.stopPropagation(ev);
2211 this.preventDefault(ev);
2215 stopPropagation: function(ev) {
2216 ev = ev.browserEvent || ev;
2217 if (ev.stopPropagation) {
2218 ev.stopPropagation();
2220 ev.cancelBubble = true;
2225 preventDefault: function(ev) {
2226 ev = ev.browserEvent || ev;
2227 if(ev.preventDefault) {
2228 ev.preventDefault();
2230 ev.returnValue = false;
2235 getEvent: function(e) {
2236 var ev = e || window.event;
2238 var c = this.getEvent.caller;
2240 ev = c.arguments[0];
2241 if (ev && Event == ev.constructor) {
2251 getCharCode: function(ev) {
2252 ev = ev.browserEvent || ev;
2253 return ev.charCode || ev.keyCode || 0;
2257 _getCacheIndex: function(el, eventName, fn) {
2258 for (var i = 0,len = listeners.length; i < len; ++i) {
2259 var li = listeners[i];
2261 li[this.FN] == fn &&
2262 li[this.EL] == el &&
2263 li[this.TYPE] == eventName) {
2275 getEl: function(id) {
2276 return document.getElementById(id);
2280 clearCache: function() {
2284 _load: function(e) {
2285 loadComplete = true;
2286 var EU = Roo.lib.Event;
2290 EU.doRemove(window, "load", EU._load);
2295 _tryPreloadAttach: function() {
2304 var tryAgain = !loadComplete;
2306 tryAgain = (retryCount > 0);
2311 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2312 var item = onAvailStack[i];
2314 var el = this.getEl(item.id);
2317 if (!item.checkReady ||
2320 (document && document.body)) {
2323 if (item.override) {
2324 if (item.override === true) {
2327 scope = item.override;
2330 item.fn.call(scope, item.obj);
2331 onAvailStack[i] = null;
2334 notAvail.push(item);
2339 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2343 this.startInterval();
2345 clearInterval(this._interval);
2346 this._interval = null;
2349 this.locked = false;
2356 purgeElement: function(el, recurse, eventName) {
2357 var elListeners = this.getListeners(el, eventName);
2359 for (var i = 0,len = elListeners.length; i < len; ++i) {
2360 var l = elListeners[i];
2361 this.removeListener(el, l.type, l.fn);
2365 if (recurse && el && el.childNodes) {
2366 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2367 this.purgeElement(el.childNodes[i], recurse, eventName);
2373 getListeners: function(el, eventName) {
2374 var results = [], searchLists;
2376 searchLists = [listeners, unloadListeners];
2377 } else if (eventName == "unload") {
2378 searchLists = [unloadListeners];
2380 searchLists = [listeners];
2383 for (var j = 0; j < searchLists.length; ++j) {
2384 var searchList = searchLists[j];
2385 if (searchList && searchList.length > 0) {
2386 for (var i = 0,len = searchList.length; i < len; ++i) {
2387 var l = searchList[i];
2388 if (l && l[this.EL] === el &&
2389 (!eventName || eventName === l[this.TYPE])) {
2394 adjust: l[this.ADJ_SCOPE],
2402 return (results.length) ? results : null;
2406 _unload: function(e) {
2408 var EU = Roo.lib.Event, i, j, l, len, index;
2410 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2411 l = unloadListeners[i];
2414 if (l[EU.ADJ_SCOPE]) {
2415 if (l[EU.ADJ_SCOPE] === true) {
2418 scope = l[EU.ADJ_SCOPE];
2421 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2422 unloadListeners[i] = null;
2428 unloadListeners = null;
2430 if (listeners && listeners.length > 0) {
2431 j = listeners.length;
2434 l = listeners[index];
2436 EU.removeListener(l[EU.EL], l[EU.TYPE],
2446 EU.doRemove(window, "unload", EU._unload);
2451 getScroll: function() {
2452 var dd = document.documentElement, db = document.body;
2453 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2454 return [dd.scrollTop, dd.scrollLeft];
2456 return [db.scrollTop, db.scrollLeft];
2463 doAdd: function () {
2464 if (window.addEventListener) {
2465 return function(el, eventName, fn, capture) {
2466 el.addEventListener(eventName, fn, (capture));
2468 } else if (window.attachEvent) {
2469 return function(el, eventName, fn, capture) {
2470 el.attachEvent("on" + eventName, fn);
2479 doRemove: function() {
2480 if (window.removeEventListener) {
2481 return function (el, eventName, fn, capture) {
2482 el.removeEventListener(eventName, fn, (capture));
2484 } else if (window.detachEvent) {
2485 return function (el, eventName, fn) {
2486 el.detachEvent("on" + eventName, fn);
2498 var E = Roo.lib.Event;
2499 E.on = E.addListener;
2500 E.un = E.removeListener;
2502 if (document && document.body) {
2505 E.doAdd(window, "load", E._load);
2507 E.doAdd(window, "unload", E._unload);
2508 E._tryPreloadAttach();
2512 * Portions of this file are based on pieces of Yahoo User Interface Library
2513 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2514 * YUI licensed under the BSD License:
2515 * http://developer.yahoo.net/yui/license.txt
2516 * <script type="text/javascript">
2522 * @class Roo.lib.Ajax
2529 request : function(method, uri, cb, data, options) {
2531 var hs = options.headers;
2534 if(hs.hasOwnProperty(h)){
2535 this.initHeader(h, hs[h], false);
2539 if(options.xmlData){
2540 this.initHeader('Content-Type', 'text/xml', false);
2542 data = options.xmlData;
2546 return this.asyncRequest(method, uri, cb, data);
2549 serializeForm : function(form) {
2550 if(typeof form == 'string') {
2551 form = (document.getElementById(form) || document.forms[form]);
2554 var el, name, val, disabled, data = '', hasSubmit = false;
2555 for (var i = 0; i < form.elements.length; i++) {
2556 el = form.elements[i];
2557 disabled = form.elements[i].disabled;
2558 name = form.elements[i].name;
2559 val = form.elements[i].value;
2561 if (!disabled && name){
2565 case 'select-multiple':
2566 for (var j = 0; j < el.options.length; j++) {
2567 if (el.options[j].selected) {
2569 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2572 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2580 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2593 if(hasSubmit == false) {
2594 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2599 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2604 data = data.substr(0, data.length - 1);
2612 useDefaultHeader:true,
2614 defaultPostHeader:'application/x-www-form-urlencoded',
2616 useDefaultXhrHeader:true,
2618 defaultXhrHeader:'XMLHttpRequest',
2620 hasDefaultHeaders:true,
2632 setProgId:function(id)
2634 this.activeX.unshift(id);
2637 setDefaultPostHeader:function(b)
2639 this.useDefaultHeader = b;
2642 setDefaultXhrHeader:function(b)
2644 this.useDefaultXhrHeader = b;
2647 setPollingInterval:function(i)
2649 if (typeof i == 'number' && isFinite(i)) {
2650 this.pollInterval = i;
2654 createXhrObject:function(transactionId)
2660 http = new XMLHttpRequest();
2662 obj = { conn:http, tId:transactionId };
2666 for (var i = 0; i < this.activeX.length; ++i) {
2670 http = new ActiveXObject(this.activeX[i]);
2672 obj = { conn:http, tId:transactionId };
2685 getConnectionObject:function()
2688 var tId = this.transactionId;
2692 o = this.createXhrObject(tId);
2694 this.transactionId++;
2705 asyncRequest:function(method, uri, callback, postData)
2707 var o = this.getConnectionObject();
2713 o.conn.open(method, uri, true);
2715 if (this.useDefaultXhrHeader) {
2716 if (!this.defaultHeaders['X-Requested-With']) {
2717 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2721 if(postData && this.useDefaultHeader){
2722 this.initHeader('Content-Type', this.defaultPostHeader);
2725 if (this.hasDefaultHeaders || this.hasHeaders) {
2729 this.handleReadyState(o, callback);
2730 o.conn.send(postData || null);
2736 handleReadyState:function(o, callback)
2740 if (callback && callback.timeout) {
2742 this.timeout[o.tId] = window.setTimeout(function() {
2743 oConn.abort(o, callback, true);
2744 }, callback.timeout);
2747 this.poll[o.tId] = window.setInterval(
2749 if (o.conn && o.conn.readyState == 4) {
2750 window.clearInterval(oConn.poll[o.tId]);
2751 delete oConn.poll[o.tId];
2753 if(callback && callback.timeout) {
2754 window.clearTimeout(oConn.timeout[o.tId]);
2755 delete oConn.timeout[o.tId];
2758 oConn.handleTransactionResponse(o, callback);
2761 , this.pollInterval);
2764 handleTransactionResponse:function(o, callback, isAbort)
2768 this.releaseObject(o);
2772 var httpStatus, responseObject;
2776 if (o.conn.status !== undefined && o.conn.status != 0) {
2777 httpStatus = o.conn.status;
2789 if (httpStatus >= 200 && httpStatus < 300) {
2790 responseObject = this.createResponseObject(o, callback.argument);
2791 if (callback.success) {
2792 if (!callback.scope) {
2793 callback.success(responseObject);
2798 callback.success.apply(callback.scope, [responseObject]);
2803 switch (httpStatus) {
2811 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2812 if (callback.failure) {
2813 if (!callback.scope) {
2814 callback.failure(responseObject);
2817 callback.failure.apply(callback.scope, [responseObject]);
2822 responseObject = this.createResponseObject(o, callback.argument);
2823 if (callback.failure) {
2824 if (!callback.scope) {
2825 callback.failure(responseObject);
2828 callback.failure.apply(callback.scope, [responseObject]);
2834 this.releaseObject(o);
2835 responseObject = null;
2838 createResponseObject:function(o, callbackArg)
2845 var headerStr = o.conn.getAllResponseHeaders();
2846 var header = headerStr.split('\n');
2847 for (var i = 0; i < header.length; i++) {
2848 var delimitPos = header[i].indexOf(':');
2849 if (delimitPos != -1) {
2850 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2858 obj.status = o.conn.status;
2859 obj.statusText = o.conn.statusText;
2860 obj.getResponseHeader = headerObj;
2861 obj.getAllResponseHeaders = headerStr;
2862 obj.responseText = o.conn.responseText;
2863 obj.responseXML = o.conn.responseXML;
2865 if (typeof callbackArg !== undefined) {
2866 obj.argument = callbackArg;
2872 createExceptionObject:function(tId, callbackArg, isAbort)
2875 var COMM_ERROR = 'communication failure';
2876 var ABORT_CODE = -1;
2877 var ABORT_ERROR = 'transaction aborted';
2883 obj.status = ABORT_CODE;
2884 obj.statusText = ABORT_ERROR;
2887 obj.status = COMM_CODE;
2888 obj.statusText = COMM_ERROR;
2892 obj.argument = callbackArg;
2898 initHeader:function(label, value, isDefault)
2900 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2902 if (headerObj[label] === undefined) {
2903 headerObj[label] = value;
2908 headerObj[label] = value + "," + headerObj[label];
2912 this.hasDefaultHeaders = true;
2915 this.hasHeaders = true;
2920 setHeader:function(o)
2922 if (this.hasDefaultHeaders) {
2923 for (var prop in this.defaultHeaders) {
2924 if (this.defaultHeaders.hasOwnProperty(prop)) {
2925 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2930 if (this.hasHeaders) {
2931 for (var prop in this.headers) {
2932 if (this.headers.hasOwnProperty(prop)) {
2933 o.conn.setRequestHeader(prop, this.headers[prop]);
2937 this.hasHeaders = false;
2941 resetDefaultHeaders:function() {
2942 delete this.defaultHeaders;
2943 this.defaultHeaders = {};
2944 this.hasDefaultHeaders = false;
2947 abort:function(o, callback, isTimeout)
2949 if(this.isCallInProgress(o)) {
2951 window.clearInterval(this.poll[o.tId]);
2952 delete this.poll[o.tId];
2954 delete this.timeout[o.tId];
2957 this.handleTransactionResponse(o, callback, true);
2967 isCallInProgress:function(o)
2970 return o.conn.readyState != 4 && o.conn.readyState != 0;
2979 releaseObject:function(o)
2988 'MSXML2.XMLHTTP.3.0',
2996 * Portions of this file are based on pieces of Yahoo User Interface Library
2997 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2998 * YUI licensed under the BSD License:
2999 * http://developer.yahoo.net/yui/license.txt
3000 * <script type="text/javascript">
3004 Roo.lib.Region = function(t, r, b, l) {
3014 Roo.lib.Region.prototype = {
3015 contains : function(region) {
3016 return ( region.left >= this.left &&
3017 region.right <= this.right &&
3018 region.top >= this.top &&
3019 region.bottom <= this.bottom );
3023 getArea : function() {
3024 return ( (this.bottom - this.top) * (this.right - this.left) );
3027 intersect : function(region) {
3028 var t = Math.max(this.top, region.top);
3029 var r = Math.min(this.right, region.right);
3030 var b = Math.min(this.bottom, region.bottom);
3031 var l = Math.max(this.left, region.left);
3033 if (b >= t && r >= l) {
3034 return new Roo.lib.Region(t, r, b, l);
3039 union : function(region) {
3040 var t = Math.min(this.top, region.top);
3041 var r = Math.max(this.right, region.right);
3042 var b = Math.max(this.bottom, region.bottom);
3043 var l = Math.min(this.left, region.left);
3045 return new Roo.lib.Region(t, r, b, l);
3048 adjust : function(t, l, b, r) {
3057 Roo.lib.Region.getRegion = function(el) {
3058 var p = Roo.lib.Dom.getXY(el);
3061 var r = p[0] + el.offsetWidth;
3062 var b = p[1] + el.offsetHeight;
3065 return new Roo.lib.Region(t, r, b, l);
3068 * Portions of this file are based on pieces of Yahoo User Interface Library
3069 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3070 * YUI licensed under the BSD License:
3071 * http://developer.yahoo.net/yui/license.txt
3072 * <script type="text/javascript">
3075 //@@dep Roo.lib.Region
3078 Roo.lib.Point = function(x, y) {
3079 if (x instanceof Array) {
3083 this.x = this.right = this.left = this[0] = x;
3084 this.y = this.top = this.bottom = this[1] = y;
3087 Roo.lib.Point.prototype = new Roo.lib.Region();
3089 * Portions of this file are based on pieces of Yahoo User Interface Library
3090 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3091 * YUI licensed under the BSD License:
3092 * http://developer.yahoo.net/yui/license.txt
3093 * <script type="text/javascript">
3100 scroll : function(el, args, duration, easing, cb, scope) {
3101 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3104 motion : function(el, args, duration, easing, cb, scope) {
3105 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3108 color : function(el, args, duration, easing, cb, scope) {
3109 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3112 run : function(el, args, duration, easing, cb, scope, type) {
3113 type = type || Roo.lib.AnimBase;
3114 if (typeof easing == "string") {
3115 easing = Roo.lib.Easing[easing];
3117 var anim = new type(el, args, duration, easing);
3118 anim.animateX(function() {
3119 Roo.callback(cb, scope);
3125 * Portions of this file are based on pieces of Yahoo User Interface Library
3126 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3127 * YUI licensed under the BSD License:
3128 * http://developer.yahoo.net/yui/license.txt
3129 * <script type="text/javascript">
3137 if (!libFlyweight) {
3138 libFlyweight = new Roo.Element.Flyweight();
3140 libFlyweight.dom = el;
3141 return libFlyweight;
3144 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3148 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3150 this.init(el, attributes, duration, method);
3154 Roo.lib.AnimBase.fly = fly;
3158 Roo.lib.AnimBase.prototype = {
3160 toString: function() {
3161 var el = this.getEl();
3162 var id = el.id || el.tagName;
3163 return ("Anim " + id);
3167 noNegatives: /width|height|opacity|padding/i,
3168 offsetAttribute: /^((width|height)|(top|left))$/,
3169 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3170 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3174 doMethod: function(attr, start, end) {
3175 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3179 setAttribute: function(attr, val, unit) {
3180 if (this.patterns.noNegatives.test(attr)) {
3181 val = (val > 0) ? val : 0;
3184 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3188 getAttribute: function(attr) {
3189 var el = this.getEl();
3190 var val = fly(el).getStyle(attr);
3192 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3193 return parseFloat(val);
3196 var a = this.patterns.offsetAttribute.exec(attr) || [];
3197 var pos = !!( a[3] );
3198 var box = !!( a[2] );
3201 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3202 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3211 getDefaultUnit: function(attr) {
3212 if (this.patterns.defaultUnit.test(attr)) {
3219 animateX : function(callback, scope) {
3220 var f = function() {
3221 this.onComplete.removeListener(f);
3222 if (typeof callback == "function") {
3223 callback.call(scope || this, this);
3226 this.onComplete.addListener(f, this);
3231 setRuntimeAttribute: function(attr) {
3234 var attributes = this.attributes;
3236 this.runtimeAttributes[attr] = {};
3238 var isset = function(prop) {
3239 return (typeof prop !== 'undefined');
3242 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3246 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3249 if (isset(attributes[attr]['to'])) {
3250 end = attributes[attr]['to'];
3251 } else if (isset(attributes[attr]['by'])) {
3252 if (start.constructor == Array) {
3254 for (var i = 0, len = start.length; i < len; ++i) {
3255 end[i] = start[i] + attributes[attr]['by'][i];
3258 end = start + attributes[attr]['by'];
3262 this.runtimeAttributes[attr].start = start;
3263 this.runtimeAttributes[attr].end = end;
3266 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3270 init: function(el, attributes, duration, method) {
3272 var isAnimated = false;
3275 var startTime = null;
3278 var actualFrames = 0;
3281 el = Roo.getDom(el);
3284 this.attributes = attributes || {};
3287 this.duration = duration || 1;
3290 this.method = method || Roo.lib.Easing.easeNone;
3293 this.useSeconds = true;
3296 this.currentFrame = 0;
3299 this.totalFrames = Roo.lib.AnimMgr.fps;
3302 this.getEl = function() {
3307 this.isAnimated = function() {
3312 this.getStartTime = function() {
3316 this.runtimeAttributes = {};
3319 this.animate = function() {
3320 if (this.isAnimated()) {
3324 this.currentFrame = 0;
3326 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3328 Roo.lib.AnimMgr.registerElement(this);
3332 this.stop = function(finish) {
3334 this.currentFrame = this.totalFrames;
3335 this._onTween.fire();
3337 Roo.lib.AnimMgr.stop(this);
3340 var onStart = function() {
3341 this.onStart.fire();
3343 this.runtimeAttributes = {};
3344 for (var attr in this.attributes) {
3345 this.setRuntimeAttribute(attr);
3350 startTime = new Date();
3354 var onTween = function() {
3356 duration: new Date() - this.getStartTime(),
3357 currentFrame: this.currentFrame
3360 data.toString = function() {
3362 'duration: ' + data.duration +
3363 ', currentFrame: ' + data.currentFrame
3367 this.onTween.fire(data);
3369 var runtimeAttributes = this.runtimeAttributes;
3371 for (var attr in runtimeAttributes) {
3372 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3378 var onComplete = function() {
3379 var actual_duration = (new Date() - startTime) / 1000 ;
3382 duration: actual_duration,
3383 frames: actualFrames,
3384 fps: actualFrames / actual_duration
3387 data.toString = function() {
3389 'duration: ' + data.duration +
3390 ', frames: ' + data.frames +
3391 ', fps: ' + data.fps
3397 this.onComplete.fire(data);
3401 this._onStart = new Roo.util.Event(this);
3402 this.onStart = new Roo.util.Event(this);
3403 this.onTween = new Roo.util.Event(this);
3404 this._onTween = new Roo.util.Event(this);
3405 this.onComplete = new Roo.util.Event(this);
3406 this._onComplete = new Roo.util.Event(this);
3407 this._onStart.addListener(onStart);
3408 this._onTween.addListener(onTween);
3409 this._onComplete.addListener(onComplete);
3414 * Portions of this file are based on pieces of Yahoo User Interface Library
3415 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3416 * YUI licensed under the BSD License:
3417 * http://developer.yahoo.net/yui/license.txt
3418 * <script type="text/javascript">
3422 Roo.lib.AnimMgr = new function() {
3439 this.registerElement = function(tween) {
3440 queue[queue.length] = tween;
3442 tween._onStart.fire();
3447 this.unRegister = function(tween, index) {
3448 tween._onComplete.fire();
3449 index = index || getIndex(tween);
3451 queue.splice(index, 1);
3455 if (tweenCount <= 0) {
3461 this.start = function() {
3462 if (thread === null) {
3463 thread = setInterval(this.run, this.delay);
3468 this.stop = function(tween) {
3470 clearInterval(thread);
3472 for (var i = 0, len = queue.length; i < len; ++i) {
3473 if (queue[0].isAnimated()) {
3474 this.unRegister(queue[0], 0);
3483 this.unRegister(tween);
3488 this.run = function() {
3489 for (var i = 0, len = queue.length; i < len; ++i) {
3490 var tween = queue[i];
3491 if (!tween || !tween.isAnimated()) {
3495 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3497 tween.currentFrame += 1;
3499 if (tween.useSeconds) {
3500 correctFrame(tween);
3502 tween._onTween.fire();
3505 Roo.lib.AnimMgr.stop(tween, i);
3510 var getIndex = function(anim) {
3511 for (var i = 0, len = queue.length; i < len; ++i) {
3512 if (queue[i] == anim) {
3520 var correctFrame = function(tween) {
3521 var frames = tween.totalFrames;
3522 var frame = tween.currentFrame;
3523 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3524 var elapsed = (new Date() - tween.getStartTime());
3527 if (elapsed < tween.duration * 1000) {
3528 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3530 tweak = frames - (frame + 1);
3532 if (tweak > 0 && isFinite(tweak)) {
3533 if (tween.currentFrame + tweak >= frames) {
3534 tweak = frames - (frame + 1);
3537 tween.currentFrame += tweak;
3543 * Portions of this file are based on pieces of Yahoo User Interface Library
3544 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3545 * YUI licensed under the BSD License:
3546 * http://developer.yahoo.net/yui/license.txt
3547 * <script type="text/javascript">
3550 Roo.lib.Bezier = new function() {
3552 this.getPosition = function(points, t) {
3553 var n = points.length;
3556 for (var i = 0; i < n; ++i) {
3557 tmp[i] = [points[i][0], points[i][1]];
3560 for (var j = 1; j < n; ++j) {
3561 for (i = 0; i < n - j; ++i) {
3562 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3563 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3567 return [ tmp[0][0], tmp[0][1] ];
3571 * Portions of this file are based on pieces of Yahoo User Interface Library
3572 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3573 * YUI licensed under the BSD License:
3574 * http://developer.yahoo.net/yui/license.txt
3575 * <script type="text/javascript">
3580 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3581 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3584 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3586 var fly = Roo.lib.AnimBase.fly;
3588 var superclass = Y.ColorAnim.superclass;
3589 var proto = Y.ColorAnim.prototype;
3591 proto.toString = function() {
3592 var el = this.getEl();
3593 var id = el.id || el.tagName;
3594 return ("ColorAnim " + id);
3597 proto.patterns.color = /color$/i;
3598 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3599 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3600 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3601 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3604 proto.parseColor = function(s) {
3605 if (s.length == 3) {
3609 var c = this.patterns.hex.exec(s);
3610 if (c && c.length == 4) {
3611 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3614 c = this.patterns.rgb.exec(s);
3615 if (c && c.length == 4) {
3616 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3619 c = this.patterns.hex3.exec(s);
3620 if (c && c.length == 4) {
3621 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3626 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3627 proto.getAttribute = function(attr) {
3628 var el = this.getEl();
3629 if (this.patterns.color.test(attr)) {
3630 var val = fly(el).getStyle(attr);
3632 if (this.patterns.transparent.test(val)) {
3633 var parent = el.parentNode;
3634 val = fly(parent).getStyle(attr);
3636 while (parent && this.patterns.transparent.test(val)) {
3637 parent = parent.parentNode;
3638 val = fly(parent).getStyle(attr);
3639 if (parent.tagName.toUpperCase() == 'HTML') {
3645 val = superclass.getAttribute.call(this, attr);
3650 proto.getAttribute = function(attr) {
3651 var el = this.getEl();
3652 if (this.patterns.color.test(attr)) {
3653 var val = fly(el).getStyle(attr);
3655 if (this.patterns.transparent.test(val)) {
3656 var parent = el.parentNode;
3657 val = fly(parent).getStyle(attr);
3659 while (parent && this.patterns.transparent.test(val)) {
3660 parent = parent.parentNode;
3661 val = fly(parent).getStyle(attr);
3662 if (parent.tagName.toUpperCase() == 'HTML') {
3668 val = superclass.getAttribute.call(this, attr);
3674 proto.doMethod = function(attr, start, end) {
3677 if (this.patterns.color.test(attr)) {
3679 for (var i = 0, len = start.length; i < len; ++i) {
3680 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3683 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3686 val = superclass.doMethod.call(this, attr, start, end);
3692 proto.setRuntimeAttribute = function(attr) {
3693 superclass.setRuntimeAttribute.call(this, attr);
3695 if (this.patterns.color.test(attr)) {
3696 var attributes = this.attributes;
3697 var start = this.parseColor(this.runtimeAttributes[attr].start);
3698 var end = this.parseColor(this.runtimeAttributes[attr].end);
3700 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3701 end = this.parseColor(attributes[attr].by);
3703 for (var i = 0, len = start.length; i < len; ++i) {
3704 end[i] = start[i] + end[i];
3708 this.runtimeAttributes[attr].start = start;
3709 this.runtimeAttributes[attr].end = end;
3715 * Portions of this file are based on pieces of Yahoo User Interface Library
3716 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3717 * YUI licensed under the BSD License:
3718 * http://developer.yahoo.net/yui/license.txt
3719 * <script type="text/javascript">
3725 easeNone: function (t, b, c, d) {
3726 return c * t / d + b;
3730 easeIn: function (t, b, c, d) {
3731 return c * (t /= d) * t + b;
3735 easeOut: function (t, b, c, d) {
3736 return -c * (t /= d) * (t - 2) + b;
3740 easeBoth: function (t, b, c, d) {
3741 if ((t /= d / 2) < 1) {
3742 return c / 2 * t * t + b;
3745 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3749 easeInStrong: function (t, b, c, d) {
3750 return c * (t /= d) * t * t * t + b;
3754 easeOutStrong: function (t, b, c, d) {
3755 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3759 easeBothStrong: function (t, b, c, d) {
3760 if ((t /= d / 2) < 1) {
3761 return c / 2 * t * t * t * t + b;
3764 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3769 elasticIn: function (t, b, c, d, a, p) {
3773 if ((t /= d) == 1) {
3780 if (!a || a < Math.abs(c)) {
3785 var s = p / (2 * Math.PI) * Math.asin(c / a);
3788 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3792 elasticOut: function (t, b, c, d, a, p) {
3796 if ((t /= d) == 1) {
3803 if (!a || a < Math.abs(c)) {
3808 var s = p / (2 * Math.PI) * Math.asin(c / a);
3811 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3815 elasticBoth: function (t, b, c, d, a, p) {
3820 if ((t /= d / 2) == 2) {
3828 if (!a || a < Math.abs(c)) {
3833 var s = p / (2 * Math.PI) * Math.asin(c / a);
3837 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3838 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3840 return a * Math.pow(2, -10 * (t -= 1)) *
3841 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3846 backIn: function (t, b, c, d, s) {
3847 if (typeof s == 'undefined') {
3850 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3854 backOut: function (t, b, c, d, s) {
3855 if (typeof s == 'undefined') {
3858 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3862 backBoth: function (t, b, c, d, s) {
3863 if (typeof s == 'undefined') {
3867 if ((t /= d / 2 ) < 1) {
3868 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3870 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3874 bounceIn: function (t, b, c, d) {
3875 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3879 bounceOut: function (t, b, c, d) {
3880 if ((t /= d) < (1 / 2.75)) {
3881 return c * (7.5625 * t * t) + b;
3882 } else if (t < (2 / 2.75)) {
3883 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3884 } else if (t < (2.5 / 2.75)) {
3885 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3887 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3891 bounceBoth: function (t, b, c, d) {
3893 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3895 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3898 * Portions of this file are based on pieces of Yahoo User Interface Library
3899 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3900 * YUI licensed under the BSD License:
3901 * http://developer.yahoo.net/yui/license.txt
3902 * <script type="text/javascript">
3906 Roo.lib.Motion = function(el, attributes, duration, method) {
3908 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3912 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3916 var superclass = Y.Motion.superclass;
3917 var proto = Y.Motion.prototype;
3919 proto.toString = function() {
3920 var el = this.getEl();
3921 var id = el.id || el.tagName;
3922 return ("Motion " + id);
3925 proto.patterns.points = /^points$/i;
3927 proto.setAttribute = function(attr, val, unit) {
3928 if (this.patterns.points.test(attr)) {
3929 unit = unit || 'px';
3930 superclass.setAttribute.call(this, 'left', val[0], unit);
3931 superclass.setAttribute.call(this, 'top', val[1], unit);
3933 superclass.setAttribute.call(this, attr, val, unit);
3937 proto.getAttribute = function(attr) {
3938 if (this.patterns.points.test(attr)) {
3940 superclass.getAttribute.call(this, 'left'),
3941 superclass.getAttribute.call(this, 'top')
3944 val = superclass.getAttribute.call(this, attr);
3950 proto.doMethod = function(attr, start, end) {
3953 if (this.patterns.points.test(attr)) {
3954 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3955 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3957 val = superclass.doMethod.call(this, attr, start, end);
3962 proto.setRuntimeAttribute = function(attr) {
3963 if (this.patterns.points.test(attr)) {
3964 var el = this.getEl();
3965 var attributes = this.attributes;
3967 var control = attributes['points']['control'] || [];
3971 if (control.length > 0 && !(control[0] instanceof Array)) {
3972 control = [control];
3975 for (i = 0,len = control.length; i < len; ++i) {
3976 tmp[i] = control[i];
3981 Roo.fly(el).position();
3983 if (isset(attributes['points']['from'])) {
3984 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3987 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3990 start = this.getAttribute('points');
3993 if (isset(attributes['points']['to'])) {
3994 end = translateValues.call(this, attributes['points']['to'], start);
3996 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3997 for (i = 0,len = control.length; i < len; ++i) {
3998 control[i] = translateValues.call(this, control[i], start);
4002 } else if (isset(attributes['points']['by'])) {
4003 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
4005 for (i = 0,len = control.length; i < len; ++i) {
4006 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
4010 this.runtimeAttributes[attr] = [start];
4012 if (control.length > 0) {
4013 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4016 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4019 superclass.setRuntimeAttribute.call(this, attr);
4023 var translateValues = function(val, start) {
4024 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4025 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4030 var isset = function(prop) {
4031 return (typeof prop !== 'undefined');
4035 * Portions of this file are based on pieces of Yahoo User Interface Library
4036 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4037 * YUI licensed under the BSD License:
4038 * http://developer.yahoo.net/yui/license.txt
4039 * <script type="text/javascript">
4043 Roo.lib.Scroll = function(el, attributes, duration, method) {
4045 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4049 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4053 var superclass = Y.Scroll.superclass;
4054 var proto = Y.Scroll.prototype;
4056 proto.toString = function() {
4057 var el = this.getEl();
4058 var id = el.id || el.tagName;
4059 return ("Scroll " + id);
4062 proto.doMethod = function(attr, start, end) {
4065 if (attr == 'scroll') {
4067 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4068 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4072 val = superclass.doMethod.call(this, attr, start, end);
4077 proto.getAttribute = function(attr) {
4079 var el = this.getEl();
4081 if (attr == 'scroll') {
4082 val = [ el.scrollLeft, el.scrollTop ];
4084 val = superclass.getAttribute.call(this, attr);
4090 proto.setAttribute = function(attr, val, unit) {
4091 var el = this.getEl();
4093 if (attr == 'scroll') {
4094 el.scrollLeft = val[0];
4095 el.scrollTop = val[1];
4097 superclass.setAttribute.call(this, attr, val, unit);
4103 * Ext JS Library 1.1.1
4104 * Copyright(c) 2006-2007, Ext JS, LLC.
4106 * Originally Released Under LGPL - original licence link has changed is not relivant.
4109 * <script type="text/javascript">
4113 // nasty IE9 hack - what a pile of crap that is..
4115 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4116 Range.prototype.createContextualFragment = function (html) {
4117 var doc = window.document;
4118 var container = doc.createElement("div");
4119 container.innerHTML = html;
4120 var frag = doc.createDocumentFragment(), n;
4121 while ((n = container.firstChild)) {
4122 frag.appendChild(n);
4129 * @class Roo.DomHelper
4130 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4131 * 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>.
4134 Roo.DomHelper = function(){
4135 var tempTableEl = null;
4136 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4137 var tableRe = /^table|tbody|tr|td$/i;
4139 // build as innerHTML where available
4141 var createHtml = function(o){
4142 if(typeof o == 'string'){
4151 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4152 if(attr == "style"){
4154 if(typeof s == "function"){
4157 if(typeof s == "string"){
4158 b += ' style="' + s + '"';
4159 }else if(typeof s == "object"){
4162 if(typeof s[key] != "function"){
4163 b += key + ":" + s[key] + ";";
4170 b += ' class="' + o["cls"] + '"';
4171 }else if(attr == "htmlFor"){
4172 b += ' for="' + o["htmlFor"] + '"';
4174 b += " " + attr + '="' + o[attr] + '"';
4178 if(emptyTags.test(o.tag)){
4182 var cn = o.children || o.cn;
4184 //http://bugs.kde.org/show_bug.cgi?id=71506
4185 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4186 for(var i = 0, len = cn.length; i < len; i++) {
4187 b += createHtml(cn[i], b);
4190 b += createHtml(cn, b);
4196 b += "</" + o.tag + ">";
4203 var createDom = function(o, parentNode){
4205 // defininition craeted..
4207 if (o.ns && o.ns != 'html') {
4209 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4210 xmlns[o.ns] = o.xmlns;
4213 if (typeof(xmlns[o.ns]) == 'undefined') {
4214 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4220 if (typeof(o) == 'string') {
4221 return parentNode.appendChild(document.createTextNode(o));
4223 o.tag = o.tag || div;
4224 if (o.ns && Roo.isIE) {
4226 o.tag = o.ns + ':' + o.tag;
4229 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4230 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4233 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4234 attr == "style" || typeof o[attr] == "function") continue;
4236 if(attr=="cls" && Roo.isIE){
4237 el.className = o["cls"];
4239 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4240 else el[attr] = o[attr];
4243 Roo.DomHelper.applyStyles(el, o.style);
4244 var cn = o.children || o.cn;
4246 //http://bugs.kde.org/show_bug.cgi?id=71506
4247 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4248 for(var i = 0, len = cn.length; i < len; i++) {
4249 createDom(cn[i], el);
4256 el.innerHTML = o.html;
4259 parentNode.appendChild(el);
4264 var ieTable = function(depth, s, h, e){
4265 tempTableEl.innerHTML = [s, h, e].join('');
4266 var i = -1, el = tempTableEl;
4273 // kill repeat to save bytes
4277 tbe = '</tbody>'+te,
4283 * Nasty code for IE's broken table implementation
4285 var insertIntoTable = function(tag, where, el, html){
4287 tempTableEl = document.createElement('div');
4292 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4295 if(where == 'beforebegin'){
4299 before = el.nextSibling;
4302 node = ieTable(4, trs, html, tre);
4304 else if(tag == 'tr'){
4305 if(where == 'beforebegin'){
4308 node = ieTable(3, tbs, html, tbe);
4309 } else if(where == 'afterend'){
4310 before = el.nextSibling;
4312 node = ieTable(3, tbs, html, tbe);
4313 } else{ // INTO a TR
4314 if(where == 'afterbegin'){
4315 before = el.firstChild;
4317 node = ieTable(4, trs, html, tre);
4319 } else if(tag == 'tbody'){
4320 if(where == 'beforebegin'){
4323 node = ieTable(2, ts, html, te);
4324 } else if(where == 'afterend'){
4325 before = el.nextSibling;
4327 node = ieTable(2, ts, html, te);
4329 if(where == 'afterbegin'){
4330 before = el.firstChild;
4332 node = ieTable(3, tbs, html, tbe);
4335 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4338 if(where == 'afterbegin'){
4339 before = el.firstChild;
4341 node = ieTable(2, ts, html, te);
4343 el.insertBefore(node, before);
4348 /** True to force the use of DOM instead of html fragments @type Boolean */
4352 * Returns the markup for the passed Element(s) config
4353 * @param {Object} o The Dom object spec (and children)
4356 markup : function(o){
4357 return createHtml(o);
4361 * Applies a style specification to an element
4362 * @param {String/HTMLElement} el The element to apply styles to
4363 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4364 * a function which returns such a specification.
4366 applyStyles : function(el, styles){
4369 if(typeof styles == "string"){
4370 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4372 while ((matches = re.exec(styles)) != null){
4373 el.setStyle(matches[1], matches[2]);
4375 }else if (typeof styles == "object"){
4376 for (var style in styles){
4377 el.setStyle(style, styles[style]);
4379 }else if (typeof styles == "function"){
4380 Roo.DomHelper.applyStyles(el, styles.call());
4386 * Inserts an HTML fragment into the Dom
4387 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4388 * @param {HTMLElement} el The context element
4389 * @param {String} html The HTML fragmenet
4390 * @return {HTMLElement} The new node
4392 insertHtml : function(where, el, html){
4393 where = where.toLowerCase();
4394 if(el.insertAdjacentHTML){
4395 if(tableRe.test(el.tagName)){
4397 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4403 el.insertAdjacentHTML('BeforeBegin', html);
4404 return el.previousSibling;
4406 el.insertAdjacentHTML('AfterBegin', html);
4407 return el.firstChild;
4409 el.insertAdjacentHTML('BeforeEnd', html);
4410 return el.lastChild;
4412 el.insertAdjacentHTML('AfterEnd', html);
4413 return el.nextSibling;
4415 throw 'Illegal insertion point -> "' + where + '"';
4417 var range = el.ownerDocument.createRange();
4421 range.setStartBefore(el);
4422 frag = range.createContextualFragment(html);
4423 el.parentNode.insertBefore(frag, el);
4424 return el.previousSibling;
4427 range.setStartBefore(el.firstChild);
4428 frag = range.createContextualFragment(html);
4429 el.insertBefore(frag, el.firstChild);
4430 return el.firstChild;
4432 el.innerHTML = html;
4433 return el.firstChild;
4437 range.setStartAfter(el.lastChild);
4438 frag = range.createContextualFragment(html);
4439 el.appendChild(frag);
4440 return el.lastChild;
4442 el.innerHTML = html;
4443 return el.lastChild;
4446 range.setStartAfter(el);
4447 frag = range.createContextualFragment(html);
4448 el.parentNode.insertBefore(frag, el.nextSibling);
4449 return el.nextSibling;
4451 throw 'Illegal insertion point -> "' + where + '"';
4455 * Creates new Dom element(s) and inserts them before el
4456 * @param {String/HTMLElement/Element} el The context element
4457 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4458 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4459 * @return {HTMLElement/Roo.Element} The new node
4461 insertBefore : function(el, o, returnElement){
4462 return this.doInsert(el, o, returnElement, "beforeBegin");
4466 * Creates new Dom element(s) and inserts them after el
4467 * @param {String/HTMLElement/Element} el The context element
4468 * @param {Object} o The Dom object spec (and children)
4469 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4470 * @return {HTMLElement/Roo.Element} The new node
4472 insertAfter : function(el, o, returnElement){
4473 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4477 * Creates new Dom element(s) and inserts them as the first child of el
4478 * @param {String/HTMLElement/Element} el The context element
4479 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4480 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4481 * @return {HTMLElement/Roo.Element} The new node
4483 insertFirst : function(el, o, returnElement){
4484 return this.doInsert(el, o, returnElement, "afterBegin");
4488 doInsert : function(el, o, returnElement, pos, sibling){
4489 el = Roo.getDom(el);
4491 if(this.useDom || o.ns){
4492 newNode = createDom(o, null);
4493 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4495 var html = createHtml(o);
4496 newNode = this.insertHtml(pos, el, html);
4498 return returnElement ? Roo.get(newNode, true) : newNode;
4502 * Creates new Dom element(s) and appends them to el
4503 * @param {String/HTMLElement/Element} el The context element
4504 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4505 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4506 * @return {HTMLElement/Roo.Element} The new node
4508 append : function(el, o, returnElement){
4509 el = Roo.getDom(el);
4511 if(this.useDom || o.ns){
4512 newNode = createDom(o, null);
4513 el.appendChild(newNode);
4515 var html = createHtml(o);
4516 newNode = this.insertHtml("beforeEnd", el, html);
4518 return returnElement ? Roo.get(newNode, true) : newNode;
4522 * Creates new Dom element(s) and overwrites the contents of el with them
4523 * @param {String/HTMLElement/Element} el The context element
4524 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4525 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4526 * @return {HTMLElement/Roo.Element} The new node
4528 overwrite : function(el, o, returnElement){
4529 el = Roo.getDom(el);
4532 while (el.childNodes.length) {
4533 el.removeChild(el.firstChild);
4537 el.innerHTML = createHtml(o);
4540 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4544 * Creates a new Roo.DomHelper.Template from the Dom object spec
4545 * @param {Object} o The Dom object spec (and children)
4546 * @return {Roo.DomHelper.Template} The new template
4548 createTemplate : function(o){
4549 var html = createHtml(o);
4550 return new Roo.Template(html);
4556 * Ext JS Library 1.1.1
4557 * Copyright(c) 2006-2007, Ext JS, LLC.
4559 * Originally Released Under LGPL - original licence link has changed is not relivant.
4562 * <script type="text/javascript">
4566 * @class Roo.Template
4567 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4568 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4571 var t = new Roo.Template({
4572 html : '<div name="{id}">' +
4573 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4575 myformat: function (value, allValues) {
4576 return 'XX' + value;
4579 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4581 * For more information see this blog post with examples:
4582 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4583 - Create Elements using DOM, HTML fragments and Templates</a>.
4585 * @param {Object} cfg - Configuration object.
4587 Roo.Template = function(cfg){
4589 if(cfg instanceof Array){
4591 }else if(arguments.length > 1){
4592 cfg = Array.prototype.join.call(arguments, "");
4596 if (typeof(cfg) == 'object') {
4607 Roo.Template.prototype = {
4610 * @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..
4611 * it should be fixed so that template is observable...
4615 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4619 * Returns an HTML fragment of this template with the specified values applied.
4620 * @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'})
4621 * @return {String} The HTML fragment
4623 applyTemplate : function(values){
4627 return this.compiled(values);
4629 var useF = this.disableFormats !== true;
4630 var fm = Roo.util.Format, tpl = this;
4631 var fn = function(m, name, format, args){
4633 if(format.substr(0, 5) == "this."){
4634 return tpl.call(format.substr(5), values[name], values);
4637 // quoted values are required for strings in compiled templates,
4638 // but for non compiled we need to strip them
4639 // quoted reversed for jsmin
4640 var re = /^\s*['"](.*)["']\s*$/;
4641 args = args.split(',');
4642 for(var i = 0, len = args.length; i < len; i++){
4643 args[i] = args[i].replace(re, "$1");
4645 args = [values[name]].concat(args);
4647 args = [values[name]];
4649 return fm[format].apply(fm, args);
4652 return values[name] !== undefined ? values[name] : "";
4655 return this.html.replace(this.re, fn);
4673 this.loading = true;
4674 this.compiled = false;
4676 var cx = new Roo.data.Connection();
4680 success : function (response) {
4682 _t.html = response.responseText;
4686 failure : function(response) {
4687 Roo.log("Template failed to load from " + _t.url);
4694 * Sets the HTML used as the template and optionally compiles it.
4695 * @param {String} html
4696 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4697 * @return {Roo.Template} this
4699 set : function(html, compile){
4701 this.compiled = null;
4709 * True to disable format functions (defaults to false)
4712 disableFormats : false,
4715 * The regular expression used to match template variables
4719 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4722 * Compiles the template into an internal function, eliminating the RegEx overhead.
4723 * @return {Roo.Template} this
4725 compile : function(){
4726 var fm = Roo.util.Format;
4727 var useF = this.disableFormats !== true;
4728 var sep = Roo.isGecko ? "+" : ",";
4729 var fn = function(m, name, format, args){
4731 args = args ? ',' + args : "";
4732 if(format.substr(0, 5) != "this."){
4733 format = "fm." + format + '(';
4735 format = 'this.call("'+ format.substr(5) + '", ';
4739 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4741 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4744 // branched to use + in gecko and [].join() in others
4746 body = "this.compiled = function(values){ return '" +
4747 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4750 body = ["this.compiled = function(values){ return ['"];
4751 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4752 body.push("'].join('');};");
4753 body = body.join('');
4763 // private function used to call members
4764 call : function(fnName, value, allValues){
4765 return this[fnName](value, allValues);
4769 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4770 * @param {String/HTMLElement/Roo.Element} el The context element
4771 * @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'})
4772 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4773 * @return {HTMLElement/Roo.Element} The new node or Element
4775 insertFirst: function(el, values, returnElement){
4776 return this.doInsert('afterBegin', el, values, returnElement);
4780 * Applies the supplied values to the template and inserts the new node(s) before el.
4781 * @param {String/HTMLElement/Roo.Element} el The context element
4782 * @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'})
4783 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4784 * @return {HTMLElement/Roo.Element} The new node or Element
4786 insertBefore: function(el, values, returnElement){
4787 return this.doInsert('beforeBegin', el, values, returnElement);
4791 * Applies the supplied values to the template and inserts the new node(s) after el.
4792 * @param {String/HTMLElement/Roo.Element} el The context element
4793 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4794 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4795 * @return {HTMLElement/Roo.Element} The new node or Element
4797 insertAfter : function(el, values, returnElement){
4798 return this.doInsert('afterEnd', el, values, returnElement);
4802 * Applies the supplied values to the template and appends the new node(s) to el.
4803 * @param {String/HTMLElement/Roo.Element} el The context element
4804 * @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'})
4805 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4806 * @return {HTMLElement/Roo.Element} The new node or Element
4808 append : function(el, values, returnElement){
4809 return this.doInsert('beforeEnd', el, values, returnElement);
4812 doInsert : function(where, el, values, returnEl){
4813 el = Roo.getDom(el);
4814 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4815 return returnEl ? Roo.get(newNode, true) : newNode;
4819 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4820 * @param {String/HTMLElement/Roo.Element} el The context element
4821 * @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'})
4822 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4823 * @return {HTMLElement/Roo.Element} The new node or Element
4825 overwrite : function(el, values, returnElement){
4826 el = Roo.getDom(el);
4827 el.innerHTML = this.applyTemplate(values);
4828 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4832 * Alias for {@link #applyTemplate}
4835 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4838 Roo.DomHelper.Template = Roo.Template;
4841 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4842 * @param {String/HTMLElement} el A DOM element or its id
4843 * @returns {Roo.Template} The created template
4846 Roo.Template.from = function(el){
4847 el = Roo.getDom(el);
4848 return new Roo.Template(el.value || el.innerHTML);
4851 * Ext JS Library 1.1.1
4852 * Copyright(c) 2006-2007, Ext JS, LLC.
4854 * Originally Released Under LGPL - original licence link has changed is not relivant.
4857 * <script type="text/javascript">
4862 * This is code is also distributed under MIT license for use
4863 * with jQuery and prototype JavaScript libraries.
4866 * @class Roo.DomQuery
4867 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).
4869 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>
4872 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.
4874 <h4>Element Selectors:</h4>
4876 <li> <b>*</b> any element</li>
4877 <li> <b>E</b> an element with the tag E</li>
4878 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4879 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4880 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4881 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4883 <h4>Attribute Selectors:</h4>
4884 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4886 <li> <b>E[foo]</b> has an attribute "foo"</li>
4887 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4888 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4889 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4890 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4891 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4892 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4894 <h4>Pseudo Classes:</h4>
4896 <li> <b>E:first-child</b> E is the first child of its parent</li>
4897 <li> <b>E:last-child</b> E is the last child of its parent</li>
4898 <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>
4899 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4900 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4901 <li> <b>E:only-child</b> E is the only child of its parent</li>
4902 <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>
4903 <li> <b>E:first</b> the first E in the resultset</li>
4904 <li> <b>E:last</b> the last E in the resultset</li>
4905 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4906 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4907 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4908 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4909 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4910 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4911 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4912 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4913 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4915 <h4>CSS Value Selectors:</h4>
4917 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4918 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4919 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4920 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4921 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4922 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4926 Roo.DomQuery = function(){
4927 var cache = {}, simpleCache = {}, valueCache = {};
4928 var nonSpace = /\S/;
4929 var trimRe = /^\s+|\s+$/g;
4930 var tplRe = /\{(\d+)\}/g;
4931 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4932 var tagTokenRe = /^(#)?([\w-\*]+)/;
4933 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4935 function child(p, index){
4937 var n = p.firstChild;
4939 if(n.nodeType == 1){
4950 while((n = n.nextSibling) && n.nodeType != 1);
4955 while((n = n.previousSibling) && n.nodeType != 1);
4959 function children(d){
4960 var n = d.firstChild, ni = -1;
4962 var nx = n.nextSibling;
4963 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4973 function byClassName(c, a, v){
4977 var r = [], ri = -1, cn;
4978 for(var i = 0, ci; ci = c[i]; i++){
4979 if((' '+ci.className+' ').indexOf(v) != -1){
4986 function attrValue(n, attr){
4987 if(!n.tagName && typeof n.length != "undefined"){
4996 if(attr == "class" || attr == "className"){
4999 return n.getAttribute(attr) || n[attr];
5003 function getNodes(ns, mode, tagName){
5004 var result = [], ri = -1, cs;
5008 tagName = tagName || "*";
5009 if(typeof ns.getElementsByTagName != "undefined"){
5013 for(var i = 0, ni; ni = ns[i]; i++){
5014 cs = ni.getElementsByTagName(tagName);
5015 for(var j = 0, ci; ci = cs[j]; j++){
5019 }else if(mode == "/" || mode == ">"){
5020 var utag = tagName.toUpperCase();
5021 for(var i = 0, ni, cn; ni = ns[i]; i++){
5022 cn = ni.children || ni.childNodes;
5023 for(var j = 0, cj; cj = cn[j]; j++){
5024 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5029 }else if(mode == "+"){
5030 var utag = tagName.toUpperCase();
5031 for(var i = 0, n; n = ns[i]; i++){
5032 while((n = n.nextSibling) && n.nodeType != 1);
5033 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5037 }else if(mode == "~"){
5038 for(var i = 0, n; n = ns[i]; i++){
5039 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5048 function concat(a, b){
5052 for(var i = 0, l = b.length; i < l; i++){
5058 function byTag(cs, tagName){
5059 if(cs.tagName || cs == document){
5065 var r = [], ri = -1;
5066 tagName = tagName.toLowerCase();
5067 for(var i = 0, ci; ci = cs[i]; i++){
5068 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5075 function byId(cs, attr, id){
5076 if(cs.tagName || cs == document){
5082 var r = [], ri = -1;
5083 for(var i = 0,ci; ci = cs[i]; i++){
5084 if(ci && ci.id == id){
5092 function byAttribute(cs, attr, value, op, custom){
5093 var r = [], ri = -1, st = custom=="{";
5094 var f = Roo.DomQuery.operators[op];
5095 for(var i = 0, ci; ci = cs[i]; i++){
5098 a = Roo.DomQuery.getStyle(ci, attr);
5100 else if(attr == "class" || attr == "className"){
5102 }else if(attr == "for"){
5104 }else if(attr == "href"){
5105 a = ci.getAttribute("href", 2);
5107 a = ci.getAttribute(attr);
5109 if((f && f(a, value)) || (!f && a)){
5116 function byPseudo(cs, name, value){
5117 return Roo.DomQuery.pseudos[name](cs, value);
5120 // This is for IE MSXML which does not support expandos.
5121 // IE runs the same speed using setAttribute, however FF slows way down
5122 // and Safari completely fails so they need to continue to use expandos.
5123 var isIE = window.ActiveXObject ? true : false;
5125 // this eval is stop the compressor from
5126 // renaming the variable to something shorter
5128 /** eval:var:batch */
5133 function nodupIEXml(cs){
5135 cs[0].setAttribute("_nodup", d);
5137 for(var i = 1, len = cs.length; i < len; i++){
5139 if(!c.getAttribute("_nodup") != d){
5140 c.setAttribute("_nodup", d);
5144 for(var i = 0, len = cs.length; i < len; i++){
5145 cs[i].removeAttribute("_nodup");
5154 var len = cs.length, c, i, r = cs, cj, ri = -1;
5155 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5158 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5159 return nodupIEXml(cs);
5163 for(i = 1; c = cs[i]; i++){
5168 for(var j = 0; j < i; j++){
5171 for(j = i+1; cj = cs[j]; j++){
5183 function quickDiffIEXml(c1, c2){
5185 for(var i = 0, len = c1.length; i < len; i++){
5186 c1[i].setAttribute("_qdiff", d);
5189 for(var i = 0, len = c2.length; i < len; i++){
5190 if(c2[i].getAttribute("_qdiff") != d){
5191 r[r.length] = c2[i];
5194 for(var i = 0, len = c1.length; i < len; i++){
5195 c1[i].removeAttribute("_qdiff");
5200 function quickDiff(c1, c2){
5201 var len1 = c1.length;
5205 if(isIE && c1[0].selectSingleNode){
5206 return quickDiffIEXml(c1, c2);
5209 for(var i = 0; i < len1; i++){
5213 for(var i = 0, len = c2.length; i < len; i++){
5214 if(c2[i]._qdiff != d){
5215 r[r.length] = c2[i];
5221 function quickId(ns, mode, root, id){
5223 var d = root.ownerDocument || root;
5224 return d.getElementById(id);
5226 ns = getNodes(ns, mode, "*");
5227 return byId(ns, null, id);
5231 getStyle : function(el, name){
5232 return Roo.fly(el).getStyle(name);
5235 * Compiles a selector/xpath query into a reusable function. The returned function
5236 * takes one parameter "root" (optional), which is the context node from where the query should start.
5237 * @param {String} selector The selector/xpath query
5238 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5239 * @return {Function}
5241 compile : function(path, type){
5242 type = type || "select";
5244 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5245 var q = path, mode, lq;
5246 var tk = Roo.DomQuery.matchers;
5247 var tklen = tk.length;
5250 // accept leading mode switch
5251 var lmode = q.match(modeRe);
5252 if(lmode && lmode[1]){
5253 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5254 q = q.replace(lmode[1], "");
5256 // strip leading slashes
5257 while(path.substr(0, 1)=="/"){
5258 path = path.substr(1);
5261 while(q && lq != q){
5263 var tm = q.match(tagTokenRe);
5264 if(type == "select"){
5267 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5269 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5271 q = q.replace(tm[0], "");
5272 }else if(q.substr(0, 1) != '@'){
5273 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5278 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5280 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5282 q = q.replace(tm[0], "");
5285 while(!(mm = q.match(modeRe))){
5286 var matched = false;
5287 for(var j = 0; j < tklen; j++){
5289 var m = q.match(t.re);
5291 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5294 q = q.replace(m[0], "");
5299 // prevent infinite loop on bad selector
5301 throw 'Error parsing selector, parsing failed at "' + q + '"';
5305 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5306 q = q.replace(mm[1], "");
5309 fn[fn.length] = "return nodup(n);\n}";
5312 * list of variables that need from compression as they are used by eval.
5322 * eval:var:byClassName
5324 * eval:var:byAttribute
5325 * eval:var:attrValue
5333 * Selects a group of elements.
5334 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5335 * @param {Node} root (optional) The start of the query (defaults to document).
5338 select : function(path, root, type){
5339 if(!root || root == document){
5342 if(typeof root == "string"){
5343 root = document.getElementById(root);
5345 var paths = path.split(",");
5347 for(var i = 0, len = paths.length; i < len; i++){
5348 var p = paths[i].replace(trimRe, "");
5350 cache[p] = Roo.DomQuery.compile(p);
5352 throw p + " is not a valid selector";
5355 var result = cache[p](root);
5356 if(result && result != document){
5357 results = results.concat(result);
5360 if(paths.length > 1){
5361 return nodup(results);
5367 * Selects a single element.
5368 * @param {String} selector The selector/xpath query
5369 * @param {Node} root (optional) The start of the query (defaults to document).
5372 selectNode : function(path, root){
5373 return Roo.DomQuery.select(path, root)[0];
5377 * Selects the value of a node, optionally replacing null with the defaultValue.
5378 * @param {String} selector The selector/xpath query
5379 * @param {Node} root (optional) The start of the query (defaults to document).
5380 * @param {String} defaultValue
5382 selectValue : function(path, root, defaultValue){
5383 path = path.replace(trimRe, "");
5384 if(!valueCache[path]){
5385 valueCache[path] = Roo.DomQuery.compile(path, "select");
5387 var n = valueCache[path](root);
5388 n = n[0] ? n[0] : n;
5389 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5390 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5394 * Selects the value of a node, parsing integers and floats.
5395 * @param {String} selector The selector/xpath query
5396 * @param {Node} root (optional) The start of the query (defaults to document).
5397 * @param {Number} defaultValue
5400 selectNumber : function(path, root, defaultValue){
5401 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5402 return parseFloat(v);
5406 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5407 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5408 * @param {String} selector The simple selector to test
5411 is : function(el, ss){
5412 if(typeof el == "string"){
5413 el = document.getElementById(el);
5415 var isArray = (el instanceof Array);
5416 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5417 return isArray ? (result.length == el.length) : (result.length > 0);
5421 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5422 * @param {Array} el An array of elements to filter
5423 * @param {String} selector The simple selector to test
5424 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5425 * the selector instead of the ones that match
5428 filter : function(els, ss, nonMatches){
5429 ss = ss.replace(trimRe, "");
5430 if(!simpleCache[ss]){
5431 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5433 var result = simpleCache[ss](els);
5434 return nonMatches ? quickDiff(result, els) : result;
5438 * Collection of matching regular expressions and code snippets.
5442 select: 'n = byClassName(n, null, " {1} ");'
5444 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5445 select: 'n = byPseudo(n, "{1}", "{2}");'
5447 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5448 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5451 select: 'n = byId(n, null, "{1}");'
5454 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5459 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5460 * 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, > <.
5463 "=" : function(a, v){
5466 "!=" : function(a, v){
5469 "^=" : function(a, v){
5470 return a && a.substr(0, v.length) == v;
5472 "$=" : function(a, v){
5473 return a && a.substr(a.length-v.length) == v;
5475 "*=" : function(a, v){
5476 return a && a.indexOf(v) !== -1;
5478 "%=" : function(a, v){
5479 return (a % v) == 0;
5481 "|=" : function(a, v){
5482 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5484 "~=" : function(a, v){
5485 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5490 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5491 * and the argument (if any) supplied in the selector.
5494 "first-child" : function(c){
5495 var r = [], ri = -1, n;
5496 for(var i = 0, ci; ci = n = c[i]; i++){
5497 while((n = n.previousSibling) && n.nodeType != 1);
5505 "last-child" : function(c){
5506 var r = [], ri = -1, n;
5507 for(var i = 0, ci; ci = n = c[i]; i++){
5508 while((n = n.nextSibling) && n.nodeType != 1);
5516 "nth-child" : function(c, a) {
5517 var r = [], ri = -1;
5518 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5519 var f = (m[1] || 1) - 0, l = m[2] - 0;
5520 for(var i = 0, n; n = c[i]; i++){
5521 var pn = n.parentNode;
5522 if (batch != pn._batch) {
5524 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5525 if(cn.nodeType == 1){
5532 if (l == 0 || n.nodeIndex == l){
5535 } else if ((n.nodeIndex + l) % f == 0){
5543 "only-child" : function(c){
5544 var r = [], ri = -1;;
5545 for(var i = 0, ci; ci = c[i]; i++){
5546 if(!prev(ci) && !next(ci)){
5553 "empty" : function(c){
5554 var r = [], ri = -1;
5555 for(var i = 0, ci; ci = c[i]; i++){
5556 var cns = ci.childNodes, j = 0, cn, empty = true;
5559 if(cn.nodeType == 1 || cn.nodeType == 3){
5571 "contains" : function(c, v){
5572 var r = [], ri = -1;
5573 for(var i = 0, ci; ci = c[i]; i++){
5574 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5581 "nodeValue" : function(c, v){
5582 var r = [], ri = -1;
5583 for(var i = 0, ci; ci = c[i]; i++){
5584 if(ci.firstChild && ci.firstChild.nodeValue == v){
5591 "checked" : function(c){
5592 var r = [], ri = -1;
5593 for(var i = 0, ci; ci = c[i]; i++){
5594 if(ci.checked == true){
5601 "not" : function(c, ss){
5602 return Roo.DomQuery.filter(c, ss, true);
5605 "odd" : function(c){
5606 return this["nth-child"](c, "odd");
5609 "even" : function(c){
5610 return this["nth-child"](c, "even");
5613 "nth" : function(c, a){
5614 return c[a-1] || [];
5617 "first" : function(c){
5621 "last" : function(c){
5622 return c[c.length-1] || [];
5625 "has" : function(c, ss){
5626 var s = Roo.DomQuery.select;
5627 var r = [], ri = -1;
5628 for(var i = 0, ci; ci = c[i]; i++){
5629 if(s(ss, ci).length > 0){
5636 "next" : function(c, ss){
5637 var is = Roo.DomQuery.is;
5638 var r = [], ri = -1;
5639 for(var i = 0, ci; ci = c[i]; i++){
5648 "prev" : function(c, ss){
5649 var is = Roo.DomQuery.is;
5650 var r = [], ri = -1;
5651 for(var i = 0, ci; ci = c[i]; i++){
5664 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5665 * @param {String} path The selector/xpath query
5666 * @param {Node} root (optional) The start of the query (defaults to document).
5671 Roo.query = Roo.DomQuery.select;
5674 * Ext JS Library 1.1.1
5675 * Copyright(c) 2006-2007, Ext JS, LLC.
5677 * Originally Released Under LGPL - original licence link has changed is not relivant.
5680 * <script type="text/javascript">
5684 * @class Roo.util.Observable
5685 * Base class that provides a common interface for publishing events. Subclasses are expected to
5686 * to have a property "events" with all the events defined.<br>
5689 Employee = function(name){
5696 Roo.extend(Employee, Roo.util.Observable);
5698 * @param {Object} config properties to use (incuding events / listeners)
5701 Roo.util.Observable = function(cfg){
5704 this.addEvents(cfg.events || {});
5706 delete cfg.events; // make sure
5709 Roo.apply(this, cfg);
5712 this.on(this.listeners);
5713 delete this.listeners;
5716 Roo.util.Observable.prototype = {
5718 * @cfg {Object} listeners list of events and functions to call for this object,
5722 'click' : function(e) {
5732 * Fires the specified event with the passed parameters (minus the event name).
5733 * @param {String} eventName
5734 * @param {Object...} args Variable number of parameters are passed to handlers
5735 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5737 fireEvent : function(){
5738 var ce = this.events[arguments[0].toLowerCase()];
5739 if(typeof ce == "object"){
5740 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5747 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5750 * Appends an event handler to this component
5751 * @param {String} eventName The type of event to listen for
5752 * @param {Function} handler The method the event invokes
5753 * @param {Object} scope (optional) The scope in which to execute the handler
5754 * function. The handler function's "this" context.
5755 * @param {Object} options (optional) An object containing handler configuration
5756 * properties. This may contain any of the following properties:<ul>
5757 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5758 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5759 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5760 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5761 * by the specified number of milliseconds. If the event fires again within that time, the original
5762 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5765 * <b>Combining Options</b><br>
5766 * Using the options argument, it is possible to combine different types of listeners:<br>
5768 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5770 el.on('click', this.onClick, this, {
5777 * <b>Attaching multiple handlers in 1 call</b><br>
5778 * The method also allows for a single argument to be passed which is a config object containing properties
5779 * which specify multiple handlers.
5788 fn: this.onMouseOver,
5792 fn: this.onMouseOut,
5798 * Or a shorthand syntax which passes the same scope object to all handlers:
5801 'click': this.onClick,
5802 'mouseover': this.onMouseOver,
5803 'mouseout': this.onMouseOut,
5808 addListener : function(eventName, fn, scope, o){
5809 if(typeof eventName == "object"){
5812 if(this.filterOptRe.test(e)){
5815 if(typeof o[e] == "function"){
5817 this.addListener(e, o[e], o.scope, o);
5819 // individual options
5820 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5825 o = (!o || typeof o == "boolean") ? {} : o;
5826 eventName = eventName.toLowerCase();
5827 var ce = this.events[eventName] || true;
5828 if(typeof ce == "boolean"){
5829 ce = new Roo.util.Event(this, eventName);
5830 this.events[eventName] = ce;
5832 ce.addListener(fn, scope, o);
5836 * Removes a listener
5837 * @param {String} eventName The type of event to listen for
5838 * @param {Function} handler The handler to remove
5839 * @param {Object} scope (optional) The scope (this object) for the handler
5841 removeListener : function(eventName, fn, scope){
5842 var ce = this.events[eventName.toLowerCase()];
5843 if(typeof ce == "object"){
5844 ce.removeListener(fn, scope);
5849 * Removes all listeners for this object
5851 purgeListeners : function(){
5852 for(var evt in this.events){
5853 if(typeof this.events[evt] == "object"){
5854 this.events[evt].clearListeners();
5859 relayEvents : function(o, events){
5860 var createHandler = function(ename){
5862 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5865 for(var i = 0, len = events.length; i < len; i++){
5866 var ename = events[i];
5867 if(!this.events[ename]){ this.events[ename] = true; };
5868 o.on(ename, createHandler(ename), this);
5873 * Used to define events on this Observable
5874 * @param {Object} object The object with the events defined
5876 addEvents : function(o){
5880 Roo.applyIf(this.events, o);
5884 * Checks to see if this object has any listeners for a specified event
5885 * @param {String} eventName The name of the event to check for
5886 * @return {Boolean} True if the event is being listened for, else false
5888 hasListener : function(eventName){
5889 var e = this.events[eventName];
5890 return typeof e == "object" && e.listeners.length > 0;
5894 * Appends an event handler to this element (shorthand for addListener)
5895 * @param {String} eventName The type of event to listen for
5896 * @param {Function} handler The method the event invokes
5897 * @param {Object} scope (optional) The scope in which to execute the handler
5898 * function. The handler function's "this" context.
5899 * @param {Object} options (optional)
5902 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5904 * Removes a listener (shorthand for removeListener)
5905 * @param {String} eventName The type of event to listen for
5906 * @param {Function} handler The handler to remove
5907 * @param {Object} scope (optional) The scope (this object) for the handler
5910 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5913 * Starts capture on the specified Observable. All events will be passed
5914 * to the supplied function with the event name + standard signature of the event
5915 * <b>before</b> the event is fired. If the supplied function returns false,
5916 * the event will not fire.
5917 * @param {Observable} o The Observable to capture
5918 * @param {Function} fn The function to call
5919 * @param {Object} scope (optional) The scope (this object) for the fn
5922 Roo.util.Observable.capture = function(o, fn, scope){
5923 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5927 * Removes <b>all</b> added captures from the Observable.
5928 * @param {Observable} o The Observable to release
5931 Roo.util.Observable.releaseCapture = function(o){
5932 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5937 var createBuffered = function(h, o, scope){
5938 var task = new Roo.util.DelayedTask();
5940 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5944 var createSingle = function(h, e, fn, scope){
5946 e.removeListener(fn, scope);
5947 return h.apply(scope, arguments);
5951 var createDelayed = function(h, o, scope){
5953 var args = Array.prototype.slice.call(arguments, 0);
5954 setTimeout(function(){
5955 h.apply(scope, args);
5960 Roo.util.Event = function(obj, name){
5963 this.listeners = [];
5966 Roo.util.Event.prototype = {
5967 addListener : function(fn, scope, options){
5968 var o = options || {};
5969 scope = scope || this.obj;
5970 if(!this.isListening(fn, scope)){
5971 var l = {fn: fn, scope: scope, options: o};
5974 h = createDelayed(h, o, scope);
5977 h = createSingle(h, this, fn, scope);
5980 h = createBuffered(h, o, scope);
5983 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5984 this.listeners.push(l);
5986 this.listeners = this.listeners.slice(0);
5987 this.listeners.push(l);
5992 findListener : function(fn, scope){
5993 scope = scope || this.obj;
5994 var ls = this.listeners;
5995 for(var i = 0, len = ls.length; i < len; i++){
5997 if(l.fn == fn && l.scope == scope){
6004 isListening : function(fn, scope){
6005 return this.findListener(fn, scope) != -1;
6008 removeListener : function(fn, scope){
6010 if((index = this.findListener(fn, scope)) != -1){
6012 this.listeners.splice(index, 1);
6014 this.listeners = this.listeners.slice(0);
6015 this.listeners.splice(index, 1);
6022 clearListeners : function(){
6023 this.listeners = [];
6027 var ls = this.listeners, scope, len = ls.length;
6030 var args = Array.prototype.slice.call(arguments, 0);
6031 for(var i = 0; i < len; i++){
6033 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6034 this.firing = false;
6038 this.firing = false;
6045 * Ext JS Library 1.1.1
6046 * Copyright(c) 2006-2007, Ext JS, LLC.
6048 * Originally Released Under LGPL - original licence link has changed is not relivant.
6051 * <script type="text/javascript">
6055 * @class Roo.EventManager
6056 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6057 * several useful events directly.
6058 * See {@link Roo.EventObject} for more details on normalized event objects.
6061 Roo.EventManager = function(){
6062 var docReadyEvent, docReadyProcId, docReadyState = false;
6063 var resizeEvent, resizeTask, textEvent, textSize;
6064 var E = Roo.lib.Event;
6065 var D = Roo.lib.Dom;
6070 var fireDocReady = function(){
6072 docReadyState = true;
6075 clearInterval(docReadyProcId);
6077 if(Roo.isGecko || Roo.isOpera) {
6078 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6081 var defer = document.getElementById("ie-deferred-loader");
6083 defer.onreadystatechange = null;
6084 defer.parentNode.removeChild(defer);
6088 docReadyEvent.fire();
6089 docReadyEvent.clearListeners();
6094 var initDocReady = function(){
6095 docReadyEvent = new Roo.util.Event();
6096 if(Roo.isGecko || Roo.isOpera) {
6097 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6099 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6100 var defer = document.getElementById("ie-deferred-loader");
6101 defer.onreadystatechange = function(){
6102 if(this.readyState == "complete"){
6106 }else if(Roo.isSafari){
6107 docReadyProcId = setInterval(function(){
6108 var rs = document.readyState;
6109 if(rs == "complete") {
6114 // no matter what, make sure it fires on load
6115 E.on(window, "load", fireDocReady);
6118 var createBuffered = function(h, o){
6119 var task = new Roo.util.DelayedTask(h);
6121 // create new event object impl so new events don't wipe out properties
6122 e = new Roo.EventObjectImpl(e);
6123 task.delay(o.buffer, h, null, [e]);
6127 var createSingle = function(h, el, ename, fn){
6129 Roo.EventManager.removeListener(el, ename, fn);
6134 var createDelayed = function(h, o){
6136 // create new event object impl so new events don't wipe out properties
6137 e = new Roo.EventObjectImpl(e);
6138 setTimeout(function(){
6143 var transitionEndVal = false;
6145 var transitionEnd = function()
6147 if (transitionEndVal) {
6148 return transitionEndVal;
6150 var el = document.createElement('div');
6152 var transEndEventNames = {
6153 WebkitTransition : 'webkitTransitionEnd',
6154 MozTransition : 'transitionend',
6155 OTransition : 'oTransitionEnd otransitionend',
6156 transition : 'transitionend'
6159 for (var name in transEndEventNames) {
6160 if (el.style[name] !== undefined) {
6161 transitionEndVal = transEndEventNames[name];
6162 return transitionEndVal ;
6168 var listen = function(element, ename, opt, fn, scope){
6169 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6170 fn = fn || o.fn; scope = scope || o.scope;
6171 var el = Roo.getDom(element);
6175 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6178 if (ename == 'transitionend') {
6179 ename = transitionEnd();
6181 var h = function(e){
6182 e = Roo.EventObject.setEvent(e);
6185 t = e.getTarget(o.delegate, el);
6192 if(o.stopEvent === true){
6195 if(o.preventDefault === true){
6198 if(o.stopPropagation === true){
6199 e.stopPropagation();
6202 if(o.normalized === false){
6206 fn.call(scope || el, e, t, o);
6209 h = createDelayed(h, o);
6212 h = createSingle(h, el, ename, fn);
6215 h = createBuffered(h, o);
6217 fn._handlers = fn._handlers || [];
6220 fn._handlers.push([Roo.id(el), ename, h]);
6225 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6226 el.addEventListener("DOMMouseScroll", h, false);
6227 E.on(window, 'unload', function(){
6228 el.removeEventListener("DOMMouseScroll", h, false);
6231 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6232 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6237 var stopListening = function(el, ename, fn){
6238 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6240 for(var i = 0, len = hds.length; i < len; i++){
6242 if(h[0] == id && h[1] == ename){
6249 E.un(el, ename, hd);
6250 el = Roo.getDom(el);
6251 if(ename == "mousewheel" && el.addEventListener){
6252 el.removeEventListener("DOMMouseScroll", hd, false);
6254 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6255 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6259 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6266 * @scope Roo.EventManager
6271 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6272 * object with a Roo.EventObject
6273 * @param {Function} fn The method the event invokes
6274 * @param {Object} scope An object that becomes the scope of the handler
6275 * @param {boolean} override If true, the obj passed in becomes
6276 * the execution scope of the listener
6277 * @return {Function} The wrapped function
6280 wrap : function(fn, scope, override){
6282 Roo.EventObject.setEvent(e);
6283 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6288 * Appends an event handler to an element (shorthand for addListener)
6289 * @param {String/HTMLElement} element The html element or id to assign the
6290 * @param {String} eventName The type of event to listen for
6291 * @param {Function} handler The method the event invokes
6292 * @param {Object} scope (optional) The scope in which to execute the handler
6293 * function. The handler function's "this" context.
6294 * @param {Object} options (optional) An object containing handler configuration
6295 * properties. This may contain any of the following properties:<ul>
6296 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6297 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6298 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6299 * <li>preventDefault {Boolean} True to prevent the default action</li>
6300 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6301 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6302 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6303 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6304 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6305 * by the specified number of milliseconds. If the event fires again within that time, the original
6306 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6309 * <b>Combining Options</b><br>
6310 * Using the options argument, it is possible to combine different types of listeners:<br>
6312 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6314 el.on('click', this.onClick, this, {
6321 * <b>Attaching multiple handlers in 1 call</b><br>
6322 * The method also allows for a single argument to be passed which is a config object containing properties
6323 * which specify multiple handlers.
6333 fn: this.onMouseOver
6342 * Or a shorthand syntax:<br>
6345 'click' : this.onClick,
6346 'mouseover' : this.onMouseOver,
6347 'mouseout' : this.onMouseOut
6351 addListener : function(element, eventName, fn, scope, options){
6352 if(typeof eventName == "object"){
6358 if(typeof o[e] == "function"){
6360 listen(element, e, o, o[e], o.scope);
6362 // individual options
6363 listen(element, e, o[e]);
6368 return listen(element, eventName, options, fn, scope);
6372 * Removes an event handler
6374 * @param {String/HTMLElement} element The id or html element to remove the
6376 * @param {String} eventName The type of event
6377 * @param {Function} fn
6378 * @return {Boolean} True if a listener was actually removed
6380 removeListener : function(element, eventName, fn){
6381 return stopListening(element, eventName, fn);
6385 * Fires when the document is ready (before onload and before images are loaded). Can be
6386 * accessed shorthanded Roo.onReady().
6387 * @param {Function} fn The method the event invokes
6388 * @param {Object} scope An object that becomes the scope of the handler
6389 * @param {boolean} options
6391 onDocumentReady : function(fn, scope, options){
6392 if(docReadyState){ // if it already fired
6393 docReadyEvent.addListener(fn, scope, options);
6394 docReadyEvent.fire();
6395 docReadyEvent.clearListeners();
6401 docReadyEvent.addListener(fn, scope, options);
6405 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6406 * @param {Function} fn The method the event invokes
6407 * @param {Object} scope An object that becomes the scope of the handler
6408 * @param {boolean} options
6410 onWindowResize : function(fn, scope, options){
6412 resizeEvent = new Roo.util.Event();
6413 resizeTask = new Roo.util.DelayedTask(function(){
6414 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6416 E.on(window, "resize", function(){
6418 resizeTask.delay(50);
6420 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6424 resizeEvent.addListener(fn, scope, options);
6428 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6429 * @param {Function} fn The method the event invokes
6430 * @param {Object} scope An object that becomes the scope of the handler
6431 * @param {boolean} options
6433 onTextResize : function(fn, scope, options){
6435 textEvent = new Roo.util.Event();
6436 var textEl = new Roo.Element(document.createElement('div'));
6437 textEl.dom.className = 'x-text-resize';
6438 textEl.dom.innerHTML = 'X';
6439 textEl.appendTo(document.body);
6440 textSize = textEl.dom.offsetHeight;
6441 setInterval(function(){
6442 if(textEl.dom.offsetHeight != textSize){
6443 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6445 }, this.textResizeInterval);
6447 textEvent.addListener(fn, scope, options);
6451 * Removes the passed window resize listener.
6452 * @param {Function} fn The method the event invokes
6453 * @param {Object} scope The scope of handler
6455 removeResizeListener : function(fn, scope){
6457 resizeEvent.removeListener(fn, scope);
6462 fireResize : function(){
6464 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6468 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6472 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6474 textResizeInterval : 50
6479 * @scopeAlias pub=Roo.EventManager
6483 * Appends an event handler to an element (shorthand for addListener)
6484 * @param {String/HTMLElement} element The html element or id to assign the
6485 * @param {String} eventName The type of event to listen for
6486 * @param {Function} handler The method the event invokes
6487 * @param {Object} scope (optional) The scope in which to execute the handler
6488 * function. The handler function's "this" context.
6489 * @param {Object} options (optional) An object containing handler configuration
6490 * properties. This may contain any of the following properties:<ul>
6491 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6492 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6493 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6494 * <li>preventDefault {Boolean} True to prevent the default action</li>
6495 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6496 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6497 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6498 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6499 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6500 * by the specified number of milliseconds. If the event fires again within that time, the original
6501 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6504 * <b>Combining Options</b><br>
6505 * Using the options argument, it is possible to combine different types of listeners:<br>
6507 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6509 el.on('click', this.onClick, this, {
6516 * <b>Attaching multiple handlers in 1 call</b><br>
6517 * The method also allows for a single argument to be passed which is a config object containing properties
6518 * which specify multiple handlers.
6528 fn: this.onMouseOver
6537 * Or a shorthand syntax:<br>
6540 'click' : this.onClick,
6541 'mouseover' : this.onMouseOver,
6542 'mouseout' : this.onMouseOut
6546 pub.on = pub.addListener;
6547 pub.un = pub.removeListener;
6549 pub.stoppedMouseDownEvent = new Roo.util.Event();
6553 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6554 * @param {Function} fn The method the event invokes
6555 * @param {Object} scope An object that becomes the scope of the handler
6556 * @param {boolean} override If true, the obj passed in becomes
6557 * the execution scope of the listener
6561 Roo.onReady = Roo.EventManager.onDocumentReady;
6563 Roo.onReady(function(){
6564 var bd = Roo.get(document.body);
6569 : Roo.isGecko ? "roo-gecko"
6570 : Roo.isOpera ? "roo-opera"
6571 : Roo.isSafari ? "roo-safari" : ""];
6574 cls.push("roo-mac");
6577 cls.push("roo-linux");
6579 if(Roo.isBorderBox){
6580 cls.push('roo-border-box');
6582 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6583 var p = bd.dom.parentNode;
6585 p.className += ' roo-strict';
6588 bd.addClass(cls.join(' '));
6592 * @class Roo.EventObject
6593 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6594 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6597 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6599 var target = e.getTarget();
6602 var myDiv = Roo.get("myDiv");
6603 myDiv.on("click", handleClick);
6605 Roo.EventManager.on("myDiv", 'click', handleClick);
6606 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6610 Roo.EventObject = function(){
6612 var E = Roo.lib.Event;
6614 // safari keypress events for special keys return bad keycodes
6617 63235 : 39, // right
6620 63276 : 33, // page up
6621 63277 : 34, // page down
6622 63272 : 46, // delete
6627 // normalize button clicks
6628 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6629 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6631 Roo.EventObjectImpl = function(e){
6633 this.setEvent(e.browserEvent || e);
6636 Roo.EventObjectImpl.prototype = {
6638 * Used to fix doc tools.
6639 * @scope Roo.EventObject.prototype
6645 /** The normal browser event */
6646 browserEvent : null,
6647 /** The button pressed in a mouse event */
6649 /** True if the shift key was down during the event */
6651 /** True if the control key was down during the event */
6653 /** True if the alt key was down during the event */
6712 setEvent : function(e){
6713 if(e == this || (e && e.browserEvent)){ // already wrapped
6716 this.browserEvent = e;
6718 // normalize buttons
6719 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6720 if(e.type == 'click' && this.button == -1){
6724 this.shiftKey = e.shiftKey;
6725 // mac metaKey behaves like ctrlKey
6726 this.ctrlKey = e.ctrlKey || e.metaKey;
6727 this.altKey = e.altKey;
6728 // in getKey these will be normalized for the mac
6729 this.keyCode = e.keyCode;
6730 // keyup warnings on firefox.
6731 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6732 // cache the target for the delayed and or buffered events
6733 this.target = E.getTarget(e);
6735 this.xy = E.getXY(e);
6738 this.shiftKey = false;
6739 this.ctrlKey = false;
6740 this.altKey = false;
6750 * Stop the event (preventDefault and stopPropagation)
6752 stopEvent : function(){
6753 if(this.browserEvent){
6754 if(this.browserEvent.type == 'mousedown'){
6755 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6757 E.stopEvent(this.browserEvent);
6762 * Prevents the browsers default handling of the event.
6764 preventDefault : function(){
6765 if(this.browserEvent){
6766 E.preventDefault(this.browserEvent);
6771 isNavKeyPress : function(){
6772 var k = this.keyCode;
6773 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6774 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6777 isSpecialKey : function(){
6778 var k = this.keyCode;
6779 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6780 (k == 16) || (k == 17) ||
6781 (k >= 18 && k <= 20) ||
6782 (k >= 33 && k <= 35) ||
6783 (k >= 36 && k <= 39) ||
6784 (k >= 44 && k <= 45);
6787 * Cancels bubbling of the event.
6789 stopPropagation : function(){
6790 if(this.browserEvent){
6791 if(this.type == 'mousedown'){
6792 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6794 E.stopPropagation(this.browserEvent);
6799 * Gets the key code for the event.
6802 getCharCode : function(){
6803 return this.charCode || this.keyCode;
6807 * Returns a normalized keyCode for the event.
6808 * @return {Number} The key code
6810 getKey : function(){
6811 var k = this.keyCode || this.charCode;
6812 return Roo.isSafari ? (safariKeys[k] || k) : k;
6816 * Gets the x coordinate of the event.
6819 getPageX : function(){
6824 * Gets the y coordinate of the event.
6827 getPageY : function(){
6832 * Gets the time of the event.
6835 getTime : function(){
6836 if(this.browserEvent){
6837 return E.getTime(this.browserEvent);
6843 * Gets the page coordinates of the event.
6844 * @return {Array} The xy values like [x, y]
6851 * Gets the target for the event.
6852 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6853 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6854 search as a number or element (defaults to 10 || document.body)
6855 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6856 * @return {HTMLelement}
6858 getTarget : function(selector, maxDepth, returnEl){
6859 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6862 * Gets the related target.
6863 * @return {HTMLElement}
6865 getRelatedTarget : function(){
6866 if(this.browserEvent){
6867 return E.getRelatedTarget(this.browserEvent);
6873 * Normalizes mouse wheel delta across browsers
6874 * @return {Number} The delta
6876 getWheelDelta : function(){
6877 var e = this.browserEvent;
6879 if(e.wheelDelta){ /* IE/Opera. */
6880 delta = e.wheelDelta/120;
6881 }else if(e.detail){ /* Mozilla case. */
6882 delta = -e.detail/3;
6888 * Returns true if the control, meta, shift or alt key was pressed during this event.
6891 hasModifier : function(){
6892 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6896 * Returns true if the target of this event equals el or is a child of el
6897 * @param {String/HTMLElement/Element} el
6898 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6901 within : function(el, related){
6902 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6903 return t && Roo.fly(el).contains(t);
6906 getPoint : function(){
6907 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6911 return new Roo.EventObjectImpl();
6916 * Ext JS Library 1.1.1
6917 * Copyright(c) 2006-2007, Ext JS, LLC.
6919 * Originally Released Under LGPL - original licence link has changed is not relivant.
6922 * <script type="text/javascript">
6926 // was in Composite Element!??!?!
6929 var D = Roo.lib.Dom;
6930 var E = Roo.lib.Event;
6931 var A = Roo.lib.Anim;
6933 // local style camelizing for speed
6935 var camelRe = /(-[a-z])/gi;
6936 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6937 var view = document.defaultView;
6940 * @class Roo.Element
6941 * Represents an Element in the DOM.<br><br>
6944 var el = Roo.get("my-div");
6947 var el = getEl("my-div");
6949 // or with a DOM element
6950 var el = Roo.get(myDivElement);
6952 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6953 * each call instead of constructing a new one.<br><br>
6954 * <b>Animations</b><br />
6955 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6956 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6958 Option Default Description
6959 --------- -------- ---------------------------------------------
6960 duration .35 The duration of the animation in seconds
6961 easing easeOut The YUI easing method
6962 callback none A function to execute when the anim completes
6963 scope this The scope (this) of the callback function
6965 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6966 * manipulate the animation. Here's an example:
6968 var el = Roo.get("my-div");
6973 // default animation
6974 el.setWidth(100, true);
6976 // animation with some options set
6983 // using the "anim" property to get the Anim object
6989 el.setWidth(100, opt);
6991 if(opt.anim.isAnimated()){
6995 * <b> Composite (Collections of) Elements</b><br />
6996 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6997 * @constructor Create a new Element directly.
6998 * @param {String/HTMLElement} element
6999 * @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).
7001 Roo.Element = function(element, forceNew){
7002 var dom = typeof element == "string" ?
7003 document.getElementById(element) : element;
7004 if(!dom){ // invalid id/element
7008 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7009 return Roo.Element.cache[id];
7019 * The DOM element ID
7022 this.id = id || Roo.id(dom);
7025 var El = Roo.Element;
7029 * The element's default display mode (defaults to "")
7032 originalDisplay : "",
7036 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7041 * Sets the element's visibility mode. When setVisible() is called it
7042 * will use this to determine whether to set the visibility or the display property.
7043 * @param visMode Element.VISIBILITY or Element.DISPLAY
7044 * @return {Roo.Element} this
7046 setVisibilityMode : function(visMode){
7047 this.visibilityMode = visMode;
7051 * Convenience method for setVisibilityMode(Element.DISPLAY)
7052 * @param {String} display (optional) What to set display to when visible
7053 * @return {Roo.Element} this
7055 enableDisplayMode : function(display){
7056 this.setVisibilityMode(El.DISPLAY);
7057 if(typeof display != "undefined") this.originalDisplay = display;
7062 * 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)
7063 * @param {String} selector The simple selector to test
7064 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7065 search as a number or element (defaults to 10 || document.body)
7066 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7067 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7069 findParent : function(simpleSelector, maxDepth, returnEl){
7070 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7071 maxDepth = maxDepth || 50;
7072 if(typeof maxDepth != "number"){
7073 stopEl = Roo.getDom(maxDepth);
7076 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7077 if(dq.is(p, simpleSelector)){
7078 return returnEl ? Roo.get(p) : p;
7088 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7089 * @param {String} selector The simple selector to test
7090 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7091 search as a number or element (defaults to 10 || document.body)
7092 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7093 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7095 findParentNode : function(simpleSelector, maxDepth, returnEl){
7096 var p = Roo.fly(this.dom.parentNode, '_internal');
7097 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7101 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7102 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7103 * @param {String} selector The simple selector to test
7104 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7105 search as a number or element (defaults to 10 || document.body)
7106 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7108 up : function(simpleSelector, maxDepth){
7109 return this.findParentNode(simpleSelector, maxDepth, true);
7115 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7116 * @param {String} selector The simple selector to test
7117 * @return {Boolean} True if this element matches the selector, else false
7119 is : function(simpleSelector){
7120 return Roo.DomQuery.is(this.dom, simpleSelector);
7124 * Perform animation on this element.
7125 * @param {Object} args The YUI animation control args
7126 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7127 * @param {Function} onComplete (optional) Function to call when animation completes
7128 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7129 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7130 * @return {Roo.Element} this
7132 animate : function(args, duration, onComplete, easing, animType){
7133 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7138 * @private Internal animation call
7140 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7141 animType = animType || 'run';
7143 var anim = Roo.lib.Anim[animType](
7145 (opt.duration || defaultDur) || .35,
7146 (opt.easing || defaultEase) || 'easeOut',
7148 Roo.callback(cb, this);
7149 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7157 // private legacy anim prep
7158 preanim : function(a, i){
7159 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7163 * Removes worthless text nodes
7164 * @param {Boolean} forceReclean (optional) By default the element
7165 * keeps track if it has been cleaned already so
7166 * you can call this over and over. However, if you update the element and
7167 * need to force a reclean, you can pass true.
7169 clean : function(forceReclean){
7170 if(this.isCleaned && forceReclean !== true){
7174 var d = this.dom, n = d.firstChild, ni = -1;
7176 var nx = n.nextSibling;
7177 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7184 this.isCleaned = true;
7189 calcOffsetsTo : function(el){
7192 var restorePos = false;
7193 if(el.getStyle('position') == 'static'){
7194 el.position('relative');
7199 while(op && op != d && op.tagName != 'HTML'){
7202 op = op.offsetParent;
7205 el.position('static');
7211 * Scrolls this element into view within the passed container.
7212 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7213 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7214 * @return {Roo.Element} this
7216 scrollIntoView : function(container, hscroll){
7217 var c = Roo.getDom(container) || document.body;
7220 var o = this.calcOffsetsTo(c),
7223 b = t+el.offsetHeight,
7224 r = l+el.offsetWidth;
7226 var ch = c.clientHeight;
7227 var ct = parseInt(c.scrollTop, 10);
7228 var cl = parseInt(c.scrollLeft, 10);
7230 var cr = cl + c.clientWidth;
7238 if(hscroll !== false){
7242 c.scrollLeft = r-c.clientWidth;
7249 scrollChildIntoView : function(child, hscroll){
7250 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7254 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7255 * the new height may not be available immediately.
7256 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7257 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7258 * @param {Function} onComplete (optional) Function to call when animation completes
7259 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7260 * @return {Roo.Element} this
7262 autoHeight : function(animate, duration, onComplete, easing){
7263 var oldHeight = this.getHeight();
7265 this.setHeight(1); // force clipping
7266 setTimeout(function(){
7267 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7269 this.setHeight(height);
7271 if(typeof onComplete == "function"){
7275 this.setHeight(oldHeight); // restore original height
7276 this.setHeight(height, animate, duration, function(){
7278 if(typeof onComplete == "function") onComplete();
7279 }.createDelegate(this), easing);
7281 }.createDelegate(this), 0);
7286 * Returns true if this element is an ancestor of the passed element
7287 * @param {HTMLElement/String} el The element to check
7288 * @return {Boolean} True if this element is an ancestor of el, else false
7290 contains : function(el){
7291 if(!el){return false;}
7292 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7296 * Checks whether the element is currently visible using both visibility and display properties.
7297 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7298 * @return {Boolean} True if the element is currently visible, else false
7300 isVisible : function(deep) {
7301 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7302 if(deep !== true || !vis){
7305 var p = this.dom.parentNode;
7306 while(p && p.tagName.toLowerCase() != "body"){
7307 if(!Roo.fly(p, '_isVisible').isVisible()){
7316 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7317 * @param {String} selector The CSS selector
7318 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7319 * @return {CompositeElement/CompositeElementLite} The composite element
7321 select : function(selector, unique){
7322 return El.select(selector, unique, this.dom);
7326 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7327 * @param {String} selector The CSS selector
7328 * @return {Array} An array of the matched nodes
7330 query : function(selector, unique){
7331 return Roo.DomQuery.select(selector, this.dom);
7335 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7336 * @param {String} selector The CSS selector
7337 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7338 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7340 child : function(selector, returnDom){
7341 var n = Roo.DomQuery.selectNode(selector, this.dom);
7342 return returnDom ? n : Roo.get(n);
7346 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7347 * @param {String} selector The CSS selector
7348 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7349 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7351 down : function(selector, returnDom){
7352 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7353 return returnDom ? n : Roo.get(n);
7357 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7358 * @param {String} group The group the DD object is member of
7359 * @param {Object} config The DD config object
7360 * @param {Object} overrides An object containing methods to override/implement on the DD object
7361 * @return {Roo.dd.DD} The DD object
7363 initDD : function(group, config, overrides){
7364 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7365 return Roo.apply(dd, overrides);
7369 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7370 * @param {String} group The group the DDProxy object is member of
7371 * @param {Object} config The DDProxy config object
7372 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7373 * @return {Roo.dd.DDProxy} The DDProxy object
7375 initDDProxy : function(group, config, overrides){
7376 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7377 return Roo.apply(dd, overrides);
7381 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7382 * @param {String} group The group the DDTarget object is member of
7383 * @param {Object} config The DDTarget config object
7384 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7385 * @return {Roo.dd.DDTarget} The DDTarget object
7387 initDDTarget : function(group, config, overrides){
7388 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7389 return Roo.apply(dd, overrides);
7393 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7394 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7395 * @param {Boolean} visible Whether the element is visible
7396 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7397 * @return {Roo.Element} this
7399 setVisible : function(visible, animate){
7401 if(this.visibilityMode == El.DISPLAY){
7402 this.setDisplayed(visible);
7405 this.dom.style.visibility = visible ? "visible" : "hidden";
7408 // closure for composites
7410 var visMode = this.visibilityMode;
7412 this.setOpacity(.01);
7413 this.setVisible(true);
7415 this.anim({opacity: { to: (visible?1:0) }},
7416 this.preanim(arguments, 1),
7417 null, .35, 'easeIn', function(){
7419 if(visMode == El.DISPLAY){
7420 dom.style.display = "none";
7422 dom.style.visibility = "hidden";
7424 Roo.get(dom).setOpacity(1);
7432 * Returns true if display is not "none"
7435 isDisplayed : function() {
7436 return this.getStyle("display") != "none";
7440 * Toggles the element's visibility or display, depending on visibility mode.
7441 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7442 * @return {Roo.Element} this
7444 toggle : function(animate){
7445 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7450 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7451 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7452 * @return {Roo.Element} this
7454 setDisplayed : function(value) {
7455 if(typeof value == "boolean"){
7456 value = value ? this.originalDisplay : "none";
7458 this.setStyle("display", value);
7463 * Tries to focus the element. Any exceptions are caught and ignored.
7464 * @return {Roo.Element} this
7466 focus : function() {
7474 * Tries to blur the element. Any exceptions are caught and ignored.
7475 * @return {Roo.Element} this
7485 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7486 * @param {String/Array} className The CSS class to add, or an array of classes
7487 * @return {Roo.Element} this
7489 addClass : function(className){
7490 if(className instanceof Array){
7491 for(var i = 0, len = className.length; i < len; i++) {
7492 this.addClass(className[i]);
7495 if(className && !this.hasClass(className)){
7496 this.dom.className = this.dom.className + " " + className;
7503 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7504 * @param {String/Array} className The CSS class to add, or an array of classes
7505 * @return {Roo.Element} this
7507 radioClass : function(className){
7508 var siblings = this.dom.parentNode.childNodes;
7509 for(var i = 0; i < siblings.length; i++) {
7510 var s = siblings[i];
7511 if(s.nodeType == 1){
7512 Roo.get(s).removeClass(className);
7515 this.addClass(className);
7520 * Removes one or more CSS classes from the element.
7521 * @param {String/Array} className The CSS class to remove, or an array of classes
7522 * @return {Roo.Element} this
7524 removeClass : function(className){
7525 if(!className || !this.dom.className){
7528 if(className instanceof Array){
7529 for(var i = 0, len = className.length; i < len; i++) {
7530 this.removeClass(className[i]);
7533 if(this.hasClass(className)){
7534 var re = this.classReCache[className];
7536 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7537 this.classReCache[className] = re;
7539 this.dom.className =
7540 this.dom.className.replace(re, " ");
7550 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7551 * @param {String} className The CSS class to toggle
7552 * @return {Roo.Element} this
7554 toggleClass : function(className){
7555 if(this.hasClass(className)){
7556 this.removeClass(className);
7558 this.addClass(className);
7564 * Checks if the specified CSS class exists on this element's DOM node.
7565 * @param {String} className The CSS class to check for
7566 * @return {Boolean} True if the class exists, else false
7568 hasClass : function(className){
7569 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7573 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7574 * @param {String} oldClassName The CSS class to replace
7575 * @param {String} newClassName The replacement CSS class
7576 * @return {Roo.Element} this
7578 replaceClass : function(oldClassName, newClassName){
7579 this.removeClass(oldClassName);
7580 this.addClass(newClassName);
7585 * Returns an object with properties matching the styles requested.
7586 * For example, el.getStyles('color', 'font-size', 'width') might return
7587 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7588 * @param {String} style1 A style name
7589 * @param {String} style2 A style name
7590 * @param {String} etc.
7591 * @return {Object} The style object
7593 getStyles : function(){
7594 var a = arguments, len = a.length, r = {};
7595 for(var i = 0; i < len; i++){
7596 r[a[i]] = this.getStyle(a[i]);
7602 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7603 * @param {String} property The style property whose value is returned.
7604 * @return {String} The current value of the style property for this element.
7606 getStyle : function(){
7607 return view && view.getComputedStyle ?
7609 var el = this.dom, v, cs, camel;
7610 if(prop == 'float'){
7613 if(el.style && (v = el.style[prop])){
7616 if(cs = view.getComputedStyle(el, "")){
7617 if(!(camel = propCache[prop])){
7618 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7625 var el = this.dom, v, cs, camel;
7626 if(prop == 'opacity'){
7627 if(typeof el.style.filter == 'string'){
7628 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7630 var fv = parseFloat(m[1]);
7632 return fv ? fv / 100 : 0;
7637 }else if(prop == 'float'){
7638 prop = "styleFloat";
7640 if(!(camel = propCache[prop])){
7641 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7643 if(v = el.style[camel]){
7646 if(cs = el.currentStyle){
7654 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7655 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7656 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7657 * @return {Roo.Element} this
7659 setStyle : function(prop, value){
7660 if(typeof prop == "string"){
7662 if (prop == 'float') {
7663 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7668 if(!(camel = propCache[prop])){
7669 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7672 if(camel == 'opacity') {
7673 this.setOpacity(value);
7675 this.dom.style[camel] = value;
7678 for(var style in prop){
7679 if(typeof prop[style] != "function"){
7680 this.setStyle(style, prop[style]);
7688 * More flexible version of {@link #setStyle} for setting style properties.
7689 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7690 * a function which returns such a specification.
7691 * @return {Roo.Element} this
7693 applyStyles : function(style){
7694 Roo.DomHelper.applyStyles(this.dom, style);
7699 * 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).
7700 * @return {Number} The X position of the element
7703 return D.getX(this.dom);
7707 * 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).
7708 * @return {Number} The Y position of the element
7711 return D.getY(this.dom);
7715 * 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).
7716 * @return {Array} The XY position of the element
7719 return D.getXY(this.dom);
7723 * 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).
7724 * @param {Number} The X position of the element
7725 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7726 * @return {Roo.Element} this
7728 setX : function(x, animate){
7730 D.setX(this.dom, x);
7732 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7738 * 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).
7739 * @param {Number} The Y position of the element
7740 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7741 * @return {Roo.Element} this
7743 setY : function(y, animate){
7745 D.setY(this.dom, y);
7747 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7753 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7754 * @param {String} left The left CSS property value
7755 * @return {Roo.Element} this
7757 setLeft : function(left){
7758 this.setStyle("left", this.addUnits(left));
7763 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7764 * @param {String} top The top CSS property value
7765 * @return {Roo.Element} this
7767 setTop : function(top){
7768 this.setStyle("top", this.addUnits(top));
7773 * Sets the element's CSS right style.
7774 * @param {String} right The right CSS property value
7775 * @return {Roo.Element} this
7777 setRight : function(right){
7778 this.setStyle("right", this.addUnits(right));
7783 * Sets the element's CSS bottom style.
7784 * @param {String} bottom The bottom CSS property value
7785 * @return {Roo.Element} this
7787 setBottom : function(bottom){
7788 this.setStyle("bottom", this.addUnits(bottom));
7793 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7794 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7795 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7796 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7797 * @return {Roo.Element} this
7799 setXY : function(pos, animate){
7801 D.setXY(this.dom, pos);
7803 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7809 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7810 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7811 * @param {Number} x X value for new position (coordinates are page-based)
7812 * @param {Number} y Y value for new position (coordinates are page-based)
7813 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7814 * @return {Roo.Element} this
7816 setLocation : function(x, y, animate){
7817 this.setXY([x, y], this.preanim(arguments, 2));
7822 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7823 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7824 * @param {Number} x X value for new position (coordinates are page-based)
7825 * @param {Number} y Y value for new position (coordinates are page-based)
7826 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7827 * @return {Roo.Element} this
7829 moveTo : function(x, y, animate){
7830 this.setXY([x, y], this.preanim(arguments, 2));
7835 * Returns the region of the given element.
7836 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7837 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7839 getRegion : function(){
7840 return D.getRegion(this.dom);
7844 * Returns the offset height of the element
7845 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7846 * @return {Number} The element's height
7848 getHeight : function(contentHeight){
7849 var h = this.dom.offsetHeight || 0;
7850 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7854 * Returns the offset width of the element
7855 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7856 * @return {Number} The element's width
7858 getWidth : function(contentWidth){
7859 var w = this.dom.offsetWidth || 0;
7860 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7864 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7865 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7866 * if a height has not been set using CSS.
7869 getComputedHeight : function(){
7870 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7872 h = parseInt(this.getStyle('height'), 10) || 0;
7873 if(!this.isBorderBox()){
7874 h += this.getFrameWidth('tb');
7881 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7882 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7883 * if a width has not been set using CSS.
7886 getComputedWidth : function(){
7887 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7889 w = parseInt(this.getStyle('width'), 10) || 0;
7890 if(!this.isBorderBox()){
7891 w += this.getFrameWidth('lr');
7898 * Returns the size of the element.
7899 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7900 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7902 getSize : function(contentSize){
7903 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7907 * Returns the width and height of the viewport.
7908 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7910 getViewSize : function(){
7911 var d = this.dom, doc = document, aw = 0, ah = 0;
7912 if(d == doc || d == doc.body){
7913 return {width : D.getViewWidth(), height: D.getViewHeight()};
7916 width : d.clientWidth,
7917 height: d.clientHeight
7923 * Returns the value of the "value" attribute
7924 * @param {Boolean} asNumber true to parse the value as a number
7925 * @return {String/Number}
7927 getValue : function(asNumber){
7928 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7932 adjustWidth : function(width){
7933 if(typeof width == "number"){
7934 if(this.autoBoxAdjust && !this.isBorderBox()){
7935 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7945 adjustHeight : function(height){
7946 if(typeof height == "number"){
7947 if(this.autoBoxAdjust && !this.isBorderBox()){
7948 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7958 * Set the width of the element
7959 * @param {Number} width The new width
7960 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7961 * @return {Roo.Element} this
7963 setWidth : function(width, animate){
7964 width = this.adjustWidth(width);
7966 this.dom.style.width = this.addUnits(width);
7968 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7974 * Set the height of the element
7975 * @param {Number} height The new height
7976 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7977 * @return {Roo.Element} this
7979 setHeight : function(height, animate){
7980 height = this.adjustHeight(height);
7982 this.dom.style.height = this.addUnits(height);
7984 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7990 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7991 * @param {Number} width The new width
7992 * @param {Number} height The new height
7993 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7994 * @return {Roo.Element} this
7996 setSize : function(width, height, animate){
7997 if(typeof width == "object"){ // in case of object from getSize()
7998 height = width.height; width = width.width;
8000 width = this.adjustWidth(width); height = this.adjustHeight(height);
8002 this.dom.style.width = this.addUnits(width);
8003 this.dom.style.height = this.addUnits(height);
8005 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8011 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8012 * @param {Number} x X value for new position (coordinates are page-based)
8013 * @param {Number} y Y value for new position (coordinates are page-based)
8014 * @param {Number} width The new width
8015 * @param {Number} height The new height
8016 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8017 * @return {Roo.Element} this
8019 setBounds : function(x, y, width, height, animate){
8021 this.setSize(width, height);
8022 this.setLocation(x, y);
8024 width = this.adjustWidth(width); height = this.adjustHeight(height);
8025 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8026 this.preanim(arguments, 4), 'motion');
8032 * 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.
8033 * @param {Roo.lib.Region} region The region to fill
8034 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8035 * @return {Roo.Element} this
8037 setRegion : function(region, animate){
8038 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8043 * Appends an event handler
8045 * @param {String} eventName The type of event to append
8046 * @param {Function} fn The method the event invokes
8047 * @param {Object} scope (optional) The scope (this object) of the fn
8048 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8050 addListener : function(eventName, fn, scope, options){
8052 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8057 * Removes an event handler from this element
8058 * @param {String} eventName the type of event to remove
8059 * @param {Function} fn the method the event invokes
8060 * @return {Roo.Element} this
8062 removeListener : function(eventName, fn){
8063 Roo.EventManager.removeListener(this.dom, eventName, fn);
8068 * Removes all previous added listeners from this element
8069 * @return {Roo.Element} this
8071 removeAllListeners : function(){
8072 E.purgeElement(this.dom);
8076 relayEvent : function(eventName, observable){
8077 this.on(eventName, function(e){
8078 observable.fireEvent(eventName, e);
8083 * Set the opacity of the element
8084 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8085 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8086 * @return {Roo.Element} this
8088 setOpacity : function(opacity, animate){
8090 var s = this.dom.style;
8093 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8094 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8096 s.opacity = opacity;
8099 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8105 * Gets the left X coordinate
8106 * @param {Boolean} local True to get the local css position instead of page coordinate
8109 getLeft : function(local){
8113 return parseInt(this.getStyle("left"), 10) || 0;
8118 * Gets the right X coordinate of the element (element X position + element width)
8119 * @param {Boolean} local True to get the local css position instead of page coordinate
8122 getRight : function(local){
8124 return this.getX() + this.getWidth();
8126 return (this.getLeft(true) + this.getWidth()) || 0;
8131 * Gets the top Y coordinate
8132 * @param {Boolean} local True to get the local css position instead of page coordinate
8135 getTop : function(local) {
8139 return parseInt(this.getStyle("top"), 10) || 0;
8144 * Gets the bottom Y coordinate of the element (element Y position + element height)
8145 * @param {Boolean} local True to get the local css position instead of page coordinate
8148 getBottom : function(local){
8150 return this.getY() + this.getHeight();
8152 return (this.getTop(true) + this.getHeight()) || 0;
8157 * Initializes positioning on this element. If a desired position is not passed, it will make the
8158 * the element positioned relative IF it is not already positioned.
8159 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8160 * @param {Number} zIndex (optional) The zIndex to apply
8161 * @param {Number} x (optional) Set the page X position
8162 * @param {Number} y (optional) Set the page Y position
8164 position : function(pos, zIndex, x, y){
8166 if(this.getStyle('position') == 'static'){
8167 this.setStyle('position', 'relative');
8170 this.setStyle("position", pos);
8173 this.setStyle("z-index", zIndex);
8175 if(x !== undefined && y !== undefined){
8177 }else if(x !== undefined){
8179 }else if(y !== undefined){
8185 * Clear positioning back to the default when the document was loaded
8186 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8187 * @return {Roo.Element} this
8189 clearPositioning : function(value){
8197 "position" : "static"
8203 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8204 * snapshot before performing an update and then restoring the element.
8207 getPositioning : function(){
8208 var l = this.getStyle("left");
8209 var t = this.getStyle("top");
8211 "position" : this.getStyle("position"),
8213 "right" : l ? "" : this.getStyle("right"),
8215 "bottom" : t ? "" : this.getStyle("bottom"),
8216 "z-index" : this.getStyle("z-index")
8221 * Gets the width of the border(s) for the specified side(s)
8222 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8223 * passing lr would get the border (l)eft width + the border (r)ight width.
8224 * @return {Number} The width of the sides passed added together
8226 getBorderWidth : function(side){
8227 return this.addStyles(side, El.borders);
8231 * Gets the width of the padding(s) for the specified side(s)
8232 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8233 * passing lr would get the padding (l)eft + the padding (r)ight.
8234 * @return {Number} The padding of the sides passed added together
8236 getPadding : function(side){
8237 return this.addStyles(side, El.paddings);
8241 * Set positioning with an object returned by getPositioning().
8242 * @param {Object} posCfg
8243 * @return {Roo.Element} this
8245 setPositioning : function(pc){
8246 this.applyStyles(pc);
8247 if(pc.right == "auto"){
8248 this.dom.style.right = "";
8250 if(pc.bottom == "auto"){
8251 this.dom.style.bottom = "";
8257 fixDisplay : function(){
8258 if(this.getStyle("display") == "none"){
8259 this.setStyle("visibility", "hidden");
8260 this.setStyle("display", this.originalDisplay); // first try reverting to default
8261 if(this.getStyle("display") == "none"){ // if that fails, default to block
8262 this.setStyle("display", "block");
8268 * Quick set left and top adding default units
8269 * @param {String} left The left CSS property value
8270 * @param {String} top The top CSS property value
8271 * @return {Roo.Element} this
8273 setLeftTop : function(left, top){
8274 this.dom.style.left = this.addUnits(left);
8275 this.dom.style.top = this.addUnits(top);
8280 * Move this element relative to its current position.
8281 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8282 * @param {Number} distance How far to move the element in pixels
8283 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8284 * @return {Roo.Element} this
8286 move : function(direction, distance, animate){
8287 var xy = this.getXY();
8288 direction = direction.toLowerCase();
8292 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8296 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8301 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8306 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8313 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8314 * @return {Roo.Element} this
8317 if(!this.isClipped){
8318 this.isClipped = true;
8319 this.originalClip = {
8320 "o": this.getStyle("overflow"),
8321 "x": this.getStyle("overflow-x"),
8322 "y": this.getStyle("overflow-y")
8324 this.setStyle("overflow", "hidden");
8325 this.setStyle("overflow-x", "hidden");
8326 this.setStyle("overflow-y", "hidden");
8332 * Return clipping (overflow) to original clipping before clip() was called
8333 * @return {Roo.Element} this
8335 unclip : function(){
8337 this.isClipped = false;
8338 var o = this.originalClip;
8339 if(o.o){this.setStyle("overflow", o.o);}
8340 if(o.x){this.setStyle("overflow-x", o.x);}
8341 if(o.y){this.setStyle("overflow-y", o.y);}
8348 * Gets the x,y coordinates specified by the anchor position on the element.
8349 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8350 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8351 * {width: (target width), height: (target height)} (defaults to the element's current size)
8352 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8353 * @return {Array} [x, y] An array containing the element's x and y coordinates
8355 getAnchorXY : function(anchor, local, s){
8356 //Passing a different size is useful for pre-calculating anchors,
8357 //especially for anchored animations that change the el size.
8359 var w, h, vp = false;
8362 if(d == document.body || d == document){
8364 w = D.getViewWidth(); h = D.getViewHeight();
8366 w = this.getWidth(); h = this.getHeight();
8369 w = s.width; h = s.height;
8371 var x = 0, y = 0, r = Math.round;
8372 switch((anchor || "tl").toLowerCase()){
8414 var sc = this.getScroll();
8415 return [x + sc.left, y + sc.top];
8417 //Add the element's offset xy
8418 var o = this.getXY();
8419 return [x+o[0], y+o[1]];
8423 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8424 * supported position values.
8425 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8426 * @param {String} position The position to align to.
8427 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8428 * @return {Array} [x, y]
8430 getAlignToXY : function(el, p, o){
8434 throw "Element.alignTo with an element that doesn't exist";
8436 var c = false; //constrain to viewport
8437 var p1 = "", p2 = "";
8444 }else if(p.indexOf("-") == -1){
8447 p = p.toLowerCase();
8448 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8450 throw "Element.alignTo with an invalid alignment " + p;
8452 p1 = m[1]; p2 = m[2]; c = !!m[3];
8454 //Subtract the aligned el's internal xy from the target's offset xy
8455 //plus custom offset to get the aligned el's new offset xy
8456 var a1 = this.getAnchorXY(p1, true);
8457 var a2 = el.getAnchorXY(p2, false);
8458 var x = a2[0] - a1[0] + o[0];
8459 var y = a2[1] - a1[1] + o[1];
8461 //constrain the aligned el to viewport if necessary
8462 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8463 // 5px of margin for ie
8464 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8466 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8467 //perpendicular to the vp border, allow the aligned el to slide on that border,
8468 //otherwise swap the aligned el to the opposite border of the target.
8469 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8470 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8471 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8472 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8475 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8476 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8478 if((x+w) > dw + scrollX){
8479 x = swapX ? r.left-w : dw+scrollX-w;
8482 x = swapX ? r.right : scrollX;
8484 if((y+h) > dh + scrollY){
8485 y = swapY ? r.top-h : dh+scrollY-h;
8488 y = swapY ? r.bottom : scrollY;
8495 getConstrainToXY : function(){
8496 var os = {top:0, left:0, bottom:0, right: 0};
8498 return function(el, local, offsets, proposedXY){
8500 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8502 var vw, vh, vx = 0, vy = 0;
8503 if(el.dom == document.body || el.dom == document){
8504 vw = Roo.lib.Dom.getViewWidth();
8505 vh = Roo.lib.Dom.getViewHeight();
8507 vw = el.dom.clientWidth;
8508 vh = el.dom.clientHeight;
8510 var vxy = el.getXY();
8516 var s = el.getScroll();
8518 vx += offsets.left + s.left;
8519 vy += offsets.top + s.top;
8521 vw -= offsets.right;
8522 vh -= offsets.bottom;
8527 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8528 var x = xy[0], y = xy[1];
8529 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8531 // only move it if it needs it
8534 // first validate right/bottom
8543 // then make sure top/left isn't negative
8552 return moved ? [x, y] : false;
8557 adjustForConstraints : function(xy, parent, offsets){
8558 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8562 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8563 * document it aligns it to the viewport.
8564 * The position parameter is optional, and can be specified in any one of the following formats:
8566 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8567 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8568 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8569 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8570 * <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
8571 * element's anchor point, and the second value is used as the target's anchor point.</li>
8573 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8574 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8575 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8576 * that specified in order to enforce the viewport constraints.
8577 * Following are all of the supported anchor positions:
8580 ----- -----------------------------
8581 tl The top left corner (default)
8582 t The center of the top edge
8583 tr The top right corner
8584 l The center of the left edge
8585 c In the center of the element
8586 r The center of the right edge
8587 bl The bottom left corner
8588 b The center of the bottom edge
8589 br The bottom right corner
8593 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8594 el.alignTo("other-el");
8596 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8597 el.alignTo("other-el", "tr?");
8599 // align the bottom right corner of el with the center left edge of other-el
8600 el.alignTo("other-el", "br-l?");
8602 // align the center of el with the bottom left corner of other-el and
8603 // adjust the x position by -6 pixels (and the y position by 0)
8604 el.alignTo("other-el", "c-bl", [-6, 0]);
8606 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8607 * @param {String} position The position to align to.
8608 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8609 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8610 * @return {Roo.Element} this
8612 alignTo : function(element, position, offsets, animate){
8613 var xy = this.getAlignToXY(element, position, offsets);
8614 this.setXY(xy, this.preanim(arguments, 3));
8619 * Anchors an element to another element and realigns it when the window is resized.
8620 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8621 * @param {String} position The position to align to.
8622 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8623 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8624 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8625 * is a number, it is used as the buffer delay (defaults to 50ms).
8626 * @param {Function} callback The function to call after the animation finishes
8627 * @return {Roo.Element} this
8629 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8630 var action = function(){
8631 this.alignTo(el, alignment, offsets, animate);
8632 Roo.callback(callback, this);
8634 Roo.EventManager.onWindowResize(action, this);
8635 var tm = typeof monitorScroll;
8636 if(tm != 'undefined'){
8637 Roo.EventManager.on(window, 'scroll', action, this,
8638 {buffer: tm == 'number' ? monitorScroll : 50});
8640 action.call(this); // align immediately
8644 * Clears any opacity settings from this element. Required in some cases for IE.
8645 * @return {Roo.Element} this
8647 clearOpacity : function(){
8648 if (window.ActiveXObject) {
8649 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8650 this.dom.style.filter = "";
8653 this.dom.style.opacity = "";
8654 this.dom.style["-moz-opacity"] = "";
8655 this.dom.style["-khtml-opacity"] = "";
8661 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8662 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8663 * @return {Roo.Element} this
8665 hide : function(animate){
8666 this.setVisible(false, this.preanim(arguments, 0));
8671 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8672 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8673 * @return {Roo.Element} this
8675 show : function(animate){
8676 this.setVisible(true, this.preanim(arguments, 0));
8681 * @private Test if size has a unit, otherwise appends the default
8683 addUnits : function(size){
8684 return Roo.Element.addUnits(size, this.defaultUnit);
8688 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8689 * @return {Roo.Element} this
8691 beginMeasure : function(){
8693 if(el.offsetWidth || el.offsetHeight){
8694 return this; // offsets work already
8697 var p = this.dom, b = document.body; // start with this element
8698 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8699 var pe = Roo.get(p);
8700 if(pe.getStyle('display') == 'none'){
8701 changed.push({el: p, visibility: pe.getStyle("visibility")});
8702 p.style.visibility = "hidden";
8703 p.style.display = "block";
8707 this._measureChanged = changed;
8713 * Restores displays to before beginMeasure was called
8714 * @return {Roo.Element} this
8716 endMeasure : function(){
8717 var changed = this._measureChanged;
8719 for(var i = 0, len = changed.length; i < len; i++) {
8721 r.el.style.visibility = r.visibility;
8722 r.el.style.display = "none";
8724 this._measureChanged = null;
8730 * Update the innerHTML of this element, optionally searching for and processing scripts
8731 * @param {String} html The new HTML
8732 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8733 * @param {Function} callback For async script loading you can be noticed when the update completes
8734 * @return {Roo.Element} this
8736 update : function(html, loadScripts, callback){
8737 if(typeof html == "undefined"){
8740 if(loadScripts !== true){
8741 this.dom.innerHTML = html;
8742 if(typeof callback == "function"){
8750 html += '<span id="' + id + '"></span>';
8752 E.onAvailable(id, function(){
8753 var hd = document.getElementsByTagName("head")[0];
8754 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8755 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8756 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8759 while(match = re.exec(html)){
8760 var attrs = match[1];
8761 var srcMatch = attrs ? attrs.match(srcRe) : false;
8762 if(srcMatch && srcMatch[2]){
8763 var s = document.createElement("script");
8764 s.src = srcMatch[2];
8765 var typeMatch = attrs.match(typeRe);
8766 if(typeMatch && typeMatch[2]){
8767 s.type = typeMatch[2];
8770 }else if(match[2] && match[2].length > 0){
8771 if(window.execScript) {
8772 window.execScript(match[2]);
8780 window.eval(match[2]);
8784 var el = document.getElementById(id);
8785 if(el){el.parentNode.removeChild(el);}
8786 if(typeof callback == "function"){
8790 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8795 * Direct access to the UpdateManager update() method (takes the same parameters).
8796 * @param {String/Function} url The url for this request or a function to call to get the url
8797 * @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}
8798 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8799 * @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.
8800 * @return {Roo.Element} this
8803 var um = this.getUpdateManager();
8804 um.update.apply(um, arguments);
8809 * Gets this element's UpdateManager
8810 * @return {Roo.UpdateManager} The UpdateManager
8812 getUpdateManager : function(){
8813 if(!this.updateManager){
8814 this.updateManager = new Roo.UpdateManager(this);
8816 return this.updateManager;
8820 * Disables text selection for this element (normalized across browsers)
8821 * @return {Roo.Element} this
8823 unselectable : function(){
8824 this.dom.unselectable = "on";
8825 this.swallowEvent("selectstart", true);
8826 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8827 this.addClass("x-unselectable");
8832 * Calculates the x, y to center this element on the screen
8833 * @return {Array} The x, y values [x, y]
8835 getCenterXY : function(){
8836 return this.getAlignToXY(document, 'c-c');
8840 * Centers the Element in either the viewport, or another Element.
8841 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8843 center : function(centerIn){
8844 this.alignTo(centerIn || document, 'c-c');
8849 * Tests various css rules/browsers to determine if this element uses a border box
8852 isBorderBox : function(){
8853 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8857 * Return a box {x, y, width, height} that can be used to set another elements
8858 * size/location to match this element.
8859 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8860 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8861 * @return {Object} box An object in the format {x, y, width, height}
8863 getBox : function(contentBox, local){
8868 var left = parseInt(this.getStyle("left"), 10) || 0;
8869 var top = parseInt(this.getStyle("top"), 10) || 0;
8872 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8874 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8876 var l = this.getBorderWidth("l")+this.getPadding("l");
8877 var r = this.getBorderWidth("r")+this.getPadding("r");
8878 var t = this.getBorderWidth("t")+this.getPadding("t");
8879 var b = this.getBorderWidth("b")+this.getPadding("b");
8880 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)};
8882 bx.right = bx.x + bx.width;
8883 bx.bottom = bx.y + bx.height;
8888 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8889 for more information about the sides.
8890 * @param {String} sides
8893 getFrameWidth : function(sides, onlyContentBox){
8894 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8898 * 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.
8899 * @param {Object} box The box to fill {x, y, width, height}
8900 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8901 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8902 * @return {Roo.Element} this
8904 setBox : function(box, adjust, animate){
8905 var w = box.width, h = box.height;
8906 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8907 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8908 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8910 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8915 * Forces the browser to repaint this element
8916 * @return {Roo.Element} this
8918 repaint : function(){
8920 this.addClass("x-repaint");
8921 setTimeout(function(){
8922 Roo.get(dom).removeClass("x-repaint");
8928 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8929 * then it returns the calculated width of the sides (see getPadding)
8930 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8931 * @return {Object/Number}
8933 getMargins : function(side){
8936 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8937 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8938 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8939 right: parseInt(this.getStyle("margin-right"), 10) || 0
8942 return this.addStyles(side, El.margins);
8947 addStyles : function(sides, styles){
8949 for(var i = 0, len = sides.length; i < len; i++){
8950 v = this.getStyle(styles[sides.charAt(i)]);
8952 w = parseInt(v, 10);
8960 * Creates a proxy element of this element
8961 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8962 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8963 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8964 * @return {Roo.Element} The new proxy element
8966 createProxy : function(config, renderTo, matchBox){
8968 renderTo = Roo.getDom(renderTo);
8970 renderTo = document.body;
8972 config = typeof config == "object" ?
8973 config : {tag : "div", cls: config};
8974 var proxy = Roo.DomHelper.append(renderTo, config, true);
8976 proxy.setBox(this.getBox());
8982 * Puts a mask over this element to disable user interaction. Requires core.css.
8983 * This method can only be applied to elements which accept child nodes.
8984 * @param {String} msg (optional) A message to display in the mask
8985 * @param {String} msgCls (optional) A css class to apply to the msg element
8986 * @return {Element} The mask element
8988 mask : function(msg, msgCls)
8990 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
8991 this.setStyle("position", "relative");
8994 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8996 this.addClass("x-masked");
8997 this._mask.setDisplayed(true);
9002 while (dom && dom.style) {
9003 if (!isNaN(parseInt(dom.style.zIndex))) {
9004 z = Math.max(z, parseInt(dom.style.zIndex));
9006 dom = dom.parentNode;
9008 // if we are masking the body - then it hides everything..
9009 if (this.dom == document.body) {
9011 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9012 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9015 if(typeof msg == 'string'){
9017 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9019 var mm = this._maskMsg;
9020 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9021 if (mm.dom.firstChild) { // weird IE issue?
9022 mm.dom.firstChild.innerHTML = msg;
9024 mm.setDisplayed(true);
9026 mm.setStyle('z-index', z + 102);
9028 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9029 this._mask.setHeight(this.getHeight());
9031 this._mask.setStyle('z-index', z + 100);
9037 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9038 * it is cached for reuse.
9040 unmask : function(removeEl){
9042 if(removeEl === true){
9043 this._mask.remove();
9046 this._maskMsg.remove();
9047 delete this._maskMsg;
9050 this._mask.setDisplayed(false);
9052 this._maskMsg.setDisplayed(false);
9056 this.removeClass("x-masked");
9060 * Returns true if this element is masked
9063 isMasked : function(){
9064 return this._mask && this._mask.isVisible();
9068 * Creates an iframe shim for this element to keep selects and other windowed objects from
9070 * @return {Roo.Element} The new shim element
9072 createShim : function(){
9073 var el = document.createElement('iframe');
9074 el.frameBorder = 'no';
9075 el.className = 'roo-shim';
9076 if(Roo.isIE && Roo.isSecure){
9077 el.src = Roo.SSL_SECURE_URL;
9079 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9080 shim.autoBoxAdjust = false;
9085 * Removes this element from the DOM and deletes it from the cache
9087 remove : function(){
9088 if(this.dom.parentNode){
9089 this.dom.parentNode.removeChild(this.dom);
9091 delete El.cache[this.dom.id];
9095 * Sets up event handlers to add and remove a css class when the mouse is over this element
9096 * @param {String} className
9097 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9098 * mouseout events for children elements
9099 * @return {Roo.Element} this
9101 addClassOnOver : function(className, preventFlicker){
9102 this.on("mouseover", function(){
9103 Roo.fly(this, '_internal').addClass(className);
9105 var removeFn = function(e){
9106 if(preventFlicker !== true || !e.within(this, true)){
9107 Roo.fly(this, '_internal').removeClass(className);
9110 this.on("mouseout", removeFn, this.dom);
9115 * Sets up event handlers to add and remove a css class when this element has the focus
9116 * @param {String} className
9117 * @return {Roo.Element} this
9119 addClassOnFocus : function(className){
9120 this.on("focus", function(){
9121 Roo.fly(this, '_internal').addClass(className);
9123 this.on("blur", function(){
9124 Roo.fly(this, '_internal').removeClass(className);
9129 * 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)
9130 * @param {String} className
9131 * @return {Roo.Element} this
9133 addClassOnClick : function(className){
9135 this.on("mousedown", function(){
9136 Roo.fly(dom, '_internal').addClass(className);
9137 var d = Roo.get(document);
9138 var fn = function(){
9139 Roo.fly(dom, '_internal').removeClass(className);
9140 d.removeListener("mouseup", fn);
9142 d.on("mouseup", fn);
9148 * Stops the specified event from bubbling and optionally prevents the default action
9149 * @param {String} eventName
9150 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9151 * @return {Roo.Element} this
9153 swallowEvent : function(eventName, preventDefault){
9154 var fn = function(e){
9155 e.stopPropagation();
9160 if(eventName instanceof Array){
9161 for(var i = 0, len = eventName.length; i < len; i++){
9162 this.on(eventName[i], fn);
9166 this.on(eventName, fn);
9173 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9176 * Sizes this element to its parent element's dimensions performing
9177 * neccessary box adjustments.
9178 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9179 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9180 * @return {Roo.Element} this
9182 fitToParent : function(monitorResize, targetParent) {
9183 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9184 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9185 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9188 var p = Roo.get(targetParent || this.dom.parentNode);
9189 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9190 if (monitorResize === true) {
9191 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9192 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9198 * Gets the next sibling, skipping text nodes
9199 * @return {HTMLElement} The next sibling or null
9201 getNextSibling : function(){
9202 var n = this.dom.nextSibling;
9203 while(n && n.nodeType != 1){
9210 * Gets the previous sibling, skipping text nodes
9211 * @return {HTMLElement} The previous sibling or null
9213 getPrevSibling : function(){
9214 var n = this.dom.previousSibling;
9215 while(n && n.nodeType != 1){
9216 n = n.previousSibling;
9223 * Appends the passed element(s) to this element
9224 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9225 * @return {Roo.Element} this
9227 appendChild: function(el){
9234 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9235 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9236 * automatically generated with the specified attributes.
9237 * @param {HTMLElement} insertBefore (optional) a child element of this element
9238 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9239 * @return {Roo.Element} The new child element
9241 createChild: function(config, insertBefore, returnDom){
9242 config = config || {tag:'div'};
9244 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9246 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9250 * Appends this element to the passed element
9251 * @param {String/HTMLElement/Element} el The new parent element
9252 * @return {Roo.Element} this
9254 appendTo: function(el){
9255 el = Roo.getDom(el);
9256 el.appendChild(this.dom);
9261 * Inserts this element before the passed element in the DOM
9262 * @param {String/HTMLElement/Element} el The element to insert before
9263 * @return {Roo.Element} this
9265 insertBefore: function(el){
9266 el = Roo.getDom(el);
9267 el.parentNode.insertBefore(this.dom, el);
9272 * Inserts this element after the passed element in the DOM
9273 * @param {String/HTMLElement/Element} el The element to insert after
9274 * @return {Roo.Element} this
9276 insertAfter: function(el){
9277 el = Roo.getDom(el);
9278 el.parentNode.insertBefore(this.dom, el.nextSibling);
9283 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9284 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9285 * @return {Roo.Element} The new child
9287 insertFirst: function(el, returnDom){
9289 if(typeof el == 'object' && !el.nodeType){ // dh config
9290 return this.createChild(el, this.dom.firstChild, returnDom);
9292 el = Roo.getDom(el);
9293 this.dom.insertBefore(el, this.dom.firstChild);
9294 return !returnDom ? Roo.get(el) : el;
9299 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9300 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9301 * @param {String} where (optional) 'before' or 'after' defaults to before
9302 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9303 * @return {Roo.Element} the inserted Element
9305 insertSibling: function(el, where, returnDom){
9306 where = where ? where.toLowerCase() : 'before';
9308 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9310 if(typeof el == 'object' && !el.nodeType){ // dh config
9311 if(where == 'after' && !this.dom.nextSibling){
9312 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9314 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9318 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9319 where == 'before' ? this.dom : this.dom.nextSibling);
9328 * Creates and wraps this element with another element
9329 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9330 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9331 * @return {HTMLElement/Element} The newly created wrapper element
9333 wrap: function(config, returnDom){
9335 config = {tag: "div"};
9337 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9338 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9343 * Replaces the passed element with this element
9344 * @param {String/HTMLElement/Element} el The element to replace
9345 * @return {Roo.Element} this
9347 replace: function(el){
9349 this.insertBefore(el);
9355 * Inserts an html fragment into this element
9356 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9357 * @param {String} html The HTML fragment
9358 * @param {Boolean} returnEl True to return an Roo.Element
9359 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9361 insertHtml : function(where, html, returnEl){
9362 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9363 return returnEl ? Roo.get(el) : el;
9367 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9368 * @param {Object} o The object with the attributes
9369 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9370 * @return {Roo.Element} this
9372 set : function(o, useSet){
9374 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9376 if(attr == "style" || typeof o[attr] == "function") continue;
9378 el.className = o["cls"];
9380 if(useSet) el.setAttribute(attr, o[attr]);
9381 else el[attr] = o[attr];
9385 Roo.DomHelper.applyStyles(el, o.style);
9391 * Convenience method for constructing a KeyMap
9392 * @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:
9393 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9394 * @param {Function} fn The function to call
9395 * @param {Object} scope (optional) The scope of the function
9396 * @return {Roo.KeyMap} The KeyMap created
9398 addKeyListener : function(key, fn, scope){
9400 if(typeof key != "object" || key instanceof Array){
9416 return new Roo.KeyMap(this, config);
9420 * Creates a KeyMap for this element
9421 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9422 * @return {Roo.KeyMap} The KeyMap created
9424 addKeyMap : function(config){
9425 return new Roo.KeyMap(this, config);
9429 * Returns true if this element is scrollable.
9432 isScrollable : function(){
9434 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9438 * 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().
9439 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9440 * @param {Number} value The new scroll value
9441 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9442 * @return {Element} this
9445 scrollTo : function(side, value, animate){
9446 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9448 this.dom[prop] = value;
9450 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9451 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9457 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9458 * within this element's scrollable range.
9459 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9460 * @param {Number} distance How far to scroll the element in pixels
9461 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9462 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9463 * was scrolled as far as it could go.
9465 scroll : function(direction, distance, animate){
9466 if(!this.isScrollable()){
9470 var l = el.scrollLeft, t = el.scrollTop;
9471 var w = el.scrollWidth, h = el.scrollHeight;
9472 var cw = el.clientWidth, ch = el.clientHeight;
9473 direction = direction.toLowerCase();
9474 var scrolled = false;
9475 var a = this.preanim(arguments, 2);
9480 var v = Math.min(l + distance, w-cw);
9481 this.scrollTo("left", v, a);
9488 var v = Math.max(l - distance, 0);
9489 this.scrollTo("left", v, a);
9497 var v = Math.max(t - distance, 0);
9498 this.scrollTo("top", v, a);
9506 var v = Math.min(t + distance, h-ch);
9507 this.scrollTo("top", v, a);
9516 * Translates the passed page coordinates into left/top css values for this element
9517 * @param {Number/Array} x The page x or an array containing [x, y]
9518 * @param {Number} y The page y
9519 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9521 translatePoints : function(x, y){
9522 if(typeof x == 'object' || x instanceof Array){
9525 var p = this.getStyle('position');
9526 var o = this.getXY();
9528 var l = parseInt(this.getStyle('left'), 10);
9529 var t = parseInt(this.getStyle('top'), 10);
9532 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9535 t = (p == "relative") ? 0 : this.dom.offsetTop;
9538 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9542 * Returns the current scroll position of the element.
9543 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9545 getScroll : function(){
9546 var d = this.dom, doc = document;
9547 if(d == doc || d == doc.body){
9548 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9549 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9550 return {left: l, top: t};
9552 return {left: d.scrollLeft, top: d.scrollTop};
9557 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9558 * are convert to standard 6 digit hex color.
9559 * @param {String} attr The css attribute
9560 * @param {String} defaultValue The default value to use when a valid color isn't found
9561 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9564 getColor : function(attr, defaultValue, prefix){
9565 var v = this.getStyle(attr);
9566 if(!v || v == "transparent" || v == "inherit") {
9567 return defaultValue;
9569 var color = typeof prefix == "undefined" ? "#" : prefix;
9570 if(v.substr(0, 4) == "rgb("){
9571 var rvs = v.slice(4, v.length -1).split(",");
9572 for(var i = 0; i < 3; i++){
9573 var h = parseInt(rvs[i]).toString(16);
9580 if(v.substr(0, 1) == "#"){
9582 for(var i = 1; i < 4; i++){
9583 var c = v.charAt(i);
9586 }else if(v.length == 7){
9587 color += v.substr(1);
9591 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9595 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9596 * gradient background, rounded corners and a 4-way shadow.
9597 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9598 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9599 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9600 * @return {Roo.Element} this
9602 boxWrap : function(cls){
9603 cls = cls || 'x-box';
9604 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9605 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9610 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9611 * @param {String} namespace The namespace in which to look for the attribute
9612 * @param {String} name The attribute name
9613 * @return {String} The attribute value
9615 getAttributeNS : Roo.isIE ? function(ns, name){
9617 var type = typeof d[ns+":"+name];
9618 if(type != 'undefined' && type != 'unknown'){
9619 return d[ns+":"+name];
9622 } : function(ns, name){
9624 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9629 * Sets or Returns the value the dom attribute value
9630 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9631 * @param {String} value (optional) The value to set the attribute to
9632 * @return {String} The attribute value
9634 attr : function(name){
9635 if (arguments.length > 1) {
9636 this.dom.setAttribute(name, arguments[1]);
9637 return arguments[1];
9639 if (typeof(name) == 'object') {
9640 for(var i in name) {
9641 this.attr(i, name[i]);
9647 if (!this.dom.hasAttribute(name)) {
9650 return this.dom.getAttribute(name);
9657 var ep = El.prototype;
9660 * Appends an event handler (Shorthand for addListener)
9661 * @param {String} eventName The type of event to append
9662 * @param {Function} fn The method the event invokes
9663 * @param {Object} scope (optional) The scope (this object) of the fn
9664 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9667 ep.on = ep.addListener;
9669 ep.mon = ep.addListener;
9672 * Removes an event handler from this element (shorthand for removeListener)
9673 * @param {String} eventName the type of event to remove
9674 * @param {Function} fn the method the event invokes
9675 * @return {Roo.Element} this
9678 ep.un = ep.removeListener;
9681 * true to automatically adjust width and height settings for box-model issues (default to true)
9683 ep.autoBoxAdjust = true;
9686 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9689 El.addUnits = function(v, defaultUnit){
9690 if(v === "" || v == "auto"){
9693 if(v === undefined){
9696 if(typeof v == "number" || !El.unitPattern.test(v)){
9697 return v + (defaultUnit || 'px');
9702 // special markup used throughout Roo when box wrapping elements
9703 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>';
9705 * Visibility mode constant - Use visibility to hide element
9711 * Visibility mode constant - Use display to hide element
9717 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9718 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9719 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9731 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9732 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9733 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9734 * @return {Element} The Element object
9737 El.get = function(el){
9739 if(!el){ return null; }
9740 if(typeof el == "string"){ // element id
9741 if(!(elm = document.getElementById(el))){
9744 if(ex = El.cache[el]){
9747 ex = El.cache[el] = new El(elm);
9750 }else if(el.tagName){ // dom element
9754 if(ex = El.cache[id]){
9757 ex = El.cache[id] = new El(el);
9760 }else if(el instanceof El){
9762 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9763 // catch case where it hasn't been appended
9764 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9767 }else if(el.isComposite){
9769 }else if(el instanceof Array){
9770 return El.select(el);
9771 }else if(el == document){
9772 // create a bogus element object representing the document object
9774 var f = function(){};
9775 f.prototype = El.prototype;
9777 docEl.dom = document;
9785 El.uncache = function(el){
9786 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9788 delete El.cache[a[i].id || a[i]];
9794 // Garbage collection - uncache elements/purge listeners on orphaned elements
9795 // so we don't hold a reference and cause the browser to retain them
9796 El.garbageCollect = function(){
9797 if(!Roo.enableGarbageCollector){
9798 clearInterval(El.collectorThread);
9801 for(var eid in El.cache){
9802 var el = El.cache[eid], d = el.dom;
9803 // -------------------------------------------------------
9804 // Determining what is garbage:
9805 // -------------------------------------------------------
9807 // dom node is null, definitely garbage
9808 // -------------------------------------------------------
9810 // no parentNode == direct orphan, definitely garbage
9811 // -------------------------------------------------------
9812 // !d.offsetParent && !document.getElementById(eid)
9813 // display none elements have no offsetParent so we will
9814 // also try to look it up by it's id. However, check
9815 // offsetParent first so we don't do unneeded lookups.
9816 // This enables collection of elements that are not orphans
9817 // directly, but somewhere up the line they have an orphan
9819 // -------------------------------------------------------
9820 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9821 delete El.cache[eid];
9822 if(d && Roo.enableListenerCollection){
9828 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9832 El.Flyweight = function(dom){
9835 El.Flyweight.prototype = El.prototype;
9837 El._flyweights = {};
9839 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9840 * the dom node can be overwritten by other code.
9841 * @param {String/HTMLElement} el The dom node or id
9842 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9843 * prevent conflicts (e.g. internally Roo uses "_internal")
9845 * @return {Element} The shared Element object
9847 El.fly = function(el, named){
9848 named = named || '_global';
9849 el = Roo.getDom(el);
9853 if(!El._flyweights[named]){
9854 El._flyweights[named] = new El.Flyweight();
9856 El._flyweights[named].dom = el;
9857 return El._flyweights[named];
9861 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9862 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9863 * Shorthand of {@link Roo.Element#get}
9864 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9865 * @return {Element} The Element object
9871 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9872 * the dom node can be overwritten by other code.
9873 * Shorthand of {@link Roo.Element#fly}
9874 * @param {String/HTMLElement} el The dom node or id
9875 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9876 * prevent conflicts (e.g. internally Roo uses "_internal")
9878 * @return {Element} The shared Element object
9884 // speedy lookup for elements never to box adjust
9885 var noBoxAdjust = Roo.isStrict ? {
9888 input:1, select:1, textarea:1
9890 if(Roo.isIE || Roo.isGecko){
9891 noBoxAdjust['button'] = 1;
9895 Roo.EventManager.on(window, 'unload', function(){
9897 delete El._flyweights;
9905 Roo.Element.selectorFunction = Roo.DomQuery.select;
9908 Roo.Element.select = function(selector, unique, root){
9910 if(typeof selector == "string"){
9911 els = Roo.Element.selectorFunction(selector, root);
9912 }else if(selector.length !== undefined){
9915 throw "Invalid selector";
9917 if(unique === true){
9918 return new Roo.CompositeElement(els);
9920 return new Roo.CompositeElementLite(els);
9924 * Selects elements based on the passed CSS selector to enable working on them as 1.
9925 * @param {String/Array} selector The CSS selector or an array of elements
9926 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9927 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9928 * @return {CompositeElementLite/CompositeElement}
9932 Roo.select = Roo.Element.select;
9949 * Ext JS Library 1.1.1
9950 * Copyright(c) 2006-2007, Ext JS, LLC.
9952 * Originally Released Under LGPL - original licence link has changed is not relivant.
9955 * <script type="text/javascript">
9960 //Notifies Element that fx methods are available
9961 Roo.enableFx = true;
9965 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9966 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9967 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9968 * Element effects to work.</p><br/>
9970 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9971 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9972 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9973 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9974 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9975 * expected results and should be done with care.</p><br/>
9977 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9978 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9981 ----- -----------------------------
9982 tl The top left corner
9983 t The center of the top edge
9984 tr The top right corner
9985 l The center of the left edge
9986 r The center of the right edge
9987 bl The bottom left corner
9988 b The center of the bottom edge
9989 br The bottom right corner
9991 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9992 * below are common options that can be passed to any Fx method.</b>
9993 * @cfg {Function} callback A function called when the effect is finished
9994 * @cfg {Object} scope The scope of the effect function
9995 * @cfg {String} easing A valid Easing value for the effect
9996 * @cfg {String} afterCls A css class to apply after the effect
9997 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9998 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9999 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
10000 * effects that end with the element being visually hidden, ignored otherwise)
10001 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
10002 * a function which returns such a specification that will be applied to the Element after the effect finishes
10003 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
10004 * @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
10005 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10009 * Slides the element into view. An anchor point can be optionally passed to set the point of
10010 * origin for the slide effect. This function automatically handles wrapping the element with
10011 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10014 // default: slide the element in from the top
10017 // custom: slide the element in from the right with a 2-second duration
10018 el.slideIn('r', { duration: 2 });
10020 // common config options shown with default values
10026 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10027 * @param {Object} options (optional) Object literal with any of the Fx config options
10028 * @return {Roo.Element} The Element
10030 slideIn : function(anchor, o){
10031 var el = this.getFxEl();
10034 el.queueFx(o, function(){
10036 anchor = anchor || "t";
10038 // fix display to visibility
10041 // restore values after effect
10042 var r = this.getFxRestore();
10043 var b = this.getBox();
10044 // fixed size for slide
10048 var wrap = this.fxWrap(r.pos, o, "hidden");
10050 var st = this.dom.style;
10051 st.visibility = "visible";
10052 st.position = "absolute";
10054 // clear out temp styles after slide and unwrap
10055 var after = function(){
10056 el.fxUnwrap(wrap, r.pos, o);
10057 st.width = r.width;
10058 st.height = r.height;
10061 // time to calc the positions
10062 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10064 switch(anchor.toLowerCase()){
10066 wrap.setSize(b.width, 0);
10067 st.left = st.bottom = "0";
10071 wrap.setSize(0, b.height);
10072 st.right = st.top = "0";
10076 wrap.setSize(0, b.height);
10077 wrap.setX(b.right);
10078 st.left = st.top = "0";
10079 a = {width: bw, points: pt};
10082 wrap.setSize(b.width, 0);
10083 wrap.setY(b.bottom);
10084 st.left = st.top = "0";
10085 a = {height: bh, points: pt};
10088 wrap.setSize(0, 0);
10089 st.right = st.bottom = "0";
10090 a = {width: bw, height: bh};
10093 wrap.setSize(0, 0);
10094 wrap.setY(b.y+b.height);
10095 st.right = st.top = "0";
10096 a = {width: bw, height: bh, points: pt};
10099 wrap.setSize(0, 0);
10100 wrap.setXY([b.right, b.bottom]);
10101 st.left = st.top = "0";
10102 a = {width: bw, height: bh, points: pt};
10105 wrap.setSize(0, 0);
10106 wrap.setX(b.x+b.width);
10107 st.left = st.bottom = "0";
10108 a = {width: bw, height: bh, points: pt};
10111 this.dom.style.visibility = "visible";
10114 arguments.callee.anim = wrap.fxanim(a,
10124 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10125 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10126 * 'hidden') but block elements will still take up space in the document. The element must be removed
10127 * from the DOM using the 'remove' config option if desired. This function automatically handles
10128 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10131 // default: slide the element out to the top
10134 // custom: slide the element out to the right with a 2-second duration
10135 el.slideOut('r', { duration: 2 });
10137 // common config options shown with default values
10145 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10146 * @param {Object} options (optional) Object literal with any of the Fx config options
10147 * @return {Roo.Element} The Element
10149 slideOut : function(anchor, o){
10150 var el = this.getFxEl();
10153 el.queueFx(o, function(){
10155 anchor = anchor || "t";
10157 // restore values after effect
10158 var r = this.getFxRestore();
10160 var b = this.getBox();
10161 // fixed size for slide
10165 var wrap = this.fxWrap(r.pos, o, "visible");
10167 var st = this.dom.style;
10168 st.visibility = "visible";
10169 st.position = "absolute";
10173 var after = function(){
10175 el.setDisplayed(false);
10180 el.fxUnwrap(wrap, r.pos, o);
10182 st.width = r.width;
10183 st.height = r.height;
10188 var a, zero = {to: 0};
10189 switch(anchor.toLowerCase()){
10191 st.left = st.bottom = "0";
10192 a = {height: zero};
10195 st.right = st.top = "0";
10199 st.left = st.top = "0";
10200 a = {width: zero, points: {to:[b.right, b.y]}};
10203 st.left = st.top = "0";
10204 a = {height: zero, points: {to:[b.x, b.bottom]}};
10207 st.right = st.bottom = "0";
10208 a = {width: zero, height: zero};
10211 st.right = st.top = "0";
10212 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10215 st.left = st.top = "0";
10216 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10219 st.left = st.bottom = "0";
10220 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10224 arguments.callee.anim = wrap.fxanim(a,
10234 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10235 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10236 * The element must be removed from the DOM using the 'remove' config option if desired.
10242 // common config options shown with default values
10250 * @param {Object} options (optional) Object literal with any of the Fx config options
10251 * @return {Roo.Element} The Element
10253 puff : function(o){
10254 var el = this.getFxEl();
10257 el.queueFx(o, function(){
10258 this.clearOpacity();
10261 // restore values after effect
10262 var r = this.getFxRestore();
10263 var st = this.dom.style;
10265 var after = function(){
10267 el.setDisplayed(false);
10274 el.setPositioning(r.pos);
10275 st.width = r.width;
10276 st.height = r.height;
10281 var width = this.getWidth();
10282 var height = this.getHeight();
10284 arguments.callee.anim = this.fxanim({
10285 width : {to: this.adjustWidth(width * 2)},
10286 height : {to: this.adjustHeight(height * 2)},
10287 points : {by: [-(width * .5), -(height * .5)]},
10289 fontSize: {to:200, unit: "%"}
10300 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10301 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10302 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10308 // all config options shown with default values
10316 * @param {Object} options (optional) Object literal with any of the Fx config options
10317 * @return {Roo.Element} The Element
10319 switchOff : function(o){
10320 var el = this.getFxEl();
10323 el.queueFx(o, function(){
10324 this.clearOpacity();
10327 // restore values after effect
10328 var r = this.getFxRestore();
10329 var st = this.dom.style;
10331 var after = function(){
10333 el.setDisplayed(false);
10339 el.setPositioning(r.pos);
10340 st.width = r.width;
10341 st.height = r.height;
10346 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10347 this.clearOpacity();
10351 points:{by:[0, this.getHeight() * .5]}
10352 }, o, 'motion', 0.3, 'easeIn', after);
10353 }).defer(100, this);
10360 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10361 * changed using the "attr" config option) and then fading back to the original color. If no original
10362 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10365 // default: highlight background to yellow
10368 // custom: highlight foreground text to blue for 2 seconds
10369 el.highlight("0000ff", { attr: 'color', duration: 2 });
10371 // common config options shown with default values
10372 el.highlight("ffff9c", {
10373 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10374 endColor: (current color) or "ffffff",
10379 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10380 * @param {Object} options (optional) Object literal with any of the Fx config options
10381 * @return {Roo.Element} The Element
10383 highlight : function(color, o){
10384 var el = this.getFxEl();
10387 el.queueFx(o, function(){
10388 color = color || "ffff9c";
10389 attr = o.attr || "backgroundColor";
10391 this.clearOpacity();
10394 var origColor = this.getColor(attr);
10395 var restoreColor = this.dom.style[attr];
10396 endColor = (o.endColor || origColor) || "ffffff";
10398 var after = function(){
10399 el.dom.style[attr] = restoreColor;
10404 a[attr] = {from: color, to: endColor};
10405 arguments.callee.anim = this.fxanim(a,
10415 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10418 // default: a single light blue ripple
10421 // custom: 3 red ripples lasting 3 seconds total
10422 el.frame("ff0000", 3, { duration: 3 });
10424 // common config options shown with default values
10425 el.frame("C3DAF9", 1, {
10426 duration: 1 //duration of entire animation (not each individual ripple)
10427 // Note: Easing is not configurable and will be ignored if included
10430 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10431 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10432 * @param {Object} options (optional) Object literal with any of the Fx config options
10433 * @return {Roo.Element} The Element
10435 frame : function(color, count, o){
10436 var el = this.getFxEl();
10439 el.queueFx(o, function(){
10440 color = color || "#C3DAF9";
10441 if(color.length == 6){
10442 color = "#" + color;
10444 count = count || 1;
10445 duration = o.duration || 1;
10448 var b = this.getBox();
10449 var animFn = function(){
10450 var proxy = this.createProxy({
10453 visbility:"hidden",
10454 position:"absolute",
10455 "z-index":"35000", // yee haw
10456 border:"0px solid " + color
10459 var scale = Roo.isBorderBox ? 2 : 1;
10461 top:{from:b.y, to:b.y - 20},
10462 left:{from:b.x, to:b.x - 20},
10463 borderWidth:{from:0, to:10},
10464 opacity:{from:1, to:0},
10465 height:{from:b.height, to:(b.height + (20*scale))},
10466 width:{from:b.width, to:(b.width + (20*scale))}
10467 }, duration, function(){
10471 animFn.defer((duration/2)*1000, this);
10482 * Creates a pause before any subsequent queued effects begin. If there are
10483 * no effects queued after the pause it will have no effect.
10488 * @param {Number} seconds The length of time to pause (in seconds)
10489 * @return {Roo.Element} The Element
10491 pause : function(seconds){
10492 var el = this.getFxEl();
10495 el.queueFx(o, function(){
10496 setTimeout(function(){
10498 }, seconds * 1000);
10504 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10505 * using the "endOpacity" config option.
10508 // default: fade in from opacity 0 to 100%
10511 // custom: fade in from opacity 0 to 75% over 2 seconds
10512 el.fadeIn({ endOpacity: .75, duration: 2});
10514 // common config options shown with default values
10516 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10521 * @param {Object} options (optional) Object literal with any of the Fx config options
10522 * @return {Roo.Element} The Element
10524 fadeIn : function(o){
10525 var el = this.getFxEl();
10527 el.queueFx(o, function(){
10528 this.setOpacity(0);
10530 this.dom.style.visibility = 'visible';
10531 var to = o.endOpacity || 1;
10532 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10533 o, null, .5, "easeOut", function(){
10535 this.clearOpacity();
10544 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10545 * using the "endOpacity" config option.
10548 // default: fade out from the element's current opacity to 0
10551 // custom: fade out from the element's current opacity to 25% over 2 seconds
10552 el.fadeOut({ endOpacity: .25, duration: 2});
10554 // common config options shown with default values
10556 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10563 * @param {Object} options (optional) Object literal with any of the Fx config options
10564 * @return {Roo.Element} The Element
10566 fadeOut : function(o){
10567 var el = this.getFxEl();
10569 el.queueFx(o, function(){
10570 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10571 o, null, .5, "easeOut", function(){
10572 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10573 this.dom.style.display = "none";
10575 this.dom.style.visibility = "hidden";
10577 this.clearOpacity();
10585 * Animates the transition of an element's dimensions from a starting height/width
10586 * to an ending height/width.
10589 // change height and width to 100x100 pixels
10590 el.scale(100, 100);
10592 // common config options shown with default values. The height and width will default to
10593 // the element's existing values if passed as null.
10596 [element's height], {
10601 * @param {Number} width The new width (pass undefined to keep the original width)
10602 * @param {Number} height The new height (pass undefined to keep the original height)
10603 * @param {Object} options (optional) Object literal with any of the Fx config options
10604 * @return {Roo.Element} The Element
10606 scale : function(w, h, o){
10607 this.shift(Roo.apply({}, o, {
10615 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10616 * Any of these properties not specified in the config object will not be changed. This effect
10617 * requires that at least one new dimension, position or opacity setting must be passed in on
10618 * the config object in order for the function to have any effect.
10621 // slide the element horizontally to x position 200 while changing the height and opacity
10622 el.shift({ x: 200, height: 50, opacity: .8 });
10624 // common config options shown with default values.
10626 width: [element's width],
10627 height: [element's height],
10628 x: [element's x position],
10629 y: [element's y position],
10630 opacity: [element's opacity],
10635 * @param {Object} options Object literal with any of the Fx config options
10636 * @return {Roo.Element} The Element
10638 shift : function(o){
10639 var el = this.getFxEl();
10641 el.queueFx(o, function(){
10642 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10643 if(w !== undefined){
10644 a.width = {to: this.adjustWidth(w)};
10646 if(h !== undefined){
10647 a.height = {to: this.adjustHeight(h)};
10649 if(x !== undefined || y !== undefined){
10651 x !== undefined ? x : this.getX(),
10652 y !== undefined ? y : this.getY()
10655 if(op !== undefined){
10656 a.opacity = {to: op};
10658 if(o.xy !== undefined){
10659 a.points = {to: o.xy};
10661 arguments.callee.anim = this.fxanim(a,
10662 o, 'motion', .35, "easeOut", function(){
10670 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10671 * ending point of the effect.
10674 // default: slide the element downward while fading out
10677 // custom: slide the element out to the right with a 2-second duration
10678 el.ghost('r', { duration: 2 });
10680 // common config options shown with default values
10688 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10689 * @param {Object} options (optional) Object literal with any of the Fx config options
10690 * @return {Roo.Element} The Element
10692 ghost : function(anchor, o){
10693 var el = this.getFxEl();
10696 el.queueFx(o, function(){
10697 anchor = anchor || "b";
10699 // restore values after effect
10700 var r = this.getFxRestore();
10701 var w = this.getWidth(),
10702 h = this.getHeight();
10704 var st = this.dom.style;
10706 var after = function(){
10708 el.setDisplayed(false);
10714 el.setPositioning(r.pos);
10715 st.width = r.width;
10716 st.height = r.height;
10721 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10722 switch(anchor.toLowerCase()){
10749 arguments.callee.anim = this.fxanim(a,
10759 * Ensures that all effects queued after syncFx is called on the element are
10760 * run concurrently. This is the opposite of {@link #sequenceFx}.
10761 * @return {Roo.Element} The Element
10763 syncFx : function(){
10764 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10773 * Ensures that all effects queued after sequenceFx is called on the element are
10774 * run in sequence. This is the opposite of {@link #syncFx}.
10775 * @return {Roo.Element} The Element
10777 sequenceFx : function(){
10778 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10780 concurrent : false,
10787 nextFx : function(){
10788 var ef = this.fxQueue[0];
10795 * Returns true if the element has any effects actively running or queued, else returns false.
10796 * @return {Boolean} True if element has active effects, else false
10798 hasActiveFx : function(){
10799 return this.fxQueue && this.fxQueue[0];
10803 * Stops any running effects and clears the element's internal effects queue if it contains
10804 * any additional effects that haven't started yet.
10805 * @return {Roo.Element} The Element
10807 stopFx : function(){
10808 if(this.hasActiveFx()){
10809 var cur = this.fxQueue[0];
10810 if(cur && cur.anim && cur.anim.isAnimated()){
10811 this.fxQueue = [cur]; // clear out others
10812 cur.anim.stop(true);
10819 beforeFx : function(o){
10820 if(this.hasActiveFx() && !o.concurrent){
10831 * Returns true if the element is currently blocking so that no other effect can be queued
10832 * until this effect is finished, else returns false if blocking is not set. This is commonly
10833 * used to ensure that an effect initiated by a user action runs to completion prior to the
10834 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10835 * @return {Boolean} True if blocking, else false
10837 hasFxBlock : function(){
10838 var q = this.fxQueue;
10839 return q && q[0] && q[0].block;
10843 queueFx : function(o, fn){
10847 if(!this.hasFxBlock()){
10848 Roo.applyIf(o, this.fxDefaults);
10850 var run = this.beforeFx(o);
10851 fn.block = o.block;
10852 this.fxQueue.push(fn);
10864 fxWrap : function(pos, o, vis){
10866 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10869 wrapXY = this.getXY();
10871 var div = document.createElement("div");
10872 div.style.visibility = vis;
10873 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10874 wrap.setPositioning(pos);
10875 if(wrap.getStyle("position") == "static"){
10876 wrap.position("relative");
10878 this.clearPositioning('auto');
10880 wrap.dom.appendChild(this.dom);
10882 wrap.setXY(wrapXY);
10889 fxUnwrap : function(wrap, pos, o){
10890 this.clearPositioning();
10891 this.setPositioning(pos);
10893 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10899 getFxRestore : function(){
10900 var st = this.dom.style;
10901 return {pos: this.getPositioning(), width: st.width, height : st.height};
10905 afterFx : function(o){
10907 this.applyStyles(o.afterStyle);
10910 this.addClass(o.afterCls);
10912 if(o.remove === true){
10915 Roo.callback(o.callback, o.scope, [this]);
10917 this.fxQueue.shift();
10923 getFxEl : function(){ // support for composite element fx
10924 return Roo.get(this.dom);
10928 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10929 animType = animType || 'run';
10931 var anim = Roo.lib.Anim[animType](
10933 (opt.duration || defaultDur) || .35,
10934 (opt.easing || defaultEase) || 'easeOut',
10936 Roo.callback(cb, this);
10945 // backwords compat
10946 Roo.Fx.resize = Roo.Fx.scale;
10948 //When included, Roo.Fx is automatically applied to Element so that all basic
10949 //effects are available directly via the Element API
10950 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10952 * Ext JS Library 1.1.1
10953 * Copyright(c) 2006-2007, Ext JS, LLC.
10955 * Originally Released Under LGPL - original licence link has changed is not relivant.
10958 * <script type="text/javascript">
10963 * @class Roo.CompositeElement
10964 * Standard composite class. Creates a Roo.Element for every element in the collection.
10966 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10967 * actions will be performed on all the elements in this collection.</b>
10969 * All methods return <i>this</i> and can be chained.
10971 var els = Roo.select("#some-el div.some-class", true);
10972 // or select directly from an existing element
10973 var el = Roo.get('some-el');
10974 el.select('div.some-class', true);
10976 els.setWidth(100); // all elements become 100 width
10977 els.hide(true); // all elements fade out and hide
10979 els.setWidth(100).hide(true);
10982 Roo.CompositeElement = function(els){
10983 this.elements = [];
10984 this.addElements(els);
10986 Roo.CompositeElement.prototype = {
10988 addElements : function(els){
10989 if(!els) return this;
10990 if(typeof els == "string"){
10991 els = Roo.Element.selectorFunction(els);
10993 var yels = this.elements;
10994 var index = yels.length-1;
10995 for(var i = 0, len = els.length; i < len; i++) {
10996 yels[++index] = Roo.get(els[i]);
11002 * Clears this composite and adds the elements returned by the passed selector.
11003 * @param {String/Array} els A string CSS selector, an array of elements or an element
11004 * @return {CompositeElement} this
11006 fill : function(els){
11007 this.elements = [];
11013 * Filters this composite to only elements that match the passed selector.
11014 * @param {String} selector A string CSS selector
11015 * @param {Boolean} inverse return inverse filter (not matches)
11016 * @return {CompositeElement} this
11018 filter : function(selector, inverse){
11020 inverse = inverse || false;
11021 this.each(function(el){
11022 var match = inverse ? !el.is(selector) : el.is(selector);
11024 els[els.length] = el.dom;
11031 invoke : function(fn, args){
11032 var els = this.elements;
11033 for(var i = 0, len = els.length; i < len; i++) {
11034 Roo.Element.prototype[fn].apply(els[i], args);
11039 * Adds elements to this composite.
11040 * @param {String/Array} els A string CSS selector, an array of elements or an element
11041 * @return {CompositeElement} this
11043 add : function(els){
11044 if(typeof els == "string"){
11045 this.addElements(Roo.Element.selectorFunction(els));
11046 }else if(els.length !== undefined){
11047 this.addElements(els);
11049 this.addElements([els]);
11054 * Calls the passed function passing (el, this, index) for each element in this composite.
11055 * @param {Function} fn The function to call
11056 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11057 * @return {CompositeElement} this
11059 each : function(fn, scope){
11060 var els = this.elements;
11061 for(var i = 0, len = els.length; i < len; i++){
11062 if(fn.call(scope || els[i], els[i], this, i) === false) {
11070 * Returns the Element object at the specified index
11071 * @param {Number} index
11072 * @return {Roo.Element}
11074 item : function(index){
11075 return this.elements[index] || null;
11079 * Returns the first Element
11080 * @return {Roo.Element}
11082 first : function(){
11083 return this.item(0);
11087 * Returns the last Element
11088 * @return {Roo.Element}
11091 return this.item(this.elements.length-1);
11095 * Returns the number of elements in this composite
11098 getCount : function(){
11099 return this.elements.length;
11103 * Returns true if this composite contains the passed element
11106 contains : function(el){
11107 return this.indexOf(el) !== -1;
11111 * Returns true if this composite contains the passed element
11114 indexOf : function(el){
11115 return this.elements.indexOf(Roo.get(el));
11120 * Removes the specified element(s).
11121 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11122 * or an array of any of those.
11123 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11124 * @return {CompositeElement} this
11126 removeElement : function(el, removeDom){
11127 if(el instanceof Array){
11128 for(var i = 0, len = el.length; i < len; i++){
11129 this.removeElement(el[i]);
11133 var index = typeof el == 'number' ? el : this.indexOf(el);
11136 var d = this.elements[index];
11140 d.parentNode.removeChild(d);
11143 this.elements.splice(index, 1);
11149 * Replaces the specified element with the passed element.
11150 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11152 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11153 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11154 * @return {CompositeElement} this
11156 replaceElement : function(el, replacement, domReplace){
11157 var index = typeof el == 'number' ? el : this.indexOf(el);
11160 this.elements[index].replaceWith(replacement);
11162 this.elements.splice(index, 1, Roo.get(replacement))
11169 * Removes all elements.
11171 clear : function(){
11172 this.elements = [];
11176 Roo.CompositeElement.createCall = function(proto, fnName){
11177 if(!proto[fnName]){
11178 proto[fnName] = function(){
11179 return this.invoke(fnName, arguments);
11183 for(var fnName in Roo.Element.prototype){
11184 if(typeof Roo.Element.prototype[fnName] == "function"){
11185 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11191 * Ext JS Library 1.1.1
11192 * Copyright(c) 2006-2007, Ext JS, LLC.
11194 * Originally Released Under LGPL - original licence link has changed is not relivant.
11197 * <script type="text/javascript">
11201 * @class Roo.CompositeElementLite
11202 * @extends Roo.CompositeElement
11203 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11205 var els = Roo.select("#some-el div.some-class");
11206 // or select directly from an existing element
11207 var el = Roo.get('some-el');
11208 el.select('div.some-class');
11210 els.setWidth(100); // all elements become 100 width
11211 els.hide(true); // all elements fade out and hide
11213 els.setWidth(100).hide(true);
11214 </code></pre><br><br>
11215 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11216 * actions will be performed on all the elements in this collection.</b>
11218 Roo.CompositeElementLite = function(els){
11219 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11220 this.el = new Roo.Element.Flyweight();
11222 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11223 addElements : function(els){
11225 if(els instanceof Array){
11226 this.elements = this.elements.concat(els);
11228 var yels = this.elements;
11229 var index = yels.length-1;
11230 for(var i = 0, len = els.length; i < len; i++) {
11231 yels[++index] = els[i];
11237 invoke : function(fn, args){
11238 var els = this.elements;
11240 for(var i = 0, len = els.length; i < len; i++) {
11242 Roo.Element.prototype[fn].apply(el, args);
11247 * Returns a flyweight Element of the dom element object at the specified index
11248 * @param {Number} index
11249 * @return {Roo.Element}
11251 item : function(index){
11252 if(!this.elements[index]){
11255 this.el.dom = this.elements[index];
11259 // fixes scope with flyweight
11260 addListener : function(eventName, handler, scope, opt){
11261 var els = this.elements;
11262 for(var i = 0, len = els.length; i < len; i++) {
11263 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11269 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11270 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11271 * a reference to the dom node, use el.dom.</b>
11272 * @param {Function} fn The function to call
11273 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11274 * @return {CompositeElement} this
11276 each : function(fn, scope){
11277 var els = this.elements;
11279 for(var i = 0, len = els.length; i < len; i++){
11281 if(fn.call(scope || el, el, this, i) === false){
11288 indexOf : function(el){
11289 return this.elements.indexOf(Roo.getDom(el));
11292 replaceElement : function(el, replacement, domReplace){
11293 var index = typeof el == 'number' ? el : this.indexOf(el);
11295 replacement = Roo.getDom(replacement);
11297 var d = this.elements[index];
11298 d.parentNode.insertBefore(replacement, d);
11299 d.parentNode.removeChild(d);
11301 this.elements.splice(index, 1, replacement);
11306 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11310 * Ext JS Library 1.1.1
11311 * Copyright(c) 2006-2007, Ext JS, LLC.
11313 * Originally Released Under LGPL - original licence link has changed is not relivant.
11316 * <script type="text/javascript">
11322 * @class Roo.data.Connection
11323 * @extends Roo.util.Observable
11324 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11325 * either to a configured URL, or to a URL specified at request time.<br><br>
11327 * Requests made by this class are asynchronous, and will return immediately. No data from
11328 * the server will be available to the statement immediately following the {@link #request} call.
11329 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11331 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11332 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11333 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11334 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11335 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11336 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11337 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11338 * standard DOM methods.
11340 * @param {Object} config a configuration object.
11342 Roo.data.Connection = function(config){
11343 Roo.apply(this, config);
11346 * @event beforerequest
11347 * Fires before a network request is made to retrieve a data object.
11348 * @param {Connection} conn This Connection object.
11349 * @param {Object} options The options config object passed to the {@link #request} method.
11351 "beforerequest" : true,
11353 * @event requestcomplete
11354 * Fires if the request was successfully completed.
11355 * @param {Connection} conn This Connection object.
11356 * @param {Object} response The XHR object containing the response data.
11357 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11358 * @param {Object} options The options config object passed to the {@link #request} method.
11360 "requestcomplete" : true,
11362 * @event requestexception
11363 * Fires if an error HTTP status was returned from the server.
11364 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11365 * @param {Connection} conn This Connection object.
11366 * @param {Object} response The XHR object containing the response data.
11367 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11368 * @param {Object} options The options config object passed to the {@link #request} method.
11370 "requestexception" : true
11372 Roo.data.Connection.superclass.constructor.call(this);
11375 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11377 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11380 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11381 * extra parameters to each request made by this object. (defaults to undefined)
11384 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11385 * to each request made by this object. (defaults to undefined)
11388 * @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)
11391 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11395 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11401 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11404 disableCaching: true,
11407 * Sends an HTTP request to a remote server.
11408 * @param {Object} options An object which may contain the following properties:<ul>
11409 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11410 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11411 * request, a url encoded string or a function to call to get either.</li>
11412 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11413 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11414 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11415 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11416 * <li>options {Object} The parameter to the request call.</li>
11417 * <li>success {Boolean} True if the request succeeded.</li>
11418 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11420 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11421 * The callback is passed the following parameters:<ul>
11422 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11423 * <li>options {Object} The parameter to the request call.</li>
11425 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11426 * The callback is passed the following parameters:<ul>
11427 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11428 * <li>options {Object} The parameter to the request call.</li>
11430 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11431 * for the callback function. Defaults to the browser window.</li>
11432 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11433 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11434 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11435 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11436 * params for the post data. Any params will be appended to the URL.</li>
11437 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11439 * @return {Number} transactionId
11441 request : function(o){
11442 if(this.fireEvent("beforerequest", this, o) !== false){
11445 if(typeof p == "function"){
11446 p = p.call(o.scope||window, o);
11448 if(typeof p == "object"){
11449 p = Roo.urlEncode(o.params);
11451 if(this.extraParams){
11452 var extras = Roo.urlEncode(this.extraParams);
11453 p = p ? (p + '&' + extras) : extras;
11456 var url = o.url || this.url;
11457 if(typeof url == 'function'){
11458 url = url.call(o.scope||window, o);
11462 var form = Roo.getDom(o.form);
11463 url = url || form.action;
11465 var enctype = form.getAttribute("enctype");
11466 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11467 return this.doFormUpload(o, p, url);
11469 var f = Roo.lib.Ajax.serializeForm(form);
11470 p = p ? (p + '&' + f) : f;
11473 var hs = o.headers;
11474 if(this.defaultHeaders){
11475 hs = Roo.apply(hs || {}, this.defaultHeaders);
11482 success: this.handleResponse,
11483 failure: this.handleFailure,
11485 argument: {options: o},
11486 timeout : o.timeout || this.timeout
11489 var method = o.method||this.method||(p ? "POST" : "GET");
11491 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11492 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11495 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11499 }else if(this.autoAbort !== false){
11503 if((method == 'GET' && p) || o.xmlData){
11504 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11507 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11508 return this.transId;
11510 Roo.callback(o.callback, o.scope, [o, null, null]);
11516 * Determine whether this object has a request outstanding.
11517 * @param {Number} transactionId (Optional) defaults to the last transaction
11518 * @return {Boolean} True if there is an outstanding request.
11520 isLoading : function(transId){
11522 return Roo.lib.Ajax.isCallInProgress(transId);
11524 return this.transId ? true : false;
11529 * Aborts any outstanding request.
11530 * @param {Number} transactionId (Optional) defaults to the last transaction
11532 abort : function(transId){
11533 if(transId || this.isLoading()){
11534 Roo.lib.Ajax.abort(transId || this.transId);
11539 handleResponse : function(response){
11540 this.transId = false;
11541 var options = response.argument.options;
11542 response.argument = options ? options.argument : null;
11543 this.fireEvent("requestcomplete", this, response, options);
11544 Roo.callback(options.success, options.scope, [response, options]);
11545 Roo.callback(options.callback, options.scope, [options, true, response]);
11549 handleFailure : function(response, e){
11550 this.transId = false;
11551 var options = response.argument.options;
11552 response.argument = options ? options.argument : null;
11553 this.fireEvent("requestexception", this, response, options, e);
11554 Roo.callback(options.failure, options.scope, [response, options]);
11555 Roo.callback(options.callback, options.scope, [options, false, response]);
11559 doFormUpload : function(o, ps, url){
11561 var frame = document.createElement('iframe');
11564 frame.className = 'x-hidden';
11566 frame.src = Roo.SSL_SECURE_URL;
11568 document.body.appendChild(frame);
11571 document.frames[id].name = id;
11574 var form = Roo.getDom(o.form);
11576 form.method = 'POST';
11577 form.enctype = form.encoding = 'multipart/form-data';
11583 if(ps){ // add dynamic params
11585 ps = Roo.urlDecode(ps, false);
11587 if(ps.hasOwnProperty(k)){
11588 hd = document.createElement('input');
11589 hd.type = 'hidden';
11592 form.appendChild(hd);
11599 var r = { // bogus response object
11604 r.argument = o ? o.argument : null;
11609 doc = frame.contentWindow.document;
11611 doc = (frame.contentDocument || window.frames[id].document);
11613 if(doc && doc.body){
11614 r.responseText = doc.body.innerHTML;
11616 if(doc && doc.XMLDocument){
11617 r.responseXML = doc.XMLDocument;
11619 r.responseXML = doc;
11626 Roo.EventManager.removeListener(frame, 'load', cb, this);
11628 this.fireEvent("requestcomplete", this, r, o);
11629 Roo.callback(o.success, o.scope, [r, o]);
11630 Roo.callback(o.callback, o.scope, [o, true, r]);
11632 setTimeout(function(){document.body.removeChild(frame);}, 100);
11635 Roo.EventManager.on(frame, 'load', cb, this);
11638 if(hiddens){ // remove dynamic params
11639 for(var i = 0, len = hiddens.length; i < len; i++){
11640 form.removeChild(hiddens[i]);
11647 * Ext JS Library 1.1.1
11648 * Copyright(c) 2006-2007, Ext JS, LLC.
11650 * Originally Released Under LGPL - original licence link has changed is not relivant.
11653 * <script type="text/javascript">
11657 * Global Ajax request class.
11660 * @extends Roo.data.Connection
11663 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11664 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11665 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11666 * @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)
11667 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11668 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11669 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11671 Roo.Ajax = new Roo.data.Connection({
11680 * Serialize the passed form into a url encoded string
11682 * @param {String/HTMLElement} form
11685 serializeForm : function(form){
11686 return Roo.lib.Ajax.serializeForm(form);
11690 * Ext JS Library 1.1.1
11691 * Copyright(c) 2006-2007, Ext JS, LLC.
11693 * Originally Released Under LGPL - original licence link has changed is not relivant.
11696 * <script type="text/javascript">
11701 * @class Roo.UpdateManager
11702 * @extends Roo.util.Observable
11703 * Provides AJAX-style update for Element object.<br><br>
11706 * // Get it from a Roo.Element object
11707 * var el = Roo.get("foo");
11708 * var mgr = el.getUpdateManager();
11709 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11711 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11713 * // or directly (returns the same UpdateManager instance)
11714 * var mgr = new Roo.UpdateManager("myElementId");
11715 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11716 * mgr.on("update", myFcnNeedsToKnow);
11718 // short handed call directly from the element object
11719 Roo.get("foo").load({
11723 text: "Loading Foo..."
11727 * Create new UpdateManager directly.
11728 * @param {String/HTMLElement/Roo.Element} el The element to update
11729 * @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).
11731 Roo.UpdateManager = function(el, forceNew){
11733 if(!forceNew && el.updateManager){
11734 return el.updateManager;
11737 * The Element object
11738 * @type Roo.Element
11742 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11745 this.defaultUrl = null;
11749 * @event beforeupdate
11750 * Fired before an update is made, return false from your handler and the update is cancelled.
11751 * @param {Roo.Element} el
11752 * @param {String/Object/Function} url
11753 * @param {String/Object} params
11755 "beforeupdate": true,
11758 * Fired after successful update is made.
11759 * @param {Roo.Element} el
11760 * @param {Object} oResponseObject The response Object
11765 * Fired on update failure.
11766 * @param {Roo.Element} el
11767 * @param {Object} oResponseObject The response Object
11771 var d = Roo.UpdateManager.defaults;
11773 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11776 this.sslBlankUrl = d.sslBlankUrl;
11778 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11781 this.disableCaching = d.disableCaching;
11783 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11786 this.indicatorText = d.indicatorText;
11788 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11791 this.showLoadIndicator = d.showLoadIndicator;
11793 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11796 this.timeout = d.timeout;
11799 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11802 this.loadScripts = d.loadScripts;
11805 * Transaction object of current executing transaction
11807 this.transaction = null;
11812 this.autoRefreshProcId = null;
11814 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11817 this.refreshDelegate = this.refresh.createDelegate(this);
11819 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11822 this.updateDelegate = this.update.createDelegate(this);
11824 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11827 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11831 this.successDelegate = this.processSuccess.createDelegate(this);
11835 this.failureDelegate = this.processFailure.createDelegate(this);
11837 if(!this.renderer){
11839 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11841 this.renderer = new Roo.UpdateManager.BasicRenderer();
11844 Roo.UpdateManager.superclass.constructor.call(this);
11847 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11849 * Get the Element this UpdateManager is bound to
11850 * @return {Roo.Element} The element
11852 getEl : function(){
11856 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11857 * @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:
11860 url: "your-url.php",<br/>
11861 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11862 callback: yourFunction,<br/>
11863 scope: yourObject, //(optional scope) <br/>
11864 discardUrl: false, <br/>
11865 nocache: false,<br/>
11866 text: "Loading...",<br/>
11868 scripts: false<br/>
11871 * The only required property is url. The optional properties nocache, text and scripts
11872 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11873 * @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}
11874 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11875 * @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.
11877 update : function(url, params, callback, discardUrl){
11878 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11879 var method = this.method,
11881 if(typeof url == "object"){ // must be config object
11884 params = params || cfg.params;
11885 callback = callback || cfg.callback;
11886 discardUrl = discardUrl || cfg.discardUrl;
11887 if(callback && cfg.scope){
11888 callback = callback.createDelegate(cfg.scope);
11890 if(typeof cfg.method != "undefined"){method = cfg.method;};
11891 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11892 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11893 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11894 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11896 this.showLoading();
11898 this.defaultUrl = url;
11900 if(typeof url == "function"){
11901 url = url.call(this);
11904 method = method || (params ? "POST" : "GET");
11905 if(method == "GET"){
11906 url = this.prepareUrl(url);
11909 var o = Roo.apply(cfg ||{}, {
11912 success: this.successDelegate,
11913 failure: this.failureDelegate,
11914 callback: undefined,
11915 timeout: (this.timeout*1000),
11916 argument: {"url": url, "form": null, "callback": callback, "params": params}
11918 Roo.log("updated manager called with timeout of " + o.timeout);
11919 this.transaction = Roo.Ajax.request(o);
11924 * 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.
11925 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11926 * @param {String/HTMLElement} form The form Id or form element
11927 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11928 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11929 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11931 formUpdate : function(form, url, reset, callback){
11932 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11933 if(typeof url == "function"){
11934 url = url.call(this);
11936 form = Roo.getDom(form);
11937 this.transaction = Roo.Ajax.request({
11940 success: this.successDelegate,
11941 failure: this.failureDelegate,
11942 timeout: (this.timeout*1000),
11943 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11945 this.showLoading.defer(1, this);
11950 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11951 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11953 refresh : function(callback){
11954 if(this.defaultUrl == null){
11957 this.update(this.defaultUrl, null, callback, true);
11961 * Set this element to auto refresh.
11962 * @param {Number} interval How often to update (in seconds).
11963 * @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)
11964 * @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}
11965 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11966 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11968 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11970 this.update(url || this.defaultUrl, params, callback, true);
11972 if(this.autoRefreshProcId){
11973 clearInterval(this.autoRefreshProcId);
11975 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11979 * Stop auto refresh on this element.
11981 stopAutoRefresh : function(){
11982 if(this.autoRefreshProcId){
11983 clearInterval(this.autoRefreshProcId);
11984 delete this.autoRefreshProcId;
11988 isAutoRefreshing : function(){
11989 return this.autoRefreshProcId ? true : false;
11992 * Called to update the element to "Loading" state. Override to perform custom action.
11994 showLoading : function(){
11995 if(this.showLoadIndicator){
11996 this.el.update(this.indicatorText);
12001 * Adds unique parameter to query string if disableCaching = true
12004 prepareUrl : function(url){
12005 if(this.disableCaching){
12006 var append = "_dc=" + (new Date().getTime());
12007 if(url.indexOf("?") !== -1){
12008 url += "&" + append;
12010 url += "?" + append;
12019 processSuccess : function(response){
12020 this.transaction = null;
12021 if(response.argument.form && response.argument.reset){
12022 try{ // put in try/catch since some older FF releases had problems with this
12023 response.argument.form.reset();
12026 if(this.loadScripts){
12027 this.renderer.render(this.el, response, this,
12028 this.updateComplete.createDelegate(this, [response]));
12030 this.renderer.render(this.el, response, this);
12031 this.updateComplete(response);
12035 updateComplete : function(response){
12036 this.fireEvent("update", this.el, response);
12037 if(typeof response.argument.callback == "function"){
12038 response.argument.callback(this.el, true, response);
12045 processFailure : function(response){
12046 this.transaction = null;
12047 this.fireEvent("failure", this.el, response);
12048 if(typeof response.argument.callback == "function"){
12049 response.argument.callback(this.el, false, response);
12054 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12055 * @param {Object} renderer The object implementing the render() method
12057 setRenderer : function(renderer){
12058 this.renderer = renderer;
12061 getRenderer : function(){
12062 return this.renderer;
12066 * Set the defaultUrl used for updates
12067 * @param {String/Function} defaultUrl The url or a function to call to get the url
12069 setDefaultUrl : function(defaultUrl){
12070 this.defaultUrl = defaultUrl;
12074 * Aborts the executing transaction
12076 abort : function(){
12077 if(this.transaction){
12078 Roo.Ajax.abort(this.transaction);
12083 * Returns true if an update is in progress
12084 * @return {Boolean}
12086 isUpdating : function(){
12087 if(this.transaction){
12088 return Roo.Ajax.isLoading(this.transaction);
12095 * @class Roo.UpdateManager.defaults
12096 * @static (not really - but it helps the doc tool)
12097 * The defaults collection enables customizing the default properties of UpdateManager
12099 Roo.UpdateManager.defaults = {
12101 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12107 * True to process scripts by default (Defaults to false).
12110 loadScripts : false,
12113 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12116 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12118 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12121 disableCaching : false,
12123 * Whether to show indicatorText when loading (Defaults to true).
12126 showLoadIndicator : true,
12128 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12131 indicatorText : '<div class="loading-indicator">Loading...</div>'
12135 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12137 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12138 * @param {String/HTMLElement/Roo.Element} el The element to update
12139 * @param {String} url The url
12140 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12141 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12144 * @member Roo.UpdateManager
12146 Roo.UpdateManager.updateElement = function(el, url, params, options){
12147 var um = Roo.get(el, true).getUpdateManager();
12148 Roo.apply(um, options);
12149 um.update(url, params, options ? options.callback : null);
12151 // alias for backwards compat
12152 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12154 * @class Roo.UpdateManager.BasicRenderer
12155 * Default Content renderer. Updates the elements innerHTML with the responseText.
12157 Roo.UpdateManager.BasicRenderer = function(){};
12159 Roo.UpdateManager.BasicRenderer.prototype = {
12161 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12162 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12163 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12164 * @param {Roo.Element} el The element being rendered
12165 * @param {Object} response The YUI Connect response object
12166 * @param {UpdateManager} updateManager The calling update manager
12167 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12169 render : function(el, response, updateManager, callback){
12170 el.update(response.responseText, updateManager.loadScripts, callback);
12176 * (c)) Alan Knowles
12182 * @class Roo.DomTemplate
12183 * @extends Roo.Template
12184 * An effort at a dom based template engine..
12186 * Similar to XTemplate, except it uses dom parsing to create the template..
12188 * Supported features:
12193 {a_variable} - output encoded.
12194 {a_variable.format:("Y-m-d")} - call a method on the variable
12195 {a_variable:raw} - unencoded output
12196 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12197 {a_variable:this.method_on_template(...)} - call a method on the template object.
12202 <div roo-for="a_variable or condition.."></div>
12203 <div roo-if="a_variable or condition"></div>
12204 <div roo-exec="some javascript"></div>
12205 <div roo-name="named_template"></div>
12210 Roo.DomTemplate = function()
12212 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12219 Roo.extend(Roo.DomTemplate, Roo.Template, {
12221 * id counter for sub templates.
12225 * flag to indicate if dom parser is inside a pre,
12226 * it will strip whitespace if not.
12231 * The various sub templates
12239 * basic tag replacing syntax
12242 * // you can fake an object call by doing this
12246 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12247 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12249 iterChild : function (node, method) {
12251 var oldPre = this.inPre;
12252 if (node.tagName == 'PRE') {
12255 for( var i = 0; i < node.childNodes.length; i++) {
12256 method.call(this, node.childNodes[i]);
12258 this.inPre = oldPre;
12264 * compile the template
12266 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12269 compile: function()
12273 // covert the html into DOM...
12277 doc = document.implementation.createHTMLDocument("");
12278 doc.documentElement.innerHTML = this.html ;
12279 div = doc.documentElement;
12281 // old IE... - nasty -- it causes all sorts of issues.. with
12282 // images getting pulled from server..
12283 div = document.createElement('div');
12284 div.innerHTML = this.html;
12286 //doc.documentElement.innerHTML = htmlBody
12292 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12294 var tpls = this.tpls;
12296 // create a top level template from the snippet..
12298 //Roo.log(div.innerHTML);
12305 body : div.innerHTML,
12318 Roo.each(tpls, function(tp){
12319 this.compileTpl(tp);
12320 this.tpls[tp.id] = tp;
12323 this.master = tpls[0];
12329 compileNode : function(node, istop) {
12334 // skip anything not a tag..
12335 if (node.nodeType != 1) {
12336 if (node.nodeType == 3 && !this.inPre) {
12337 // reduce white space..
12338 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12361 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12362 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12363 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12364 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12370 // just itterate children..
12371 this.iterChild(node,this.compileNode);
12374 tpl.uid = this.id++;
12375 tpl.value = node.getAttribute('roo-' + tpl.attr);
12376 node.removeAttribute('roo-'+ tpl.attr);
12377 if (tpl.attr != 'name') {
12378 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12379 node.parentNode.replaceChild(placeholder, node);
12382 var placeholder = document.createElement('span');
12383 placeholder.className = 'roo-tpl-' + tpl.value;
12384 node.parentNode.replaceChild(placeholder, node);
12387 // parent now sees '{domtplXXXX}
12388 this.iterChild(node,this.compileNode);
12390 // we should now have node body...
12391 var div = document.createElement('div');
12392 div.appendChild(node);
12394 // this has the unfortunate side effect of converting tagged attributes
12395 // eg. href="{...}" into %7C...%7D
12396 // this has been fixed by searching for those combo's although it's a bit hacky..
12399 tpl.body = div.innerHTML;
12406 switch (tpl.value) {
12407 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12408 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12409 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12414 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12418 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12422 tpl.id = tpl.value; // replace non characters???
12428 this.tpls.push(tpl);
12438 * Compile a segment of the template into a 'sub-template'
12444 compileTpl : function(tpl)
12446 var fm = Roo.util.Format;
12447 var useF = this.disableFormats !== true;
12449 var sep = Roo.isGecko ? "+\n" : ",\n";
12451 var undef = function(str) {
12452 Roo.debug && Roo.log("Property not found :" + str);
12456 //Roo.log(tpl.body);
12460 var fn = function(m, lbrace, name, format, args)
12463 //Roo.log(arguments);
12464 args = args ? args.replace(/\\'/g,"'") : args;
12465 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12466 if (typeof(format) == 'undefined') {
12467 format = 'htmlEncode';
12469 if (format == 'raw' ) {
12473 if(name.substr(0, 6) == 'domtpl'){
12474 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12477 // build an array of options to determine if value is undefined..
12479 // basically get 'xxxx.yyyy' then do
12480 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12481 // (function () { Roo.log("Property not found"); return ''; })() :
12486 Roo.each(name.split('.'), function(st) {
12487 lookfor += (lookfor.length ? '.': '') + st;
12488 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12491 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12494 if(format && useF){
12496 args = args ? ',' + args : "";
12498 if(format.substr(0, 5) != "this."){
12499 format = "fm." + format + '(';
12501 format = 'this.call("'+ format.substr(5) + '", ';
12505 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12508 if (args && args.length) {
12509 // called with xxyx.yuu:(test,test)
12511 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12513 // raw.. - :raw modifier..
12514 return "'"+ sep + udef_st + name + ")"+sep+"'";
12518 // branched to use + in gecko and [].join() in others
12520 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12521 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12524 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12525 body.push(tpl.body.replace(/(\r\n|\n)/g,
12526 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12527 body.push("'].join('');};};");
12528 body = body.join('');
12531 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12533 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12540 * same as applyTemplate, except it's done to one of the subTemplates
12541 * when using named templates, you can do:
12543 * var str = pl.applySubTemplate('your-name', values);
12546 * @param {Number} id of the template
12547 * @param {Object} values to apply to template
12548 * @param {Object} parent (normaly the instance of this object)
12550 applySubTemplate : function(id, values, parent)
12554 var t = this.tpls[id];
12558 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12559 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12563 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12570 if(t.execCall && t.execCall.call(this, values, parent)){
12574 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12580 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12581 parent = t.target ? values : parent;
12582 if(t.forCall && vs instanceof Array){
12584 for(var i = 0, len = vs.length; i < len; i++){
12586 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12588 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12590 //Roo.log(t.compiled);
12594 return buf.join('');
12597 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12602 return t.compiled.call(this, vs, parent);
12604 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12606 //Roo.log(t.compiled);
12614 applyTemplate : function(values){
12615 return this.master.compiled.call(this, values, {});
12616 //var s = this.subs;
12619 apply : function(){
12620 return this.applyTemplate.apply(this, arguments);
12625 Roo.DomTemplate.from = function(el){
12626 el = Roo.getDom(el);
12627 return new Roo.Domtemplate(el.value || el.innerHTML);
12630 * Ext JS Library 1.1.1
12631 * Copyright(c) 2006-2007, Ext JS, LLC.
12633 * Originally Released Under LGPL - original licence link has changed is not relivant.
12636 * <script type="text/javascript">
12640 * @class Roo.util.DelayedTask
12641 * Provides a convenient method of performing setTimeout where a new
12642 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12643 * You can use this class to buffer
12644 * the keypress events for a certain number of milliseconds, and perform only if they stop
12645 * for that amount of time.
12646 * @constructor The parameters to this constructor serve as defaults and are not required.
12647 * @param {Function} fn (optional) The default function to timeout
12648 * @param {Object} scope (optional) The default scope of that timeout
12649 * @param {Array} args (optional) The default Array of arguments
12651 Roo.util.DelayedTask = function(fn, scope, args){
12652 var id = null, d, t;
12654 var call = function(){
12655 var now = new Date().getTime();
12659 fn.apply(scope, args || []);
12663 * Cancels any pending timeout and queues a new one
12664 * @param {Number} delay The milliseconds to delay
12665 * @param {Function} newFn (optional) Overrides function passed to constructor
12666 * @param {Object} newScope (optional) Overrides scope passed to constructor
12667 * @param {Array} newArgs (optional) Overrides args passed to constructor
12669 this.delay = function(delay, newFn, newScope, newArgs){
12670 if(id && delay != d){
12674 t = new Date().getTime();
12676 scope = newScope || scope;
12677 args = newArgs || args;
12679 id = setInterval(call, d);
12684 * Cancel the last queued timeout
12686 this.cancel = function(){
12694 * Ext JS Library 1.1.1
12695 * Copyright(c) 2006-2007, Ext JS, LLC.
12697 * Originally Released Under LGPL - original licence link has changed is not relivant.
12700 * <script type="text/javascript">
12704 Roo.util.TaskRunner = function(interval){
12705 interval = interval || 10;
12706 var tasks = [], removeQueue = [];
12708 var running = false;
12710 var stopThread = function(){
12716 var startThread = function(){
12719 id = setInterval(runTasks, interval);
12723 var removeTask = function(task){
12724 removeQueue.push(task);
12730 var runTasks = function(){
12731 if(removeQueue.length > 0){
12732 for(var i = 0, len = removeQueue.length; i < len; i++){
12733 tasks.remove(removeQueue[i]);
12736 if(tasks.length < 1){
12741 var now = new Date().getTime();
12742 for(var i = 0, len = tasks.length; i < len; ++i){
12744 var itime = now - t.taskRunTime;
12745 if(t.interval <= itime){
12746 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12747 t.taskRunTime = now;
12748 if(rt === false || t.taskRunCount === t.repeat){
12753 if(t.duration && t.duration <= (now - t.taskStartTime)){
12760 * Queues a new task.
12761 * @param {Object} task
12763 this.start = function(task){
12765 task.taskStartTime = new Date().getTime();
12766 task.taskRunTime = 0;
12767 task.taskRunCount = 0;
12772 this.stop = function(task){
12777 this.stopAll = function(){
12779 for(var i = 0, len = tasks.length; i < len; i++){
12780 if(tasks[i].onStop){
12789 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12791 * Ext JS Library 1.1.1
12792 * Copyright(c) 2006-2007, Ext JS, LLC.
12794 * Originally Released Under LGPL - original licence link has changed is not relivant.
12797 * <script type="text/javascript">
12802 * @class Roo.util.MixedCollection
12803 * @extends Roo.util.Observable
12804 * A Collection class that maintains both numeric indexes and keys and exposes events.
12806 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12807 * collection (defaults to false)
12808 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12809 * and return the key value for that item. This is used when available to look up the key on items that
12810 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12811 * equivalent to providing an implementation for the {@link #getKey} method.
12813 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12821 * Fires when the collection is cleared.
12826 * Fires when an item is added to the collection.
12827 * @param {Number} index The index at which the item was added.
12828 * @param {Object} o The item added.
12829 * @param {String} key The key associated with the added item.
12834 * Fires when an item is replaced in the collection.
12835 * @param {String} key he key associated with the new added.
12836 * @param {Object} old The item being replaced.
12837 * @param {Object} new The new item.
12842 * Fires when an item is removed from the collection.
12843 * @param {Object} o The item being removed.
12844 * @param {String} key (optional) The key associated with the removed item.
12849 this.allowFunctions = allowFunctions === true;
12851 this.getKey = keyFn;
12853 Roo.util.MixedCollection.superclass.constructor.call(this);
12856 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12857 allowFunctions : false,
12860 * Adds an item to the collection.
12861 * @param {String} key The key to associate with the item
12862 * @param {Object} o The item to add.
12863 * @return {Object} The item added.
12865 add : function(key, o){
12866 if(arguments.length == 1){
12868 key = this.getKey(o);
12873 if(typeof key == "undefined" || key === null){
12875 this.items.push(o);
12876 this.keys.push(null);
12878 var old = this.map[key];
12880 return this.replace(key, o);
12883 this.items.push(o);
12885 this.keys.push(key);
12887 this.fireEvent("add", this.length-1, o, key);
12892 * MixedCollection has a generic way to fetch keys if you implement getKey.
12895 var mc = new Roo.util.MixedCollection();
12896 mc.add(someEl.dom.id, someEl);
12897 mc.add(otherEl.dom.id, otherEl);
12901 var mc = new Roo.util.MixedCollection();
12902 mc.getKey = function(el){
12908 // or via the constructor
12909 var mc = new Roo.util.MixedCollection(false, function(el){
12915 * @param o {Object} The item for which to find the key.
12916 * @return {Object} The key for the passed item.
12918 getKey : function(o){
12923 * Replaces an item in the collection.
12924 * @param {String} key The key associated with the item to replace, or the item to replace.
12925 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12926 * @return {Object} The new item.
12928 replace : function(key, o){
12929 if(arguments.length == 1){
12931 key = this.getKey(o);
12933 var old = this.item(key);
12934 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12935 return this.add(key, o);
12937 var index = this.indexOfKey(key);
12938 this.items[index] = o;
12940 this.fireEvent("replace", key, old, o);
12945 * Adds all elements of an Array or an Object to the collection.
12946 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12947 * an Array of values, each of which are added to the collection.
12949 addAll : function(objs){
12950 if(arguments.length > 1 || objs instanceof Array){
12951 var args = arguments.length > 1 ? arguments : objs;
12952 for(var i = 0, len = args.length; i < len; i++){
12956 for(var key in objs){
12957 if(this.allowFunctions || typeof objs[key] != "function"){
12958 this.add(key, objs[key]);
12965 * Executes the specified function once for every item in the collection, passing each
12966 * item as the first and only parameter. returning false from the function will stop the iteration.
12967 * @param {Function} fn The function to execute for each item.
12968 * @param {Object} scope (optional) The scope in which to execute the function.
12970 each : function(fn, scope){
12971 var items = [].concat(this.items); // each safe for removal
12972 for(var i = 0, len = items.length; i < len; i++){
12973 if(fn.call(scope || items[i], items[i], i, len) === false){
12980 * Executes the specified function once for every key in the collection, passing each
12981 * key, and its associated item as the first two parameters.
12982 * @param {Function} fn The function to execute for each item.
12983 * @param {Object} scope (optional) The scope in which to execute the function.
12985 eachKey : function(fn, scope){
12986 for(var i = 0, len = this.keys.length; i < len; i++){
12987 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12992 * Returns the first item in the collection which elicits a true return value from the
12993 * passed selection function.
12994 * @param {Function} fn The selection function to execute for each item.
12995 * @param {Object} scope (optional) The scope in which to execute the function.
12996 * @return {Object} The first item in the collection which returned true from the selection function.
12998 find : function(fn, scope){
12999 for(var i = 0, len = this.items.length; i < len; i++){
13000 if(fn.call(scope || window, this.items[i], this.keys[i])){
13001 return this.items[i];
13008 * Inserts an item at the specified index in the collection.
13009 * @param {Number} index The index to insert the item at.
13010 * @param {String} key The key to associate with the new item, or the item itself.
13011 * @param {Object} o (optional) If the second parameter was a key, the new item.
13012 * @return {Object} The item inserted.
13014 insert : function(index, key, o){
13015 if(arguments.length == 2){
13017 key = this.getKey(o);
13019 if(index >= this.length){
13020 return this.add(key, o);
13023 this.items.splice(index, 0, o);
13024 if(typeof key != "undefined" && key != null){
13027 this.keys.splice(index, 0, key);
13028 this.fireEvent("add", index, o, key);
13033 * Removed an item from the collection.
13034 * @param {Object} o The item to remove.
13035 * @return {Object} The item removed.
13037 remove : function(o){
13038 return this.removeAt(this.indexOf(o));
13042 * Remove an item from a specified index in the collection.
13043 * @param {Number} index The index within the collection of the item to remove.
13045 removeAt : function(index){
13046 if(index < this.length && index >= 0){
13048 var o = this.items[index];
13049 this.items.splice(index, 1);
13050 var key = this.keys[index];
13051 if(typeof key != "undefined"){
13052 delete this.map[key];
13054 this.keys.splice(index, 1);
13055 this.fireEvent("remove", o, key);
13060 * Removed an item associated with the passed key fom the collection.
13061 * @param {String} key The key of the item to remove.
13063 removeKey : function(key){
13064 return this.removeAt(this.indexOfKey(key));
13068 * Returns the number of items in the collection.
13069 * @return {Number} the number of items in the collection.
13071 getCount : function(){
13072 return this.length;
13076 * Returns index within the collection of the passed Object.
13077 * @param {Object} o The item to find the index of.
13078 * @return {Number} index of the item.
13080 indexOf : function(o){
13081 if(!this.items.indexOf){
13082 for(var i = 0, len = this.items.length; i < len; i++){
13083 if(this.items[i] == o) return i;
13087 return this.items.indexOf(o);
13092 * Returns index within the collection of the passed key.
13093 * @param {String} key The key to find the index of.
13094 * @return {Number} index of the key.
13096 indexOfKey : function(key){
13097 if(!this.keys.indexOf){
13098 for(var i = 0, len = this.keys.length; i < len; i++){
13099 if(this.keys[i] == key) return i;
13103 return this.keys.indexOf(key);
13108 * Returns the item associated with the passed key OR index. Key has priority over index.
13109 * @param {String/Number} key The key or index of the item.
13110 * @return {Object} The item associated with the passed key.
13112 item : function(key){
13113 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13114 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13118 * Returns the item at the specified index.
13119 * @param {Number} index The index of the item.
13122 itemAt : function(index){
13123 return this.items[index];
13127 * Returns the item associated with the passed key.
13128 * @param {String/Number} key The key of the item.
13129 * @return {Object} The item associated with the passed key.
13131 key : function(key){
13132 return this.map[key];
13136 * Returns true if the collection contains the passed Object as an item.
13137 * @param {Object} o The Object to look for in the collection.
13138 * @return {Boolean} True if the collection contains the Object as an item.
13140 contains : function(o){
13141 return this.indexOf(o) != -1;
13145 * Returns true if the collection contains the passed Object as a key.
13146 * @param {String} key The key to look for in the collection.
13147 * @return {Boolean} True if the collection contains the Object as a key.
13149 containsKey : function(key){
13150 return typeof this.map[key] != "undefined";
13154 * Removes all items from the collection.
13156 clear : function(){
13161 this.fireEvent("clear");
13165 * Returns the first item in the collection.
13166 * @return {Object} the first item in the collection..
13168 first : function(){
13169 return this.items[0];
13173 * Returns the last item in the collection.
13174 * @return {Object} the last item in the collection..
13177 return this.items[this.length-1];
13180 _sort : function(property, dir, fn){
13181 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13182 fn = fn || function(a, b){
13185 var c = [], k = this.keys, items = this.items;
13186 for(var i = 0, len = items.length; i < len; i++){
13187 c[c.length] = {key: k[i], value: items[i], index: i};
13189 c.sort(function(a, b){
13190 var v = fn(a[property], b[property]) * dsc;
13192 v = (a.index < b.index ? -1 : 1);
13196 for(var i = 0, len = c.length; i < len; i++){
13197 items[i] = c[i].value;
13200 this.fireEvent("sort", this);
13204 * Sorts this collection with the passed comparison function
13205 * @param {String} direction (optional) "ASC" or "DESC"
13206 * @param {Function} fn (optional) comparison function
13208 sort : function(dir, fn){
13209 this._sort("value", dir, fn);
13213 * Sorts this collection by keys
13214 * @param {String} direction (optional) "ASC" or "DESC"
13215 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13217 keySort : function(dir, fn){
13218 this._sort("key", dir, fn || function(a, b){
13219 return String(a).toUpperCase()-String(b).toUpperCase();
13224 * Returns a range of items in this collection
13225 * @param {Number} startIndex (optional) defaults to 0
13226 * @param {Number} endIndex (optional) default to the last item
13227 * @return {Array} An array of items
13229 getRange : function(start, end){
13230 var items = this.items;
13231 if(items.length < 1){
13234 start = start || 0;
13235 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13238 for(var i = start; i <= end; i++) {
13239 r[r.length] = items[i];
13242 for(var i = start; i >= end; i--) {
13243 r[r.length] = items[i];
13250 * Filter the <i>objects</i> in this collection by a specific property.
13251 * Returns a new collection that has been filtered.
13252 * @param {String} property A property on your objects
13253 * @param {String/RegExp} value Either string that the property values
13254 * should start with or a RegExp to test against the property
13255 * @return {MixedCollection} The new filtered collection
13257 filter : function(property, value){
13258 if(!value.exec){ // not a regex
13259 value = String(value);
13260 if(value.length == 0){
13261 return this.clone();
13263 value = new RegExp("^" + Roo.escapeRe(value), "i");
13265 return this.filterBy(function(o){
13266 return o && value.test(o[property]);
13271 * Filter by a function. * Returns a new collection that has been filtered.
13272 * The passed function will be called with each
13273 * object in the collection. If the function returns true, the value is included
13274 * otherwise it is filtered.
13275 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13276 * @param {Object} scope (optional) The scope of the function (defaults to this)
13277 * @return {MixedCollection} The new filtered collection
13279 filterBy : function(fn, scope){
13280 var r = new Roo.util.MixedCollection();
13281 r.getKey = this.getKey;
13282 var k = this.keys, it = this.items;
13283 for(var i = 0, len = it.length; i < len; i++){
13284 if(fn.call(scope||this, it[i], k[i])){
13285 r.add(k[i], it[i]);
13292 * Creates a duplicate of this collection
13293 * @return {MixedCollection}
13295 clone : function(){
13296 var r = new Roo.util.MixedCollection();
13297 var k = this.keys, it = this.items;
13298 for(var i = 0, len = it.length; i < len; i++){
13299 r.add(k[i], it[i]);
13301 r.getKey = this.getKey;
13306 * Returns the item associated with the passed key or index.
13308 * @param {String/Number} key The key or index of the item.
13309 * @return {Object} The item associated with the passed key.
13311 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13313 * Ext JS Library 1.1.1
13314 * Copyright(c) 2006-2007, Ext JS, LLC.
13316 * Originally Released Under LGPL - original licence link has changed is not relivant.
13319 * <script type="text/javascript">
13322 * @class Roo.util.JSON
13323 * Modified version of Douglas Crockford"s json.js that doesn"t
13324 * mess with the Object prototype
13325 * http://www.json.org/js.html
13328 Roo.util.JSON = new (function(){
13329 var useHasOwn = {}.hasOwnProperty ? true : false;
13331 // crashes Safari in some instances
13332 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13334 var pad = function(n) {
13335 return n < 10 ? "0" + n : n;
13348 var encodeString = function(s){
13349 if (/["\\\x00-\x1f]/.test(s)) {
13350 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13355 c = b.charCodeAt();
13357 Math.floor(c / 16).toString(16) +
13358 (c % 16).toString(16);
13361 return '"' + s + '"';
13364 var encodeArray = function(o){
13365 var a = ["["], b, i, l = o.length, v;
13366 for (i = 0; i < l; i += 1) {
13368 switch (typeof v) {
13377 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13385 var encodeDate = function(o){
13386 return '"' + o.getFullYear() + "-" +
13387 pad(o.getMonth() + 1) + "-" +
13388 pad(o.getDate()) + "T" +
13389 pad(o.getHours()) + ":" +
13390 pad(o.getMinutes()) + ":" +
13391 pad(o.getSeconds()) + '"';
13395 * Encodes an Object, Array or other value
13396 * @param {Mixed} o The variable to encode
13397 * @return {String} The JSON string
13399 this.encode = function(o)
13401 // should this be extended to fully wrap stringify..
13403 if(typeof o == "undefined" || o === null){
13405 }else if(o instanceof Array){
13406 return encodeArray(o);
13407 }else if(o instanceof Date){
13408 return encodeDate(o);
13409 }else if(typeof o == "string"){
13410 return encodeString(o);
13411 }else if(typeof o == "number"){
13412 return isFinite(o) ? String(o) : "null";
13413 }else if(typeof o == "boolean"){
13416 var a = ["{"], b, i, v;
13418 if(!useHasOwn || o.hasOwnProperty(i)) {
13420 switch (typeof v) {
13429 a.push(this.encode(i), ":",
13430 v === null ? "null" : this.encode(v));
13441 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13442 * @param {String} json The JSON string
13443 * @return {Object} The resulting object
13445 this.decode = function(json){
13447 return /** eval:var:json */ eval("(" + json + ')');
13451 * Shorthand for {@link Roo.util.JSON#encode}
13452 * @member Roo encode
13454 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13456 * Shorthand for {@link Roo.util.JSON#decode}
13457 * @member Roo decode
13459 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13462 * Ext JS Library 1.1.1
13463 * Copyright(c) 2006-2007, Ext JS, LLC.
13465 * Originally Released Under LGPL - original licence link has changed is not relivant.
13468 * <script type="text/javascript">
13472 * @class Roo.util.Format
13473 * Reusable data formatting functions
13476 Roo.util.Format = function(){
13477 var trimRe = /^\s+|\s+$/g;
13480 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13481 * @param {String} value The string to truncate
13482 * @param {Number} length The maximum length to allow before truncating
13483 * @return {String} The converted text
13485 ellipsis : function(value, len){
13486 if(value && value.length > len){
13487 return value.substr(0, len-3)+"...";
13493 * Checks a reference and converts it to empty string if it is undefined
13494 * @param {Mixed} value Reference to check
13495 * @return {Mixed} Empty string if converted, otherwise the original value
13497 undef : function(value){
13498 return typeof value != "undefined" ? value : "";
13502 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13503 * @param {String} value The string to encode
13504 * @return {String} The encoded text
13506 htmlEncode : function(value){
13507 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13511 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13512 * @param {String} value The string to decode
13513 * @return {String} The decoded text
13515 htmlDecode : function(value){
13516 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13520 * Trims any whitespace from either side of a string
13521 * @param {String} value The text to trim
13522 * @return {String} The trimmed text
13524 trim : function(value){
13525 return String(value).replace(trimRe, "");
13529 * Returns a substring from within an original string
13530 * @param {String} value The original text
13531 * @param {Number} start The start index of the substring
13532 * @param {Number} length The length of the substring
13533 * @return {String} The substring
13535 substr : function(value, start, length){
13536 return String(value).substr(start, length);
13540 * Converts a string to all lower case letters
13541 * @param {String} value The text to convert
13542 * @return {String} The converted text
13544 lowercase : function(value){
13545 return String(value).toLowerCase();
13549 * Converts a string to all upper case letters
13550 * @param {String} value The text to convert
13551 * @return {String} The converted text
13553 uppercase : function(value){
13554 return String(value).toUpperCase();
13558 * Converts the first character only of a string to upper case
13559 * @param {String} value The text to convert
13560 * @return {String} The converted text
13562 capitalize : function(value){
13563 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13567 call : function(value, fn){
13568 if(arguments.length > 2){
13569 var args = Array.prototype.slice.call(arguments, 2);
13570 args.unshift(value);
13572 return /** eval:var:value */ eval(fn).apply(window, args);
13574 /** eval:var:value */
13575 return /** eval:var:value */ eval(fn).call(window, value);
13581 * safer version of Math.toFixed..??/
13582 * @param {Number/String} value The numeric value to format
13583 * @param {Number/String} value Decimal places
13584 * @return {String} The formatted currency string
13586 toFixed : function(v, n)
13588 // why not use to fixed - precision is buggered???
13590 return Math.round(v-0);
13592 var fact = Math.pow(10,n+1);
13593 v = (Math.round((v-0)*fact))/fact;
13594 var z = (''+fact).substring(2);
13595 if (v == Math.floor(v)) {
13596 return Math.floor(v) + '.' + z;
13599 // now just padd decimals..
13600 var ps = String(v).split('.');
13601 var fd = (ps[1] + z);
13602 var r = fd.substring(0,n);
13603 var rm = fd.substring(n);
13605 return ps[0] + '.' + r;
13607 r*=1; // turn it into a number;
13609 if (String(r).length != n) {
13612 r = String(r).substring(1); // chop the end off.
13615 return ps[0] + '.' + r;
13620 * Format a number as US currency
13621 * @param {Number/String} value The numeric value to format
13622 * @return {String} The formatted currency string
13624 usMoney : function(v){
13625 return '$' + Roo.util.Format.number(v);
13630 * eventually this should probably emulate php's number_format
13631 * @param {Number/String} value The numeric value to format
13632 * @param {Number} decimals number of decimal places
13633 * @return {String} The formatted currency string
13635 number : function(v,decimals)
13637 // multiply and round.
13638 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13639 var mul = Math.pow(10, decimals);
13640 var zero = String(mul).substring(1);
13641 v = (Math.round((v-0)*mul))/mul;
13643 // if it's '0' number.. then
13645 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13647 var ps = v.split('.');
13651 var r = /(\d+)(\d{3})/;
13653 while (r.test(whole)) {
13654 whole = whole.replace(r, '$1' + ',' + '$2');
13660 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13661 // does not have decimals
13662 (decimals ? ('.' + zero) : '');
13665 return whole + sub ;
13669 * Parse a value into a formatted date using the specified format pattern.
13670 * @param {Mixed} value The value to format
13671 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13672 * @return {String} The formatted date string
13674 date : function(v, format){
13678 if(!(v instanceof Date)){
13679 v = new Date(Date.parse(v));
13681 return v.dateFormat(format || Roo.util.Format.defaults.date);
13685 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13686 * @param {String} format Any valid date format string
13687 * @return {Function} The date formatting function
13689 dateRenderer : function(format){
13690 return function(v){
13691 return Roo.util.Format.date(v, format);
13696 stripTagsRE : /<\/?[^>]+>/gi,
13699 * Strips all HTML tags
13700 * @param {Mixed} value The text from which to strip tags
13701 * @return {String} The stripped text
13703 stripTags : function(v){
13704 return !v ? v : String(v).replace(this.stripTagsRE, "");
13708 Roo.util.Format.defaults = {
13712 * Ext JS Library 1.1.1
13713 * Copyright(c) 2006-2007, Ext JS, LLC.
13715 * Originally Released Under LGPL - original licence link has changed is not relivant.
13718 * <script type="text/javascript">
13725 * @class Roo.MasterTemplate
13726 * @extends Roo.Template
13727 * Provides a template that can have child templates. The syntax is:
13729 var t = new Roo.MasterTemplate(
13730 '<select name="{name}">',
13731 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13734 t.add('options', {value: 'foo', text: 'bar'});
13735 // or you can add multiple child elements in one shot
13736 t.addAll('options', [
13737 {value: 'foo', text: 'bar'},
13738 {value: 'foo2', text: 'bar2'},
13739 {value: 'foo3', text: 'bar3'}
13741 // then append, applying the master template values
13742 t.append('my-form', {name: 'my-select'});
13744 * A name attribute for the child template is not required if you have only one child
13745 * template or you want to refer to them by index.
13747 Roo.MasterTemplate = function(){
13748 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13749 this.originalHtml = this.html;
13751 var m, re = this.subTemplateRe;
13754 while(m = re.exec(this.html)){
13755 var name = m[1], content = m[2];
13760 tpl : new Roo.Template(content)
13763 st[name] = st[subIndex];
13765 st[subIndex].tpl.compile();
13766 st[subIndex].tpl.call = this.call.createDelegate(this);
13769 this.subCount = subIndex;
13772 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13774 * The regular expression used to match sub templates
13778 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13781 * Applies the passed values to a child template.
13782 * @param {String/Number} name (optional) The name or index of the child template
13783 * @param {Array/Object} values The values to be applied to the template
13784 * @return {MasterTemplate} this
13786 add : function(name, values){
13787 if(arguments.length == 1){
13788 values = arguments[0];
13791 var s = this.subs[name];
13792 s.buffer[s.buffer.length] = s.tpl.apply(values);
13797 * Applies all the passed values to a child template.
13798 * @param {String/Number} name (optional) The name or index of the child template
13799 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13800 * @param {Boolean} reset (optional) True to reset the template first
13801 * @return {MasterTemplate} this
13803 fill : function(name, values, reset){
13805 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13813 for(var i = 0, len = values.length; i < len; i++){
13814 this.add(name, values[i]);
13820 * Resets the template for reuse
13821 * @return {MasterTemplate} this
13823 reset : function(){
13825 for(var i = 0; i < this.subCount; i++){
13831 applyTemplate : function(values){
13833 var replaceIndex = -1;
13834 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13835 return s[++replaceIndex].buffer.join("");
13837 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13840 apply : function(){
13841 return this.applyTemplate.apply(this, arguments);
13844 compile : function(){return this;}
13848 * Alias for fill().
13851 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13853 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13854 * var tpl = Roo.MasterTemplate.from('element-id');
13855 * @param {String/HTMLElement} el
13856 * @param {Object} config
13859 Roo.MasterTemplate.from = function(el, config){
13860 el = Roo.getDom(el);
13861 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13864 * Ext JS Library 1.1.1
13865 * Copyright(c) 2006-2007, Ext JS, LLC.
13867 * Originally Released Under LGPL - original licence link has changed is not relivant.
13870 * <script type="text/javascript">
13875 * @class Roo.util.CSS
13876 * Utility class for manipulating CSS rules
13879 Roo.util.CSS = function(){
13881 var doc = document;
13883 var camelRe = /(-[a-z])/gi;
13884 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13888 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13889 * tag and appended to the HEAD of the document.
13890 * @param {String|Object} cssText The text containing the css rules
13891 * @param {String} id An id to add to the stylesheet for later removal
13892 * @return {StyleSheet}
13894 createStyleSheet : function(cssText, id){
13896 var head = doc.getElementsByTagName("head")[0];
13897 var nrules = doc.createElement("style");
13898 nrules.setAttribute("type", "text/css");
13900 nrules.setAttribute("id", id);
13902 if (typeof(cssText) != 'string') {
13903 // support object maps..
13904 // not sure if this a good idea..
13905 // perhaps it should be merged with the general css handling
13906 // and handle js style props.
13907 var cssTextNew = [];
13908 for(var n in cssText) {
13910 for(var k in cssText[n]) {
13911 citems.push( k + ' : ' +cssText[n][k] + ';' );
13913 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13916 cssText = cssTextNew.join("\n");
13922 head.appendChild(nrules);
13923 ss = nrules.styleSheet;
13924 ss.cssText = cssText;
13927 nrules.appendChild(doc.createTextNode(cssText));
13929 nrules.cssText = cssText;
13931 head.appendChild(nrules);
13932 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13934 this.cacheStyleSheet(ss);
13939 * Removes a style or link tag by id
13940 * @param {String} id The id of the tag
13942 removeStyleSheet : function(id){
13943 var existing = doc.getElementById(id);
13945 existing.parentNode.removeChild(existing);
13950 * Dynamically swaps an existing stylesheet reference for a new one
13951 * @param {String} id The id of an existing link tag to remove
13952 * @param {String} url The href of the new stylesheet to include
13954 swapStyleSheet : function(id, url){
13955 this.removeStyleSheet(id);
13956 var ss = doc.createElement("link");
13957 ss.setAttribute("rel", "stylesheet");
13958 ss.setAttribute("type", "text/css");
13959 ss.setAttribute("id", id);
13960 ss.setAttribute("href", url);
13961 doc.getElementsByTagName("head")[0].appendChild(ss);
13965 * Refresh the rule cache if you have dynamically added stylesheets
13966 * @return {Object} An object (hash) of rules indexed by selector
13968 refreshCache : function(){
13969 return this.getRules(true);
13973 cacheStyleSheet : function(stylesheet){
13977 try{// try catch for cross domain access issue
13978 var ssRules = stylesheet.cssRules || stylesheet.rules;
13979 for(var j = ssRules.length-1; j >= 0; --j){
13980 rules[ssRules[j].selectorText] = ssRules[j];
13986 * Gets all css rules for the document
13987 * @param {Boolean} refreshCache true to refresh the internal cache
13988 * @return {Object} An object (hash) of rules indexed by selector
13990 getRules : function(refreshCache){
13991 if(rules == null || refreshCache){
13993 var ds = doc.styleSheets;
13994 for(var i =0, len = ds.length; i < len; i++){
13996 this.cacheStyleSheet(ds[i]);
14004 * Gets an an individual CSS rule by selector(s)
14005 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
14006 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
14007 * @return {CSSRule} The CSS rule or null if one is not found
14009 getRule : function(selector, refreshCache){
14010 var rs = this.getRules(refreshCache);
14011 if(!(selector instanceof Array)){
14012 return rs[selector];
14014 for(var i = 0; i < selector.length; i++){
14015 if(rs[selector[i]]){
14016 return rs[selector[i]];
14024 * Updates a rule property
14025 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14026 * @param {String} property The css property
14027 * @param {String} value The new value for the property
14028 * @return {Boolean} true If a rule was found and updated
14030 updateRule : function(selector, property, value){
14031 if(!(selector instanceof Array)){
14032 var rule = this.getRule(selector);
14034 rule.style[property.replace(camelRe, camelFn)] = value;
14038 for(var i = 0; i < selector.length; i++){
14039 if(this.updateRule(selector[i], property, value)){
14049 * Ext JS Library 1.1.1
14050 * Copyright(c) 2006-2007, Ext JS, LLC.
14052 * Originally Released Under LGPL - original licence link has changed is not relivant.
14055 * <script type="text/javascript">
14061 * @class Roo.util.ClickRepeater
14062 * @extends Roo.util.Observable
14064 * A wrapper class which can be applied to any element. Fires a "click" event while the
14065 * mouse is pressed. The interval between firings may be specified in the config but
14066 * defaults to 10 milliseconds.
14068 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14070 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14071 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14072 * Similar to an autorepeat key delay.
14073 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14074 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14075 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14076 * "interval" and "delay" are ignored. "immediate" is honored.
14077 * @cfg {Boolean} preventDefault True to prevent the default click event
14078 * @cfg {Boolean} stopDefault True to stop the default click event
14081 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14082 * 2007-02-02 jvs Renamed to ClickRepeater
14083 * 2007-02-03 jvs Modifications for FF Mac and Safari
14086 * @param {String/HTMLElement/Element} el The element to listen on
14087 * @param {Object} config
14089 Roo.util.ClickRepeater = function(el, config)
14091 this.el = Roo.get(el);
14092 this.el.unselectable();
14094 Roo.apply(this, config);
14099 * Fires when the mouse button is depressed.
14100 * @param {Roo.util.ClickRepeater} this
14102 "mousedown" : true,
14105 * Fires on a specified interval during the time the element is pressed.
14106 * @param {Roo.util.ClickRepeater} this
14111 * Fires when the mouse key is released.
14112 * @param {Roo.util.ClickRepeater} this
14117 this.el.on("mousedown", this.handleMouseDown, this);
14118 if(this.preventDefault || this.stopDefault){
14119 this.el.on("click", function(e){
14120 if(this.preventDefault){
14121 e.preventDefault();
14123 if(this.stopDefault){
14129 // allow inline handler
14131 this.on("click", this.handler, this.scope || this);
14134 Roo.util.ClickRepeater.superclass.constructor.call(this);
14137 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14140 preventDefault : true,
14141 stopDefault : false,
14145 handleMouseDown : function(){
14146 clearTimeout(this.timer);
14148 if(this.pressClass){
14149 this.el.addClass(this.pressClass);
14151 this.mousedownTime = new Date();
14153 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14154 this.el.on("mouseout", this.handleMouseOut, this);
14156 this.fireEvent("mousedown", this);
14157 this.fireEvent("click", this);
14159 this.timer = this.click.defer(this.delay || this.interval, this);
14163 click : function(){
14164 this.fireEvent("click", this);
14165 this.timer = this.click.defer(this.getInterval(), this);
14169 getInterval: function(){
14170 if(!this.accelerate){
14171 return this.interval;
14173 var pressTime = this.mousedownTime.getElapsed();
14174 if(pressTime < 500){
14176 }else if(pressTime < 1700){
14178 }else if(pressTime < 2600){
14180 }else if(pressTime < 3500){
14182 }else if(pressTime < 4400){
14184 }else if(pressTime < 5300){
14186 }else if(pressTime < 6200){
14194 handleMouseOut : function(){
14195 clearTimeout(this.timer);
14196 if(this.pressClass){
14197 this.el.removeClass(this.pressClass);
14199 this.el.on("mouseover", this.handleMouseReturn, this);
14203 handleMouseReturn : function(){
14204 this.el.un("mouseover", this.handleMouseReturn);
14205 if(this.pressClass){
14206 this.el.addClass(this.pressClass);
14212 handleMouseUp : function(){
14213 clearTimeout(this.timer);
14214 this.el.un("mouseover", this.handleMouseReturn);
14215 this.el.un("mouseout", this.handleMouseOut);
14216 Roo.get(document).un("mouseup", this.handleMouseUp);
14217 this.el.removeClass(this.pressClass);
14218 this.fireEvent("mouseup", this);
14222 * Ext JS Library 1.1.1
14223 * Copyright(c) 2006-2007, Ext JS, LLC.
14225 * Originally Released Under LGPL - original licence link has changed is not relivant.
14228 * <script type="text/javascript">
14233 * @class Roo.KeyNav
14234 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14235 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14236 * way to implement custom navigation schemes for any UI component.</p>
14237 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14238 * pageUp, pageDown, del, home, end. Usage:</p>
14240 var nav = new Roo.KeyNav("my-element", {
14241 "left" : function(e){
14242 this.moveLeft(e.ctrlKey);
14244 "right" : function(e){
14245 this.moveRight(e.ctrlKey);
14247 "enter" : function(e){
14254 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14255 * @param {Object} config The config
14257 Roo.KeyNav = function(el, config){
14258 this.el = Roo.get(el);
14259 Roo.apply(this, config);
14260 if(!this.disabled){
14261 this.disabled = true;
14266 Roo.KeyNav.prototype = {
14268 * @cfg {Boolean} disabled
14269 * True to disable this KeyNav instance (defaults to false)
14273 * @cfg {String} defaultEventAction
14274 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14275 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14276 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14278 defaultEventAction: "stopEvent",
14280 * @cfg {Boolean} forceKeyDown
14281 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14282 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14283 * handle keydown instead of keypress.
14285 forceKeyDown : false,
14288 prepareEvent : function(e){
14289 var k = e.getKey();
14290 var h = this.keyToHandler[k];
14291 //if(h && this[h]){
14292 // e.stopPropagation();
14294 if(Roo.isSafari && h && k >= 37 && k <= 40){
14300 relay : function(e){
14301 var k = e.getKey();
14302 var h = this.keyToHandler[k];
14304 if(this.doRelay(e, this[h], h) !== true){
14305 e[this.defaultEventAction]();
14311 doRelay : function(e, h, hname){
14312 return h.call(this.scope || this, e);
14315 // possible handlers
14329 // quick lookup hash
14346 * Enable this KeyNav
14348 enable: function(){
14350 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14351 // the EventObject will normalize Safari automatically
14352 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14353 this.el.on("keydown", this.relay, this);
14355 this.el.on("keydown", this.prepareEvent, this);
14356 this.el.on("keypress", this.relay, this);
14358 this.disabled = false;
14363 * Disable this KeyNav
14365 disable: function(){
14366 if(!this.disabled){
14367 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14368 this.el.un("keydown", this.relay);
14370 this.el.un("keydown", this.prepareEvent);
14371 this.el.un("keypress", this.relay);
14373 this.disabled = true;
14378 * Ext JS Library 1.1.1
14379 * Copyright(c) 2006-2007, Ext JS, LLC.
14381 * Originally Released Under LGPL - original licence link has changed is not relivant.
14384 * <script type="text/javascript">
14389 * @class Roo.KeyMap
14390 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14391 * The constructor accepts the same config object as defined by {@link #addBinding}.
14392 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14393 * combination it will call the function with this signature (if the match is a multi-key
14394 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14395 * A KeyMap can also handle a string representation of keys.<br />
14398 // map one key by key code
14399 var map = new Roo.KeyMap("my-element", {
14400 key: 13, // or Roo.EventObject.ENTER
14405 // map multiple keys to one action by string
14406 var map = new Roo.KeyMap("my-element", {
14412 // map multiple keys to multiple actions by strings and array of codes
14413 var map = new Roo.KeyMap("my-element", [
14416 fn: function(){ alert("Return was pressed"); }
14419 fn: function(){ alert('a, b or c was pressed'); }
14424 fn: function(){ alert('Control + shift + tab was pressed.'); }
14428 * <b>Note: A KeyMap starts enabled</b>
14430 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14431 * @param {Object} config The config (see {@link #addBinding})
14432 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14434 Roo.KeyMap = function(el, config, eventName){
14435 this.el = Roo.get(el);
14436 this.eventName = eventName || "keydown";
14437 this.bindings = [];
14439 this.addBinding(config);
14444 Roo.KeyMap.prototype = {
14446 * True to stop the event from bubbling and prevent the default browser action if the
14447 * key was handled by the KeyMap (defaults to false)
14453 * Add a new binding to this KeyMap. The following config object properties are supported:
14455 Property Type Description
14456 ---------- --------------- ----------------------------------------------------------------------
14457 key String/Array A single keycode or an array of keycodes to handle
14458 shift Boolean True to handle key only when shift is pressed (defaults to false)
14459 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14460 alt Boolean True to handle key only when alt is pressed (defaults to false)
14461 fn Function The function to call when KeyMap finds the expected key combination
14462 scope Object The scope of the callback function
14468 var map = new Roo.KeyMap(document, {
14469 key: Roo.EventObject.ENTER,
14474 //Add a new binding to the existing KeyMap later
14482 * @param {Object/Array} config A single KeyMap config or an array of configs
14484 addBinding : function(config){
14485 if(config instanceof Array){
14486 for(var i = 0, len = config.length; i < len; i++){
14487 this.addBinding(config[i]);
14491 var keyCode = config.key,
14492 shift = config.shift,
14493 ctrl = config.ctrl,
14496 scope = config.scope;
14497 if(typeof keyCode == "string"){
14499 var keyString = keyCode.toUpperCase();
14500 for(var j = 0, len = keyString.length; j < len; j++){
14501 ks.push(keyString.charCodeAt(j));
14505 var keyArray = keyCode instanceof Array;
14506 var handler = function(e){
14507 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14508 var k = e.getKey();
14510 for(var i = 0, len = keyCode.length; i < len; i++){
14511 if(keyCode[i] == k){
14512 if(this.stopEvent){
14515 fn.call(scope || window, k, e);
14521 if(this.stopEvent){
14524 fn.call(scope || window, k, e);
14529 this.bindings.push(handler);
14533 * Shorthand for adding a single key listener
14534 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14535 * following options:
14536 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14537 * @param {Function} fn The function to call
14538 * @param {Object} scope (optional) The scope of the function
14540 on : function(key, fn, scope){
14541 var keyCode, shift, ctrl, alt;
14542 if(typeof key == "object" && !(key instanceof Array)){
14561 handleKeyDown : function(e){
14562 if(this.enabled){ //just in case
14563 var b = this.bindings;
14564 for(var i = 0, len = b.length; i < len; i++){
14565 b[i].call(this, e);
14571 * Returns true if this KeyMap is enabled
14572 * @return {Boolean}
14574 isEnabled : function(){
14575 return this.enabled;
14579 * Enables this KeyMap
14581 enable: function(){
14583 this.el.on(this.eventName, this.handleKeyDown, this);
14584 this.enabled = true;
14589 * Disable this KeyMap
14591 disable: function(){
14593 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14594 this.enabled = false;
14599 * Ext JS Library 1.1.1
14600 * Copyright(c) 2006-2007, Ext JS, LLC.
14602 * Originally Released Under LGPL - original licence link has changed is not relivant.
14605 * <script type="text/javascript">
14610 * @class Roo.util.TextMetrics
14611 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14612 * wide, in pixels, a given block of text will be.
14615 Roo.util.TextMetrics = function(){
14619 * Measures the size of the specified text
14620 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14621 * that can affect the size of the rendered text
14622 * @param {String} text The text to measure
14623 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14624 * in order to accurately measure the text height
14625 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14627 measure : function(el, text, fixedWidth){
14629 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14632 shared.setFixedWidth(fixedWidth || 'auto');
14633 return shared.getSize(text);
14637 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14638 * the overhead of multiple calls to initialize the style properties on each measurement.
14639 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14640 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14641 * in order to accurately measure the text height
14642 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14644 createInstance : function(el, fixedWidth){
14645 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14652 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14653 var ml = new Roo.Element(document.createElement('div'));
14654 document.body.appendChild(ml.dom);
14655 ml.position('absolute');
14656 ml.setLeftTop(-1000, -1000);
14660 ml.setWidth(fixedWidth);
14665 * Returns the size of the specified text based on the internal element's style and width properties
14666 * @memberOf Roo.util.TextMetrics.Instance#
14667 * @param {String} text The text to measure
14668 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14670 getSize : function(text){
14672 var s = ml.getSize();
14678 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14679 * that can affect the size of the rendered text
14680 * @memberOf Roo.util.TextMetrics.Instance#
14681 * @param {String/HTMLElement} el The element, dom node or id
14683 bind : function(el){
14685 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14690 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14691 * to set a fixed width in order to accurately measure the text height.
14692 * @memberOf Roo.util.TextMetrics.Instance#
14693 * @param {Number} width The width to set on the element
14695 setFixedWidth : function(width){
14696 ml.setWidth(width);
14700 * Returns the measured width of the specified text
14701 * @memberOf Roo.util.TextMetrics.Instance#
14702 * @param {String} text The text to measure
14703 * @return {Number} width The width in pixels
14705 getWidth : function(text){
14706 ml.dom.style.width = 'auto';
14707 return this.getSize(text).width;
14711 * Returns the measured height of the specified text. For multiline text, be sure to call
14712 * {@link #setFixedWidth} if necessary.
14713 * @memberOf Roo.util.TextMetrics.Instance#
14714 * @param {String} text The text to measure
14715 * @return {Number} height The height in pixels
14717 getHeight : function(text){
14718 return this.getSize(text).height;
14722 instance.bind(bindTo);
14727 // backwards compat
14728 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14730 * Ext JS Library 1.1.1
14731 * Copyright(c) 2006-2007, Ext JS, LLC.
14733 * Originally Released Under LGPL - original licence link has changed is not relivant.
14736 * <script type="text/javascript">
14740 * @class Roo.state.Provider
14741 * Abstract base class for state provider implementations. This class provides methods
14742 * for encoding and decoding <b>typed</b> variables including dates and defines the
14743 * Provider interface.
14745 Roo.state.Provider = function(){
14747 * @event statechange
14748 * Fires when a state change occurs.
14749 * @param {Provider} this This state provider
14750 * @param {String} key The state key which was changed
14751 * @param {String} value The encoded value for the state
14754 "statechange": true
14757 Roo.state.Provider.superclass.constructor.call(this);
14759 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14761 * Returns the current value for a key
14762 * @param {String} name The key name
14763 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14764 * @return {Mixed} The state data
14766 get : function(name, defaultValue){
14767 return typeof this.state[name] == "undefined" ?
14768 defaultValue : this.state[name];
14772 * Clears a value from the state
14773 * @param {String} name The key name
14775 clear : function(name){
14776 delete this.state[name];
14777 this.fireEvent("statechange", this, name, null);
14781 * Sets the value for a key
14782 * @param {String} name The key name
14783 * @param {Mixed} value The value to set
14785 set : function(name, value){
14786 this.state[name] = value;
14787 this.fireEvent("statechange", this, name, value);
14791 * Decodes a string previously encoded with {@link #encodeValue}.
14792 * @param {String} value The value to decode
14793 * @return {Mixed} The decoded value
14795 decodeValue : function(cookie){
14796 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14797 var matches = re.exec(unescape(cookie));
14798 if(!matches || !matches[1]) return; // non state cookie
14799 var type = matches[1];
14800 var v = matches[2];
14803 return parseFloat(v);
14805 return new Date(Date.parse(v));
14810 var values = v.split("^");
14811 for(var i = 0, len = values.length; i < len; i++){
14812 all.push(this.decodeValue(values[i]));
14817 var values = v.split("^");
14818 for(var i = 0, len = values.length; i < len; i++){
14819 var kv = values[i].split("=");
14820 all[kv[0]] = this.decodeValue(kv[1]);
14829 * Encodes a value including type information. Decode with {@link #decodeValue}.
14830 * @param {Mixed} value The value to encode
14831 * @return {String} The encoded value
14833 encodeValue : function(v){
14835 if(typeof v == "number"){
14837 }else if(typeof v == "boolean"){
14838 enc = "b:" + (v ? "1" : "0");
14839 }else if(v instanceof Date){
14840 enc = "d:" + v.toGMTString();
14841 }else if(v instanceof Array){
14843 for(var i = 0, len = v.length; i < len; i++){
14844 flat += this.encodeValue(v[i]);
14845 if(i != len-1) flat += "^";
14848 }else if(typeof v == "object"){
14851 if(typeof v[key] != "function"){
14852 flat += key + "=" + this.encodeValue(v[key]) + "^";
14855 enc = "o:" + flat.substring(0, flat.length-1);
14859 return escape(enc);
14865 * Ext JS Library 1.1.1
14866 * Copyright(c) 2006-2007, Ext JS, LLC.
14868 * Originally Released Under LGPL - original licence link has changed is not relivant.
14871 * <script type="text/javascript">
14874 * @class Roo.state.Manager
14875 * This is the global state manager. By default all components that are "state aware" check this class
14876 * for state information if you don't pass them a custom state provider. In order for this class
14877 * to be useful, it must be initialized with a provider when your application initializes.
14879 // in your initialization function
14881 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14883 // supposed you have a {@link Roo.BorderLayout}
14884 var layout = new Roo.BorderLayout(...);
14885 layout.restoreState();
14886 // or a {Roo.BasicDialog}
14887 var dialog = new Roo.BasicDialog(...);
14888 dialog.restoreState();
14892 Roo.state.Manager = function(){
14893 var provider = new Roo.state.Provider();
14897 * Configures the default state provider for your application
14898 * @param {Provider} stateProvider The state provider to set
14900 setProvider : function(stateProvider){
14901 provider = stateProvider;
14905 * Returns the current value for a key
14906 * @param {String} name The key name
14907 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14908 * @return {Mixed} The state data
14910 get : function(key, defaultValue){
14911 return provider.get(key, defaultValue);
14915 * Sets the value for a key
14916 * @param {String} name The key name
14917 * @param {Mixed} value The state data
14919 set : function(key, value){
14920 provider.set(key, value);
14924 * Clears a value from the state
14925 * @param {String} name The key name
14927 clear : function(key){
14928 provider.clear(key);
14932 * Gets the currently configured state provider
14933 * @return {Provider} The state provider
14935 getProvider : function(){
14942 * Ext JS Library 1.1.1
14943 * Copyright(c) 2006-2007, Ext JS, LLC.
14945 * Originally Released Under LGPL - original licence link has changed is not relivant.
14948 * <script type="text/javascript">
14951 * @class Roo.state.CookieProvider
14952 * @extends Roo.state.Provider
14953 * The default Provider implementation which saves state via cookies.
14956 var cp = new Roo.state.CookieProvider({
14958 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14959 domain: "roojs.com"
14961 Roo.state.Manager.setProvider(cp);
14963 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14964 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14965 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14966 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14967 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14968 * domain the page is running on including the 'www' like 'www.roojs.com')
14969 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14971 * Create a new CookieProvider
14972 * @param {Object} config The configuration object
14974 Roo.state.CookieProvider = function(config){
14975 Roo.state.CookieProvider.superclass.constructor.call(this);
14977 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14978 this.domain = null;
14979 this.secure = false;
14980 Roo.apply(this, config);
14981 this.state = this.readCookies();
14984 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14986 set : function(name, value){
14987 if(typeof value == "undefined" || value === null){
14991 this.setCookie(name, value);
14992 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14996 clear : function(name){
14997 this.clearCookie(name);
14998 Roo.state.CookieProvider.superclass.clear.call(this, name);
15002 readCookies : function(){
15004 var c = document.cookie + ";";
15005 var re = /\s?(.*?)=(.*?);/g;
15007 while((matches = re.exec(c)) != null){
15008 var name = matches[1];
15009 var value = matches[2];
15010 if(name && name.substring(0,3) == "ys-"){
15011 cookies[name.substr(3)] = this.decodeValue(value);
15018 setCookie : function(name, value){
15019 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15020 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15021 ((this.path == null) ? "" : ("; path=" + this.path)) +
15022 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15023 ((this.secure == true) ? "; secure" : "");
15027 clearCookie : function(name){
15028 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15029 ((this.path == null) ? "" : ("; path=" + this.path)) +
15030 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15031 ((this.secure == true) ? "; secure" : "");
15035 * Ext JS Library 1.1.1
15036 * Copyright(c) 2006-2007, Ext JS, LLC.
15038 * Originally Released Under LGPL - original licence link has changed is not relivant.
15041 * <script type="text/javascript">
15046 * @class Roo.ComponentMgr
15047 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15050 Roo.ComponentMgr = function(){
15051 var all = new Roo.util.MixedCollection();
15055 * Registers a component.
15056 * @param {Roo.Component} c The component
15058 register : function(c){
15063 * Unregisters a component.
15064 * @param {Roo.Component} c The component
15066 unregister : function(c){
15071 * Returns a component by id
15072 * @param {String} id The component id
15074 get : function(id){
15075 return all.get(id);
15079 * Registers a function that will be called when a specified component is added to ComponentMgr
15080 * @param {String} id The component id
15081 * @param {Funtction} fn The callback function
15082 * @param {Object} scope The scope of the callback
15084 onAvailable : function(id, fn, scope){
15085 all.on("add", function(index, o){
15087 fn.call(scope || o, o);
15088 all.un("add", fn, scope);
15095 * Ext JS Library 1.1.1
15096 * Copyright(c) 2006-2007, Ext JS, LLC.
15098 * Originally Released Under LGPL - original licence link has changed is not relivant.
15101 * <script type="text/javascript">
15105 * @class Roo.Component
15106 * @extends Roo.util.Observable
15107 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15108 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15109 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15110 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15111 * All visual components (widgets) that require rendering into a layout should subclass Component.
15113 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15114 * 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
15115 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15117 Roo.Component = function(config){
15118 config = config || {};
15119 if(config.tagName || config.dom || typeof config == "string"){ // element object
15120 config = {el: config, id: config.id || config};
15122 this.initialConfig = config;
15124 Roo.apply(this, config);
15128 * Fires after the component is disabled.
15129 * @param {Roo.Component} this
15134 * Fires after the component is enabled.
15135 * @param {Roo.Component} this
15139 * @event beforeshow
15140 * Fires before the component is shown. Return false to stop the show.
15141 * @param {Roo.Component} this
15146 * Fires after the component is shown.
15147 * @param {Roo.Component} this
15151 * @event beforehide
15152 * Fires before the component is hidden. Return false to stop the hide.
15153 * @param {Roo.Component} this
15158 * Fires after the component is hidden.
15159 * @param {Roo.Component} this
15163 * @event beforerender
15164 * Fires before the component is rendered. Return false to stop the render.
15165 * @param {Roo.Component} this
15167 beforerender : true,
15170 * Fires after the component is rendered.
15171 * @param {Roo.Component} this
15175 * @event beforedestroy
15176 * Fires before the component is destroyed. Return false to stop the destroy.
15177 * @param {Roo.Component} this
15179 beforedestroy : true,
15182 * Fires after the component is destroyed.
15183 * @param {Roo.Component} this
15188 this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
15190 Roo.ComponentMgr.register(this);
15191 Roo.Component.superclass.constructor.call(this);
15192 this.initComponent();
15193 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15194 this.render(this.renderTo);
15195 delete this.renderTo;
15200 Roo.Component.AUTO_ID = 1000;
15202 Roo.extend(Roo.Component, Roo.util.Observable, {
15204 * @scope Roo.Component.prototype
15206 * true if this component is hidden. Read-only.
15211 * true if this component is disabled. Read-only.
15216 * true if this component has been rendered. Read-only.
15220 /** @cfg {String} disableClass
15221 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15223 disabledClass : "x-item-disabled",
15224 /** @cfg {Boolean} allowDomMove
15225 * Whether the component can move the Dom node when rendering (defaults to true).
15227 allowDomMove : true,
15228 /** @cfg {String} hideMode (display|visibility)
15229 * How this component should hidden. Supported values are
15230 * "visibility" (css visibility), "offsets" (negative offset position) and
15231 * "display" (css display) - defaults to "display".
15233 hideMode: 'display',
15236 ctype : "Roo.Component",
15239 * @cfg {String} actionMode
15240 * which property holds the element that used for hide() / show() / disable() / enable()
15246 getActionEl : function(){
15247 return this[this.actionMode];
15250 initComponent : Roo.emptyFn,
15252 * If this is a lazy rendering component, render it to its container element.
15253 * @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.
15255 render : function(container, position){
15256 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15257 if(!container && this.el){
15258 this.el = Roo.get(this.el);
15259 container = this.el.dom.parentNode;
15260 this.allowDomMove = false;
15262 this.container = Roo.get(container);
15263 this.rendered = true;
15264 if(position !== undefined){
15265 if(typeof position == 'number'){
15266 position = this.container.dom.childNodes[position];
15268 position = Roo.getDom(position);
15271 this.onRender(this.container, position || null);
15273 this.el.addClass(this.cls);
15277 this.el.applyStyles(this.style);
15280 this.fireEvent("render", this);
15281 this.afterRender(this.container);
15293 // default function is not really useful
15294 onRender : function(ct, position){
15296 this.el = Roo.get(this.el);
15297 if(this.allowDomMove !== false){
15298 ct.dom.insertBefore(this.el.dom, position);
15304 getAutoCreate : function(){
15305 var cfg = typeof this.autoCreate == "object" ?
15306 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15307 if(this.id && !cfg.id){
15314 afterRender : Roo.emptyFn,
15317 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15318 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15320 destroy : function(){
15321 if(this.fireEvent("beforedestroy", this) !== false){
15322 this.purgeListeners();
15323 this.beforeDestroy();
15325 this.el.removeAllListeners();
15327 if(this.actionMode == "container"){
15328 this.container.remove();
15332 Roo.ComponentMgr.unregister(this);
15333 this.fireEvent("destroy", this);
15338 beforeDestroy : function(){
15343 onDestroy : function(){
15348 * Returns the underlying {@link Roo.Element}.
15349 * @return {Roo.Element} The element
15351 getEl : function(){
15356 * Returns the id of this component.
15359 getId : function(){
15364 * Try to focus this component.
15365 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15366 * @return {Roo.Component} this
15368 focus : function(selectText){
15371 if(selectText === true){
15372 this.el.dom.select();
15387 * Disable this component.
15388 * @return {Roo.Component} this
15390 disable : function(){
15394 this.disabled = true;
15395 this.fireEvent("disable", this);
15400 onDisable : function(){
15401 this.getActionEl().addClass(this.disabledClass);
15402 this.el.dom.disabled = true;
15406 * Enable this component.
15407 * @return {Roo.Component} this
15409 enable : function(){
15413 this.disabled = false;
15414 this.fireEvent("enable", this);
15419 onEnable : function(){
15420 this.getActionEl().removeClass(this.disabledClass);
15421 this.el.dom.disabled = false;
15425 * Convenience function for setting disabled/enabled by boolean.
15426 * @param {Boolean} disabled
15428 setDisabled : function(disabled){
15429 this[disabled ? "disable" : "enable"]();
15433 * Show this component.
15434 * @return {Roo.Component} this
15437 if(this.fireEvent("beforeshow", this) !== false){
15438 this.hidden = false;
15442 this.fireEvent("show", this);
15448 onShow : function(){
15449 var ae = this.getActionEl();
15450 if(this.hideMode == 'visibility'){
15451 ae.dom.style.visibility = "visible";
15452 }else if(this.hideMode == 'offsets'){
15453 ae.removeClass('x-hidden');
15455 ae.dom.style.display = "";
15460 * Hide this component.
15461 * @return {Roo.Component} this
15464 if(this.fireEvent("beforehide", this) !== false){
15465 this.hidden = true;
15469 this.fireEvent("hide", this);
15475 onHide : function(){
15476 var ae = this.getActionEl();
15477 if(this.hideMode == 'visibility'){
15478 ae.dom.style.visibility = "hidden";
15479 }else if(this.hideMode == 'offsets'){
15480 ae.addClass('x-hidden');
15482 ae.dom.style.display = "none";
15487 * Convenience function to hide or show this component by boolean.
15488 * @param {Boolean} visible True to show, false to hide
15489 * @return {Roo.Component} this
15491 setVisible: function(visible){
15501 * Returns true if this component is visible.
15503 isVisible : function(){
15504 return this.getActionEl().isVisible();
15507 cloneConfig : function(overrides){
15508 overrides = overrides || {};
15509 var id = overrides.id || Roo.id();
15510 var cfg = Roo.applyIf(overrides, this.initialConfig);
15511 cfg.id = id; // prevent dup id
15512 return new this.constructor(cfg);
15516 * Ext JS Library 1.1.1
15517 * Copyright(c) 2006-2007, Ext JS, LLC.
15519 * Originally Released Under LGPL - original licence link has changed is not relivant.
15522 * <script type="text/javascript">
15526 * @class Roo.BoxComponent
15527 * @extends Roo.Component
15528 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15529 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15530 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15531 * layout containers.
15533 * @param {Roo.Element/String/Object} config The configuration options.
15535 Roo.BoxComponent = function(config){
15536 Roo.Component.call(this, config);
15540 * Fires after the component is resized.
15541 * @param {Roo.Component} this
15542 * @param {Number} adjWidth The box-adjusted width that was set
15543 * @param {Number} adjHeight The box-adjusted height that was set
15544 * @param {Number} rawWidth The width that was originally specified
15545 * @param {Number} rawHeight The height that was originally specified
15550 * Fires after the component is moved.
15551 * @param {Roo.Component} this
15552 * @param {Number} x The new x position
15553 * @param {Number} y The new y position
15559 Roo.extend(Roo.BoxComponent, Roo.Component, {
15560 // private, set in afterRender to signify that the component has been rendered
15562 // private, used to defer height settings to subclasses
15563 deferHeight: false,
15564 /** @cfg {Number} width
15565 * width (optional) size of component
15567 /** @cfg {Number} height
15568 * height (optional) size of component
15572 * Sets the width and height of the component. This method fires the resize event. This method can accept
15573 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15574 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15575 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15576 * @return {Roo.BoxComponent} this
15578 setSize : function(w, h){
15579 // support for standard size objects
15580 if(typeof w == 'object'){
15585 if(!this.boxReady){
15591 // prevent recalcs when not needed
15592 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15595 this.lastSize = {width: w, height: h};
15597 var adj = this.adjustSize(w, h);
15598 var aw = adj.width, ah = adj.height;
15599 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15600 var rz = this.getResizeEl();
15601 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15602 rz.setSize(aw, ah);
15603 }else if(!this.deferHeight && ah !== undefined){
15605 }else if(aw !== undefined){
15608 this.onResize(aw, ah, w, h);
15609 this.fireEvent('resize', this, aw, ah, w, h);
15615 * Gets the current size of the component's underlying element.
15616 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15618 getSize : function(){
15619 return this.el.getSize();
15623 * Gets the current XY position of the component's underlying element.
15624 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15625 * @return {Array} The XY position of the element (e.g., [100, 200])
15627 getPosition : function(local){
15628 if(local === true){
15629 return [this.el.getLeft(true), this.el.getTop(true)];
15631 return this.xy || this.el.getXY();
15635 * Gets the current box measurements of the component's underlying element.
15636 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15637 * @returns {Object} box An object in the format {x, y, width, height}
15639 getBox : function(local){
15640 var s = this.el.getSize();
15642 s.x = this.el.getLeft(true);
15643 s.y = this.el.getTop(true);
15645 var xy = this.xy || this.el.getXY();
15653 * Sets the current box measurements of the component's underlying element.
15654 * @param {Object} box An object in the format {x, y, width, height}
15655 * @returns {Roo.BoxComponent} this
15657 updateBox : function(box){
15658 this.setSize(box.width, box.height);
15659 this.setPagePosition(box.x, box.y);
15664 getResizeEl : function(){
15665 return this.resizeEl || this.el;
15669 getPositionEl : function(){
15670 return this.positionEl || this.el;
15674 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15675 * This method fires the move event.
15676 * @param {Number} left The new left
15677 * @param {Number} top The new top
15678 * @returns {Roo.BoxComponent} this
15680 setPosition : function(x, y){
15683 if(!this.boxReady){
15686 var adj = this.adjustPosition(x, y);
15687 var ax = adj.x, ay = adj.y;
15689 var el = this.getPositionEl();
15690 if(ax !== undefined || ay !== undefined){
15691 if(ax !== undefined && ay !== undefined){
15692 el.setLeftTop(ax, ay);
15693 }else if(ax !== undefined){
15695 }else if(ay !== undefined){
15698 this.onPosition(ax, ay);
15699 this.fireEvent('move', this, ax, ay);
15705 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15706 * This method fires the move event.
15707 * @param {Number} x The new x position
15708 * @param {Number} y The new y position
15709 * @returns {Roo.BoxComponent} this
15711 setPagePosition : function(x, y){
15714 if(!this.boxReady){
15717 if(x === undefined || y === undefined){ // cannot translate undefined points
15720 var p = this.el.translatePoints(x, y);
15721 this.setPosition(p.left, p.top);
15726 onRender : function(ct, position){
15727 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15729 this.resizeEl = Roo.get(this.resizeEl);
15731 if(this.positionEl){
15732 this.positionEl = Roo.get(this.positionEl);
15737 afterRender : function(){
15738 Roo.BoxComponent.superclass.afterRender.call(this);
15739 this.boxReady = true;
15740 this.setSize(this.width, this.height);
15741 if(this.x || this.y){
15742 this.setPosition(this.x, this.y);
15744 if(this.pageX || this.pageY){
15745 this.setPagePosition(this.pageX, this.pageY);
15750 * Force the component's size to recalculate based on the underlying element's current height and width.
15751 * @returns {Roo.BoxComponent} this
15753 syncSize : function(){
15754 delete this.lastSize;
15755 this.setSize(this.el.getWidth(), this.el.getHeight());
15760 * Called after the component is resized, this method is empty by default but can be implemented by any
15761 * subclass that needs to perform custom logic after a resize occurs.
15762 * @param {Number} adjWidth The box-adjusted width that was set
15763 * @param {Number} adjHeight The box-adjusted height that was set
15764 * @param {Number} rawWidth The width that was originally specified
15765 * @param {Number} rawHeight The height that was originally specified
15767 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15772 * Called after the component is moved, this method is empty by default but can be implemented by any
15773 * subclass that needs to perform custom logic after a move occurs.
15774 * @param {Number} x The new x position
15775 * @param {Number} y The new y position
15777 onPosition : function(x, y){
15782 adjustSize : function(w, h){
15783 if(this.autoWidth){
15786 if(this.autoHeight){
15789 return {width : w, height: h};
15793 adjustPosition : function(x, y){
15794 return {x : x, y: y};
15797 * Original code for Roojs - LGPL
15798 * <script type="text/javascript">
15802 * @class Roo.XComponent
15803 * A delayed Element creator...
15804 * Or a way to group chunks of interface together.
15805 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15806 * used in conjunction with XComponent.build() it will create an instance of each element,
15807 * then call addxtype() to build the User interface.
15809 * Mypart.xyx = new Roo.XComponent({
15811 parent : 'Mypart.xyz', // empty == document.element.!!
15815 disabled : function() {}
15817 tree : function() { // return an tree of xtype declared components
15821 xtype : 'NestedLayoutPanel',
15828 * It can be used to build a big heiracy, with parent etc.
15829 * or you can just use this to render a single compoent to a dom element
15830 * MYPART.render(Roo.Element | String(id) | dom_element )
15837 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15838 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15840 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15842 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15843 * - if mulitple topModules exist, the last one is defined as the top module.
15847 * When the top level or multiple modules are to embedded into a existing HTML page,
15848 * the parent element can container '#id' of the element where the module will be drawn.
15852 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15853 * it relies more on a include mechanism, where sub modules are included into an outer page.
15854 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15856 * Bootstrap Roo Included elements
15858 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15859 * hence confusing the component builder as it thinks there are multiple top level elements.
15863 * @extends Roo.util.Observable
15865 * @param cfg {Object} configuration of component
15868 Roo.XComponent = function(cfg) {
15869 Roo.apply(this, cfg);
15873 * Fires when this the componnt is built
15874 * @param {Roo.XComponent} c the component
15879 this.region = this.region || 'center'; // default..
15880 Roo.XComponent.register(this);
15881 this.modules = false;
15882 this.el = false; // where the layout goes..
15886 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15889 * The created element (with Roo.factory())
15890 * @type {Roo.Layout}
15896 * for BC - use el in new code
15897 * @type {Roo.Layout}
15903 * for BC - use el in new code
15904 * @type {Roo.Layout}
15909 * @cfg {Function|boolean} disabled
15910 * If this module is disabled by some rule, return true from the funtion
15915 * @cfg {String} parent
15916 * Name of parent element which it get xtype added to..
15921 * @cfg {String} order
15922 * Used to set the order in which elements are created (usefull for multiple tabs)
15927 * @cfg {String} name
15928 * String to display while loading.
15932 * @cfg {String} region
15933 * Region to render component to (defaults to center)
15938 * @cfg {Array} items
15939 * A single item array - the first element is the root of the tree..
15940 * It's done this way to stay compatible with the Xtype system...
15946 * The method that retuns the tree of parts that make up this compoennt
15953 * render element to dom or tree
15954 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
15957 render : function(el)
15961 var hp = this.parent ? 1 : 0;
15962 Roo.debug && Roo.log(this);
15964 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
15965 // if parent is a '#.....' string, then let's use that..
15966 var ename = this.parent.substr(1);
15967 this.parent = false;
15968 Roo.debug && Roo.log(ename);
15970 case 'bootstrap-body' :
15971 if (typeof(Roo.bootstrap.Body) != 'undefined') {
15972 this.parent = { el : new Roo.bootstrap.Body() };
15973 Roo.debug && Roo.log("setting el to doc body");
15976 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
15980 this.parent = { el : true};
15983 el = Roo.get(ename);
15988 if (!el && !this.parent) {
15989 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
15993 Roo.debug && Roo.log("EL:");
15994 Roo.debug && Roo.log(el);
15995 Roo.debug && Roo.log("this.parent.el:");
15996 Roo.debug && Roo.log(this.parent.el);
15998 var tree = this._tree ? this._tree() : this.tree();
16000 // altertive root elements ??? - we need a better way to indicate these.
16001 var is_alt = (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
16002 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
16004 if (!this.parent && is_alt) {
16005 //el = Roo.get(document.body);
16006 this.parent = { el : true };
16011 if (!this.parent) {
16013 Roo.debug && Roo.log("no parent - creating one");
16015 el = el ? Roo.get(el) : false;
16017 // it's a top level one..
16019 el : new Roo.BorderLayout(el || document.body, {
16025 tabPosition: 'top',
16026 //resizeTabs: true,
16027 alwaysShowTabs: el && hp? false : true,
16028 hideTabs: el || !hp ? true : false,
16035 if (!this.parent.el) {
16036 // probably an old style ctor, which has been disabled.
16040 // The 'tree' method is '_tree now'
16042 tree.region = tree.region || this.region;
16044 if (this.parent.el === true) {
16045 // bootstrap... - body..
16046 this.parent.el = Roo.factory(tree);
16049 this.el = this.parent.el.addxtype(tree);
16050 this.fireEvent('built', this);
16052 this.panel = this.el;
16053 this.layout = this.panel.layout;
16054 this.parentLayout = this.parent.layout || false;
16060 Roo.apply(Roo.XComponent, {
16062 * @property hideProgress
16063 * true to disable the building progress bar.. usefull on single page renders.
16066 hideProgress : false,
16068 * @property buildCompleted
16069 * True when the builder has completed building the interface.
16072 buildCompleted : false,
16075 * @property topModule
16076 * the upper most module - uses document.element as it's constructor.
16083 * @property modules
16084 * array of modules to be created by registration system.
16085 * @type {Array} of Roo.XComponent
16090 * @property elmodules
16091 * array of modules to be created by which use #ID
16092 * @type {Array} of Roo.XComponent
16098 * @property build_from_html
16099 * Build elements from html - used by bootstrap HTML stuff
16100 * - this is cleared after build is completed
16101 * @type {boolean} true (default false)
16104 build_from_html : false,
16107 * Register components to be built later.
16109 * This solves the following issues
16110 * - Building is not done on page load, but after an authentication process has occured.
16111 * - Interface elements are registered on page load
16112 * - Parent Interface elements may not be loaded before child, so this handles that..
16119 module : 'Pman.Tab.projectMgr',
16121 parent : 'Pman.layout',
16122 disabled : false, // or use a function..
16125 * * @param {Object} details about module
16127 register : function(obj) {
16129 Roo.XComponent.event.fireEvent('register', obj);
16130 switch(typeof(obj.disabled) ) {
16136 if ( obj.disabled() ) {
16142 if (obj.disabled) {
16148 this.modules.push(obj);
16152 * convert a string to an object..
16153 * eg. 'AAA.BBB' -> finds AAA.BBB
16157 toObject : function(str)
16159 if (!str || typeof(str) == 'object') {
16162 if (str.substring(0,1) == '#') {
16166 var ar = str.split('.');
16171 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16173 throw "Module not found : " + str;
16177 throw "Module not found : " + str;
16179 Roo.each(ar, function(e) {
16180 if (typeof(o[e]) == 'undefined') {
16181 throw "Module not found : " + str;
16192 * move modules into their correct place in the tree..
16195 preBuild : function ()
16198 Roo.each(this.modules , function (obj)
16200 Roo.XComponent.event.fireEvent('beforebuild', obj);
16202 var opar = obj.parent;
16204 obj.parent = this.toObject(opar);
16206 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16211 Roo.debug && Roo.log("GOT top level module");
16212 Roo.debug && Roo.log(obj);
16213 obj.modules = new Roo.util.MixedCollection(false,
16214 function(o) { return o.order + '' }
16216 this.topModule = obj;
16219 // parent is a string (usually a dom element name..)
16220 if (typeof(obj.parent) == 'string') {
16221 this.elmodules.push(obj);
16224 if (obj.parent.constructor != Roo.XComponent) {
16225 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16227 if (!obj.parent.modules) {
16228 obj.parent.modules = new Roo.util.MixedCollection(false,
16229 function(o) { return o.order + '' }
16232 if (obj.parent.disabled) {
16233 obj.disabled = true;
16235 obj.parent.modules.add(obj);
16240 * make a list of modules to build.
16241 * @return {Array} list of modules.
16244 buildOrder : function()
16247 var cmp = function(a,b) {
16248 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16250 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16251 throw "No top level modules to build";
16254 // make a flat list in order of modules to build.
16255 var mods = this.topModule ? [ this.topModule ] : [];
16258 // elmodules (is a list of DOM based modules )
16259 Roo.each(this.elmodules, function(e) {
16261 if (!this.topModule &&
16262 typeof(e.parent) == 'string' &&
16263 e.parent.substring(0,1) == '#' &&
16264 Roo.get(e.parent.substr(1))
16267 _this.topModule = e;
16273 // add modules to their parents..
16274 var addMod = function(m) {
16275 Roo.debug && Roo.log("build Order: add: " + m.name);
16278 if (m.modules && !m.disabled) {
16279 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16280 m.modules.keySort('ASC', cmp );
16281 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16283 m.modules.each(addMod);
16285 Roo.debug && Roo.log("build Order: no child modules");
16287 // not sure if this is used any more..
16289 m.finalize.name = m.name + " (clean up) ";
16290 mods.push(m.finalize);
16294 if (this.topModule && this.topModule.modules) {
16295 this.topModule.modules.keySort('ASC', cmp );
16296 this.topModule.modules.each(addMod);
16302 * Build the registered modules.
16303 * @param {Object} parent element.
16304 * @param {Function} optional method to call after module has been added.
16308 build : function(opts)
16311 if (typeof(opts) != 'undefined') {
16312 Roo.apply(this,opts);
16316 var mods = this.buildOrder();
16318 //this.allmods = mods;
16319 //Roo.debug && Roo.log(mods);
16321 if (!mods.length) { // should not happen
16322 throw "NO modules!!!";
16326 var msg = "Building Interface...";
16327 // flash it up as modal - so we store the mask!?
16328 if (!this.hideProgress && Roo.MessageBox) {
16329 Roo.MessageBox.show({ title: 'loading' });
16330 Roo.MessageBox.show({
16331 title: "Please wait...",
16340 var total = mods.length;
16343 var progressRun = function() {
16344 if (!mods.length) {
16345 Roo.debug && Roo.log('hide?');
16346 if (!this.hideProgress && Roo.MessageBox) {
16347 Roo.MessageBox.hide();
16349 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16351 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16357 var m = mods.shift();
16360 Roo.debug && Roo.log(m);
16361 // not sure if this is supported any more.. - modules that are are just function
16362 if (typeof(m) == 'function') {
16364 return progressRun.defer(10, _this);
16368 msg = "Building Interface " + (total - mods.length) +
16370 (m.name ? (' - ' + m.name) : '');
16371 Roo.debug && Roo.log(msg);
16372 if (!this.hideProgress && Roo.MessageBox) {
16373 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16377 // is the module disabled?
16378 var disabled = (typeof(m.disabled) == 'function') ?
16379 m.disabled.call(m.module.disabled) : m.disabled;
16383 return progressRun(); // we do not update the display!
16391 // it's 10 on top level, and 1 on others??? why...
16392 return progressRun.defer(10, _this);
16395 progressRun.defer(1, _this);
16409 * wrapper for event.on - aliased later..
16410 * Typically use to register a event handler for register:
16412 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16421 Roo.XComponent.event = new Roo.util.Observable({
16425 * Fires when an Component is registered,
16426 * set the disable property on the Component to stop registration.
16427 * @param {Roo.XComponent} c the component being registerd.
16432 * @event beforebuild
16433 * Fires before each Component is built
16434 * can be used to apply permissions.
16435 * @param {Roo.XComponent} c the component being registerd.
16438 'beforebuild' : true,
16440 * @event buildcomplete
16441 * Fires on the top level element when all elements have been built
16442 * @param {Roo.XComponent} the top level component.
16444 'buildcomplete' : true
16449 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);