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 isGecko = !isSafari && ua.indexOf("gecko") > -1,
60 isBorderBox = isIE && !isStrict,
61 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
62 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
63 isLinux = (ua.indexOf("linux") != -1),
64 isSecure = window.location.href.toLowerCase().indexOf("https") === 0,
65 isTouch = (function() {
67 document.createEvent("TouchEvent");
74 // remove css image flicker
77 document.execCommand("BackgroundImageCache", false, true);
83 * True if the browser is in strict mode
88 * True if the page is running over SSL
93 * True when the document is fully initialized and ready for action
98 * Turn on debugging output (currently only the factory uses this)
105 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
108 enableGarbageCollector : true,
111 * True to automatically purge event listeners after uncaching an element (defaults to false).
112 * Note: this only happens if enableGarbageCollector is true.
115 enableListenerCollection:false,
118 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
119 * the IE insecure content warning (defaults to javascript:false).
122 SSL_SECURE_URL : "javascript:false",
125 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
126 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
129 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
131 emptyFn : function(){},
134 * Copies all the properties of config to obj if they don't already exist.
135 * @param {Object} obj The receiver of the properties
136 * @param {Object} config The source of the properties
137 * @return {Object} returns obj
139 applyIf : function(o, c){
142 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
149 * Applies event listeners to elements by selectors when the document is ready.
150 * The event name is specified with an @ suffix.
153 // add a listener for click on all anchors in element with id foo
154 '#foo a@click' : function(e, t){
158 // add the same listener to multiple selectors (separated by comma BEFORE the @)
159 '#foo a, #bar span.some-class@mouseover' : function(){
164 * @param {Object} obj The list of behaviors to apply
166 addBehaviors : function(o){
168 Roo.onReady(function(){
173 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
175 var parts = b.split('@');
176 if(parts[1]){ // for Object prototype breakers
179 cache[s] = Roo.select(s);
181 cache[s].on(parts[1], o[b]);
188 * Generates unique ids. If the element already has an id, it is unchanged
189 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
190 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
191 * @return {String} The generated Id.
193 id : function(el, prefix){
194 prefix = prefix || "roo-gen";
196 var id = prefix + (++idSeed);
197 return el ? (el.id ? el.id : (el.id = id)) : id;
202 * Extends one class with another class and optionally overrides members with the passed literal. This class
203 * also adds the function "override()" to the class that can be used to override
204 * members on an instance.
205 * @param {Object} subclass The class inheriting the functionality
206 * @param {Object} superclass The class being extended
207 * @param {Object} overrides (optional) A literal with members
212 var io = function(o){
217 return function(sb, sp, overrides){
218 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
221 sb = function(){sp.apply(this, arguments);};
223 var F = function(){}, sbp, spp = sp.prototype;
225 sbp = sb.prototype = new F();
229 if(spp.constructor == Object.prototype.constructor){
234 sb.override = function(o){
238 Roo.override(sb, overrides);
244 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
246 Roo.override(MyClass, {
247 newMethod1: function(){
250 newMethod2: function(foo){
255 * @param {Object} origclass The class to override
256 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
257 * containing one or more methods.
260 override : function(origclass, overrides){
262 var p = origclass.prototype;
263 for(var method in overrides){
264 p[method] = overrides[method];
269 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
271 Roo.namespace('Company', 'Company.data');
272 Company.Widget = function() { ... }
273 Company.data.CustomStore = function(config) { ... }
275 * @param {String} namespace1
276 * @param {String} namespace2
277 * @param {String} etc
280 namespace : function(){
281 var a=arguments, o=null, i, j, d, rt;
282 for (i=0; i<a.length; ++i) {
286 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
287 for (j=1; j<d.length; ++j) {
288 o[d[j]]=o[d[j]] || {};
294 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
296 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
297 Roo.factory(conf, Roo.data);
299 * @param {String} classname
300 * @param {String} namespace (optional)
304 factory : function(c, ns)
306 // no xtype, no ns or c.xns - or forced off by c.xns
307 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
310 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
311 if (c.constructor == ns[c.xtype]) {// already created...
315 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
316 var ret = new ns[c.xtype](c);
320 c.xns = false; // prevent recursion..
324 * Logs to console if it can.
326 * @param {String|Object} string
331 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
338 * 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.
342 urlEncode : function(o){
348 var ov = o[key], k = Roo.encodeURIComponent(key);
349 var type = typeof ov;
350 if(type == 'undefined'){
352 }else if(type != "function" && type != "object"){
353 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
354 }else if(ov instanceof Array){
356 for(var i = 0, len = ov.length; i < len; i++) {
357 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
368 * Safe version of encodeURIComponent
369 * @param {String} data
373 encodeURIComponent : function (data)
376 return encodeURIComponent(data);
377 } catch(e) {} // should be an uri encode error.
379 if (data == '' || data == null){
382 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
383 function nibble_to_hex(nibble){
384 var chars = '0123456789ABCDEF';
385 return chars.charAt(nibble);
387 data = data.toString();
389 for(var i=0; i<data.length; i++){
390 var c = data.charCodeAt(i);
391 var bs = new Array();
394 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
395 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
396 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
397 bs[3] = 0x80 | (c & 0x3F);
398 }else if (c > 0x800){
400 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
401 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
402 bs[2] = 0x80 | (c & 0x3F);
405 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
406 bs[1] = 0x80 | (c & 0x3F);
411 for(var j=0; j<bs.length; j++){
413 var hex = nibble_to_hex((b & 0xF0) >>> 4)
414 + nibble_to_hex(b &0x0F);
423 * 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]}.
424 * @param {String} string
425 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
426 * @return {Object} A literal with members
428 urlDecode : function(string, overwrite){
429 if(!string || !string.length){
433 var pairs = string.split('&');
434 var pair, name, value;
435 for(var i = 0, len = pairs.length; i < len; i++){
436 pair = pairs[i].split('=');
437 name = decodeURIComponent(pair[0]);
438 value = decodeURIComponent(pair[1]);
439 if(overwrite !== true){
440 if(typeof obj[name] == "undefined"){
442 }else if(typeof obj[name] == "string"){
443 obj[name] = [obj[name]];
444 obj[name].push(value);
446 obj[name].push(value);
456 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
457 * passed array is not really an array, your function is called once with it.
458 * The supplied function is called with (Object item, Number index, Array allItems).
459 * @param {Array/NodeList/Mixed} array
460 * @param {Function} fn
461 * @param {Object} scope
463 each : function(array, fn, scope){
464 if(typeof array.length == "undefined" || typeof array == "string"){
467 for(var i = 0, len = array.length; i < len; i++){
468 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
473 combine : function(){
474 var as = arguments, l = as.length, r = [];
475 for(var i = 0; i < l; i++){
477 if(a instanceof Array){
479 }else if(a.length !== undefined && !a.substr){
480 r = r.concat(Array.prototype.slice.call(a, 0));
489 * Escapes the passed string for use in a regular expression
490 * @param {String} str
493 escapeRe : function(s) {
494 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
498 callback : function(cb, scope, args, delay){
499 if(typeof cb == "function"){
501 cb.defer(delay, scope, args || []);
503 cb.apply(scope, args || []);
509 * Return the dom node for the passed string (id), dom node, or Roo.Element
510 * @param {String/HTMLElement/Roo.Element} el
511 * @return HTMLElement
513 getDom : function(el){
517 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
521 * Shorthand for {@link Roo.ComponentMgr#get}
523 * @return Roo.Component
525 getCmp : function(id){
526 return Roo.ComponentMgr.get(id);
529 num : function(v, defaultValue){
530 if(typeof v != 'number'){
536 destroy : function(){
537 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
541 as.removeAllListeners();
545 if(typeof as.purgeListeners == 'function'){
548 if(typeof as.destroy == 'function'){
555 // inpired by a similar function in mootools library
557 * Returns the type of object that is passed in. If the object passed in is null or undefined it
558 * return false otherwise it returns one of the following values:<ul>
559 * <li><b>string</b>: If the object passed is a string</li>
560 * <li><b>number</b>: If the object passed is a number</li>
561 * <li><b>boolean</b>: If the object passed is a boolean value</li>
562 * <li><b>function</b>: If the object passed is a function reference</li>
563 * <li><b>object</b>: If the object passed is an object</li>
564 * <li><b>array</b>: If the object passed is an array</li>
565 * <li><b>regexp</b>: If the object passed is a regular expression</li>
566 * <li><b>element</b>: If the object passed is a DOM Element</li>
567 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
568 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
569 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
570 * @param {Mixed} object
574 if(o === undefined || o === null){
581 if(t == 'object' && o.nodeName) {
583 case 1: return 'element';
584 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
587 if(t == 'object' || t == 'function') {
588 switch(o.constructor) {
589 case Array: return 'array';
590 case RegExp: return 'regexp';
592 if(typeof o.length == 'number' && typeof o.item == 'function') {
600 * Returns true if the passed value is null, undefined or an empty string (optional).
601 * @param {Mixed} value The value to test
602 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
605 isEmpty : function(v, allowBlank){
606 return v === null || v === undefined || (!allowBlank ? v === '' : false);
614 isFirefox : isFirefox,
622 isBorderBox : isBorderBox,
624 isWindows : isWindows,
633 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
634 * you may want to set this to true.
637 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
642 * Selects a single element as a Roo Element
643 * This is about as close as you can get to jQuery's $('do crazy stuff')
644 * @param {String} selector The selector/xpath query
645 * @param {Node} root (optional) The start of the query (defaults to document).
646 * @return {Roo.Element}
648 selectNode : function(selector, root)
650 var node = Roo.DomQuery.selectNode(selector,root);
651 return node ? Roo.get(node) : new Roo.Element(false);
659 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
660 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout",
663 "Roo.bootstrap.dash");
666 * Ext JS Library 1.1.1
667 * Copyright(c) 2006-2007, Ext JS, LLC.
669 * Originally Released Under LGPL - original licence link has changed is not relivant.
672 * <script type="text/javascript">
676 // wrappedn so fnCleanup is not in global scope...
678 function fnCleanUp() {
679 var p = Function.prototype;
680 delete p.createSequence;
682 delete p.createDelegate;
683 delete p.createCallback;
684 delete p.createInterceptor;
686 window.detachEvent("onunload", fnCleanUp);
688 window.attachEvent("onunload", fnCleanUp);
695 * These functions are available on every Function object (any JavaScript function).
697 Roo.apply(Function.prototype, {
699 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
700 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
701 * Will create a function that is bound to those 2 args.
702 * @return {Function} The new function
704 createCallback : function(/*args...*/){
705 // make args available, in function below
706 var args = arguments;
709 return method.apply(window, args);
714 * Creates a delegate (callback) that sets the scope to obj.
715 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
716 * Will create a function that is automatically scoped to this.
717 * @param {Object} obj (optional) The object for which the scope is set
718 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
719 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
720 * if a number the args are inserted at the specified position
721 * @return {Function} The new function
723 createDelegate : function(obj, args, appendArgs){
726 var callArgs = args || arguments;
727 if(appendArgs === true){
728 callArgs = Array.prototype.slice.call(arguments, 0);
729 callArgs = callArgs.concat(args);
730 }else if(typeof appendArgs == "number"){
731 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
732 var applyArgs = [appendArgs, 0].concat(args); // create method call params
733 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
735 return method.apply(obj || window, callArgs);
740 * Calls this function after the number of millseconds specified.
741 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
742 * @param {Object} obj (optional) The object for which the scope is set
743 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
744 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
745 * if a number the args are inserted at the specified position
746 * @return {Number} The timeout id that can be used with clearTimeout
748 defer : function(millis, obj, args, appendArgs){
749 var fn = this.createDelegate(obj, args, appendArgs);
751 return setTimeout(fn, millis);
757 * Create a combined function call sequence of the original function + the passed function.
758 * The resulting function returns the results of the original function.
759 * The passed fcn is called with the parameters of the original function
760 * @param {Function} fcn The function to sequence
761 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
762 * @return {Function} The new function
764 createSequence : function(fcn, scope){
765 if(typeof fcn != "function"){
770 var retval = method.apply(this || window, arguments);
771 fcn.apply(scope || this || window, arguments);
777 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
778 * The resulting function returns the results of the original function.
779 * The passed fcn is called with the parameters of the original function.
781 * @param {Function} fcn The function to call before the original
782 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
783 * @return {Function} The new function
785 createInterceptor : function(fcn, scope){
786 if(typeof fcn != "function"){
793 if(fcn.apply(scope || this || window, arguments) === false){
796 return method.apply(this || window, arguments);
802 * Ext JS Library 1.1.1
803 * Copyright(c) 2006-2007, Ext JS, LLC.
805 * Originally Released Under LGPL - original licence link has changed is not relivant.
808 * <script type="text/javascript">
811 Roo.applyIf(String, {
816 * Escapes the passed string for ' and \
817 * @param {String} string The string to escape
818 * @return {String} The escaped string
821 escape : function(string) {
822 return string.replace(/('|\\)/g, "\\$1");
826 * Pads the left side of a string with a specified character. This is especially useful
827 * for normalizing number and date strings. Example usage:
829 var s = String.leftPad('123', 5, '0');
830 // s now contains the string: '00123'
832 * @param {String} string The original string
833 * @param {Number} size The total length of the output string
834 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
835 * @return {String} The padded string
838 leftPad : function (val, size, ch) {
839 var result = new String(val);
840 if(ch === null || ch === undefined || ch === '') {
843 while (result.length < size) {
844 result = ch + result;
850 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
851 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
853 var cls = 'my-class', text = 'Some text';
854 var s = String.format('<div class="{0}">{1}</div>', cls, text);
855 // s now contains the string: '<div class="my-class">Some text</div>'
857 * @param {String} string The tokenized string to be formatted
858 * @param {String} value1 The value to replace token {0}
859 * @param {String} value2 Etc...
860 * @return {String} The formatted string
863 format : function(format){
864 var args = Array.prototype.slice.call(arguments, 1);
865 return format.replace(/\{(\d+)\}/g, function(m, i){
866 return Roo.util.Format.htmlEncode(args[i]);
872 * Utility function that allows you to easily switch a string between two alternating values. The passed value
873 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
874 * they are already different, the first value passed in is returned. Note that this method returns the new value
875 * but does not change the current string.
877 // alternate sort directions
878 sort = sort.toggle('ASC', 'DESC');
880 // instead of conditional logic:
881 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
883 * @param {String} value The value to compare to the current string
884 * @param {String} other The new value to use if the string already equals the first value passed in
885 * @return {String} The new value
888 String.prototype.toggle = function(value, other){
889 return this == value ? other : value;
892 * Ext JS Library 1.1.1
893 * Copyright(c) 2006-2007, Ext JS, LLC.
895 * Originally Released Under LGPL - original licence link has changed is not relivant.
898 * <script type="text/javascript">
904 Roo.applyIf(Number.prototype, {
906 * Checks whether or not the current number is within a desired range. If the number is already within the
907 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
908 * exceeded. Note that this method returns the constrained value but does not change the current number.
909 * @param {Number} min The minimum number in the range
910 * @param {Number} max The maximum number in the range
911 * @return {Number} The constrained value if outside the range, otherwise the current value
913 constrain : function(min, max){
914 return Math.min(Math.max(this, min), max);
918 * Ext JS Library 1.1.1
919 * Copyright(c) 2006-2007, Ext JS, LLC.
921 * Originally Released Under LGPL - original licence link has changed is not relivant.
924 * <script type="text/javascript">
929 Roo.applyIf(Array.prototype, {
932 * Checks whether or not the specified object exists in the array.
933 * @param {Object} o The object to check for
934 * @return {Number} The index of o in the array (or -1 if it is not found)
936 indexOf : function(o){
937 for (var i = 0, len = this.length; i < len; i++){
938 if(this[i] == o) return i;
944 * Removes the specified object from the array. If the object is not found nothing happens.
945 * @param {Object} o The object to remove
947 remove : function(o){
948 var index = this.indexOf(o);
950 this.splice(index, 1);
954 * Map (JS 1.6 compatibility)
955 * @param {Function} function to call
959 var len = this.length >>> 0;
960 if (typeof fun != "function")
961 throw new TypeError();
963 var res = new Array(len);
964 var thisp = arguments[1];
965 for (var i = 0; i < len; i++)
968 res[i] = fun.call(thisp, this[i], i, this);
979 * Ext JS Library 1.1.1
980 * Copyright(c) 2006-2007, Ext JS, LLC.
982 * Originally Released Under LGPL - original licence link has changed is not relivant.
985 * <script type="text/javascript">
991 * The date parsing and format syntax is a subset of
992 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
993 * supported will provide results equivalent to their PHP versions.
995 * Following is the list of all currently supported formats:
998 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
1000 Format Output Description
1001 ------ ---------- --------------------------------------------------------------
1002 d 10 Day of the month, 2 digits with leading zeros
1003 D Wed A textual representation of a day, three letters
1004 j 10 Day of the month without leading zeros
1005 l Wednesday A full textual representation of the day of the week
1006 S th English ordinal day of month suffix, 2 chars (use with j)
1007 w 3 Numeric representation of the day of the week
1008 z 9 The julian date, or day of the year (0-365)
1009 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
1010 F January A full textual representation of the month
1011 m 01 Numeric representation of a month, with leading zeros
1012 M Jan Month name abbreviation, three letters
1013 n 1 Numeric representation of a month, without leading zeros
1014 t 31 Number of days in the given month
1015 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
1016 Y 2007 A full numeric representation of a year, 4 digits
1017 y 07 A two digit representation of a year
1018 a pm Lowercase Ante meridiem and Post meridiem
1019 A PM Uppercase Ante meridiem and Post meridiem
1020 g 3 12-hour format of an hour without leading zeros
1021 G 15 24-hour format of an hour without leading zeros
1022 h 03 12-hour format of an hour with leading zeros
1023 H 15 24-hour format of an hour with leading zeros
1024 i 05 Minutes with leading zeros
1025 s 01 Seconds, with leading zeros
1026 O -0600 Difference to Greenwich time (GMT) in hours (Allows +08, without minutes)
1027 P -06:00 Difference to Greenwich time (GMT) with colon between hours and minutes
1028 T CST Timezone setting of the machine running the code
1029 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1032 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1034 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1035 document.write(dt.format('Y-m-d')); //2007-01-10
1036 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1037 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
1040 * Here are some standard date/time patterns that you might find helpful. They
1041 * are not part of the source of Date.js, but to use them you can simply copy this
1042 * block of code into any script that is included after Date.js and they will also become
1043 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1046 ISO8601Long:"Y-m-d H:i:s",
1047 ISO8601Short:"Y-m-d",
1049 LongDate: "l, F d, Y",
1050 FullDateTime: "l, F d, Y g:i:s A",
1053 LongTime: "g:i:s A",
1054 SortableDateTime: "Y-m-d\\TH:i:s",
1055 UniversalSortableDateTime: "Y-m-d H:i:sO",
1062 var dt = new Date();
1063 document.write(dt.format(Date.patterns.ShortDate));
1068 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1069 * They generate precompiled functions from date formats instead of parsing and
1070 * processing the pattern every time you format a date. These functions are available
1071 * on every Date object (any javascript function).
1073 * The original article and download are here:
1074 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1081 Returns the number of milliseconds between this date and date
1082 @param {Date} date (optional) Defaults to now
1083 @return {Number} The diff in milliseconds
1084 @member Date getElapsed
1086 Date.prototype.getElapsed = function(date) {
1087 return Math.abs((date || new Date()).getTime()-this.getTime());
1089 // was in date file..
1093 Date.parseFunctions = {count:0};
1095 Date.parseRegexes = [];
1097 Date.formatFunctions = {count:0};
1100 Date.prototype.dateFormat = function(format) {
1101 if (Date.formatFunctions[format] == null) {
1102 Date.createNewFormat(format);
1104 var func = Date.formatFunctions[format];
1105 return this[func]();
1110 * Formats a date given the supplied format string
1111 * @param {String} format The format string
1112 * @return {String} The formatted date
1115 Date.prototype.format = Date.prototype.dateFormat;
1118 Date.createNewFormat = function(format) {
1119 var funcName = "format" + Date.formatFunctions.count++;
1120 Date.formatFunctions[format] = funcName;
1121 var code = "Date.prototype." + funcName + " = function(){return ";
1122 var special = false;
1124 for (var i = 0; i < format.length; ++i) {
1125 ch = format.charAt(i);
1126 if (!special && ch == "\\") {
1131 code += "'" + String.escape(ch) + "' + ";
1134 code += Date.getFormatCode(ch);
1137 /** eval:var:zzzzzzzzzzzzz */
1138 eval(code.substring(0, code.length - 3) + ";}");
1142 Date.getFormatCode = function(character) {
1143 switch (character) {
1145 return "String.leftPad(this.getDate(), 2, '0') + ";
1147 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1149 return "this.getDate() + ";
1151 return "Date.dayNames[this.getDay()] + ";
1153 return "this.getSuffix() + ";
1155 return "this.getDay() + ";
1157 return "this.getDayOfYear() + ";
1159 return "this.getWeekOfYear() + ";
1161 return "Date.monthNames[this.getMonth()] + ";
1163 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1165 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1167 return "(this.getMonth() + 1) + ";
1169 return "this.getDaysInMonth() + ";
1171 return "(this.isLeapYear() ? 1 : 0) + ";
1173 return "this.getFullYear() + ";
1175 return "('' + this.getFullYear()).substring(2, 4) + ";
1177 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1179 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1181 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1183 return "this.getHours() + ";
1185 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1187 return "String.leftPad(this.getHours(), 2, '0') + ";
1189 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1191 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1193 return "this.getGMTOffset() + ";
1195 return "this.getGMTColonOffset() + ";
1197 return "this.getTimezone() + ";
1199 return "(this.getTimezoneOffset() * -60) + ";
1201 return "'" + String.escape(character) + "' + ";
1206 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1207 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1208 * the date format that is not specified will default to the current date value for that part. Time parts can also
1209 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1210 * string or the parse operation will fail.
1213 //dt = Fri May 25 2007 (current date)
1214 var dt = new Date();
1216 //dt = Thu May 25 2006 (today's month/day in 2006)
1217 dt = Date.parseDate("2006", "Y");
1219 //dt = Sun Jan 15 2006 (all date parts specified)
1220 dt = Date.parseDate("2006-1-15", "Y-m-d");
1222 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1223 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1225 * @param {String} input The unparsed date as a string
1226 * @param {String} format The format the date is in
1227 * @return {Date} The parsed date
1230 Date.parseDate = function(input, format) {
1231 if (Date.parseFunctions[format] == null) {
1232 Date.createParser(format);
1234 var func = Date.parseFunctions[format];
1235 return Date[func](input);
1241 Date.createParser = function(format) {
1242 var funcName = "parse" + Date.parseFunctions.count++;
1243 var regexNum = Date.parseRegexes.length;
1244 var currentGroup = 1;
1245 Date.parseFunctions[format] = funcName;
1247 var code = "Date." + funcName + " = function(input){\n"
1248 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1249 + "var d = new Date();\n"
1250 + "y = d.getFullYear();\n"
1251 + "m = d.getMonth();\n"
1252 + "d = d.getDate();\n"
1253 + "if (typeof(input) !== 'string') { input = input.toString(); }\n"
1254 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1255 + "if (results && results.length > 0) {";
1258 var special = false;
1260 for (var i = 0; i < format.length; ++i) {
1261 ch = format.charAt(i);
1262 if (!special && ch == "\\") {
1267 regex += String.escape(ch);
1270 var obj = Date.formatCodeToRegex(ch, currentGroup);
1271 currentGroup += obj.g;
1273 if (obj.g && obj.c) {
1279 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1280 + "{v = new Date(y, m, d, h, i, s);}\n"
1281 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1282 + "{v = new Date(y, m, d, h, i);}\n"
1283 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1284 + "{v = new Date(y, m, d, h);}\n"
1285 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1286 + "{v = new Date(y, m, d);}\n"
1287 + "else if (y >= 0 && m >= 0)\n"
1288 + "{v = new Date(y, m);}\n"
1289 + "else if (y >= 0)\n"
1290 + "{v = new Date(y);}\n"
1291 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1292 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1293 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1296 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1297 /** eval:var:zzzzzzzzzzzzz */
1302 Date.formatCodeToRegex = function(character, currentGroup) {
1303 switch (character) {
1307 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1310 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1311 s:"(\\d{1,2})"}; // day of month without leading zeroes
1314 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1315 s:"(\\d{2})"}; // day of month with leading zeroes
1319 s:"(?:" + Date.dayNames.join("|") + ")"};
1323 s:"(?:st|nd|rd|th)"};
1338 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1339 s:"(" + Date.monthNames.join("|") + ")"};
1342 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1343 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1346 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1347 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1350 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1351 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1362 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1366 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1367 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1371 c:"if (results[" + currentGroup + "] == 'am') {\n"
1372 + "if (h == 12) { h = 0; }\n"
1373 + "} else { if (h < 12) { h += 12; }}",
1377 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1378 + "if (h == 12) { h = 0; }\n"
1379 + "} else { if (h < 12) { h += 12; }}",
1384 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1385 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1389 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1390 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1393 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1397 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1402 "o = results[", currentGroup, "];\n",
1403 "var sn = o.substring(0,1);\n", // get + / - sign
1404 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1405 "var mn = o.substring(3,5) % 60;\n", // get minutes
1406 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1407 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1409 s:"([+\-]\\d{2,4})"};
1415 "o = results[", currentGroup, "];\n",
1416 "var sn = o.substring(0,1);\n",
1417 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(4,6) / 60);\n",
1418 "var mn = o.substring(4,6) % 60;\n",
1419 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n",
1420 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1426 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1429 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1430 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1431 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1435 s:String.escape(character)};
1440 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1441 * @return {String} The abbreviated timezone name (e.g. 'CST')
1443 Date.prototype.getTimezone = function() {
1444 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1448 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1449 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1451 Date.prototype.getGMTOffset = function() {
1452 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1453 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1454 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1458 * Get the offset from GMT of the current date (equivalent to the format specifier 'P').
1459 * @return {String} 2-characters representing hours and 2-characters representing minutes
1460 * seperated by a colon and prefixed with + or - (e.g. '-06:00')
1462 Date.prototype.getGMTColonOffset = function() {
1463 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1464 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1466 + String.leftPad(this.getTimezoneOffset() %60, 2, "0");
1470 * Get the numeric day number of the year, adjusted for leap year.
1471 * @return {Number} 0 through 364 (365 in leap years)
1473 Date.prototype.getDayOfYear = function() {
1475 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1476 for (var i = 0; i < this.getMonth(); ++i) {
1477 num += Date.daysInMonth[i];
1479 return num + this.getDate() - 1;
1483 * Get the string representation of the numeric week number of the year
1484 * (equivalent to the format specifier 'W').
1485 * @return {String} '00' through '52'
1487 Date.prototype.getWeekOfYear = function() {
1488 // Skip to Thursday of this week
1489 var now = this.getDayOfYear() + (4 - this.getDay());
1490 // Find the first Thursday of the year
1491 var jan1 = new Date(this.getFullYear(), 0, 1);
1492 var then = (7 - jan1.getDay() + 4);
1493 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1497 * Whether or not the current date is in a leap year.
1498 * @return {Boolean} True if the current date is in a leap year, else false
1500 Date.prototype.isLeapYear = function() {
1501 var year = this.getFullYear();
1502 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1506 * Get the first day of the current month, adjusted for leap year. The returned value
1507 * is the numeric day index within the week (0-6) which can be used in conjunction with
1508 * the {@link #monthNames} array to retrieve the textual day name.
1511 var dt = new Date('1/10/2007');
1512 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1514 * @return {Number} The day number (0-6)
1516 Date.prototype.getFirstDayOfMonth = function() {
1517 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1518 return (day < 0) ? (day + 7) : day;
1522 * Get the last day of the current month, adjusted for leap year. The returned value
1523 * is the numeric day index within the week (0-6) which can be used in conjunction with
1524 * the {@link #monthNames} array to retrieve the textual day name.
1527 var dt = new Date('1/10/2007');
1528 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1530 * @return {Number} The day number (0-6)
1532 Date.prototype.getLastDayOfMonth = function() {
1533 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1534 return (day < 0) ? (day + 7) : day;
1539 * Get the first date of this date's month
1542 Date.prototype.getFirstDateOfMonth = function() {
1543 return new Date(this.getFullYear(), this.getMonth(), 1);
1547 * Get the last date of this date's month
1550 Date.prototype.getLastDateOfMonth = function() {
1551 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1554 * Get the number of days in the current month, adjusted for leap year.
1555 * @return {Number} The number of days in the month
1557 Date.prototype.getDaysInMonth = function() {
1558 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1559 return Date.daysInMonth[this.getMonth()];
1563 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1564 * @return {String} 'st, 'nd', 'rd' or 'th'
1566 Date.prototype.getSuffix = function() {
1567 switch (this.getDate()) {
1584 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1587 * An array of textual month names.
1588 * Override these values for international dates, for example...
1589 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1608 * An array of textual day names.
1609 * Override these values for international dates, for example...
1610 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1626 Date.monthNumbers = {
1641 * Creates and returns a new Date instance with the exact same date value as the called instance.
1642 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1643 * variable will also be changed. When the intention is to create a new variable that will not
1644 * modify the original instance, you should create a clone.
1646 * Example of correctly cloning a date:
1649 var orig = new Date('10/1/2006');
1652 document.write(orig); //returns 'Thu Oct 05 2006'!
1655 var orig = new Date('10/1/2006');
1656 var copy = orig.clone();
1658 document.write(orig); //returns 'Thu Oct 01 2006'
1660 * @return {Date} The new Date instance
1662 Date.prototype.clone = function() {
1663 return new Date(this.getTime());
1667 * Clears any time information from this date
1668 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1669 @return {Date} this or the clone
1671 Date.prototype.clearTime = function(clone){
1673 return this.clone().clearTime();
1678 this.setMilliseconds(0);
1683 // safari setMonth is broken
1685 Date.brokenSetMonth = Date.prototype.setMonth;
1686 Date.prototype.setMonth = function(num){
1688 var n = Math.ceil(-num);
1689 var back_year = Math.ceil(n/12);
1690 var month = (n % 12) ? 12 - n % 12 : 0 ;
1691 this.setFullYear(this.getFullYear() - back_year);
1692 return Date.brokenSetMonth.call(this, month);
1694 return Date.brokenSetMonth.apply(this, arguments);
1699 /** Date interval constant
1703 /** Date interval constant
1707 /** Date interval constant
1711 /** Date interval constant
1715 /** Date interval constant
1719 /** Date interval constant
1723 /** Date interval constant
1729 * Provides a convenient method of performing basic date arithmetic. This method
1730 * does not modify the Date instance being called - it creates and returns
1731 * a new Date instance containing the resulting date value.
1736 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1737 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1739 //Negative values will subtract correctly:
1740 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1741 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1743 //You can even chain several calls together in one line!
1744 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1745 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1748 * @param {String} interval A valid date interval enum value
1749 * @param {Number} value The amount to add to the current date
1750 * @return {Date} The new Date instance
1752 Date.prototype.add = function(interval, value){
1753 var d = this.clone();
1754 if (!interval || value === 0) return d;
1755 switch(interval.toLowerCase()){
1757 d.setMilliseconds(this.getMilliseconds() + value);
1760 d.setSeconds(this.getSeconds() + value);
1763 d.setMinutes(this.getMinutes() + value);
1766 d.setHours(this.getHours() + value);
1769 d.setDate(this.getDate() + value);
1772 var day = this.getDate();
1774 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1777 d.setMonth(this.getMonth() + value);
1780 d.setFullYear(this.getFullYear() + value);
1787 * Ext JS Library 1.1.1
1788 * Copyright(c) 2006-2007, Ext JS, LLC.
1790 * Originally Released Under LGPL - original licence link has changed is not relivant.
1793 * <script type="text/javascript">
1797 * @class Roo.lib.Dom
1800 * Dom utils (from YIU afaik)
1805 * Get the view width
1806 * @param {Boolean} full True will get the full document, otherwise it's the view width
1807 * @return {Number} The width
1810 getViewWidth : function(full) {
1811 return full ? this.getDocumentWidth() : this.getViewportWidth();
1814 * Get the view height
1815 * @param {Boolean} full True will get the full document, otherwise it's the view height
1816 * @return {Number} The height
1818 getViewHeight : function(full) {
1819 return full ? this.getDocumentHeight() : this.getViewportHeight();
1822 getDocumentHeight: function() {
1823 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1824 return Math.max(scrollHeight, this.getViewportHeight());
1827 getDocumentWidth: function() {
1828 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1829 return Math.max(scrollWidth, this.getViewportWidth());
1832 getViewportHeight: function() {
1833 var height = self.innerHeight;
1834 var mode = document.compatMode;
1836 if ((mode || Roo.isIE) && !Roo.isOpera) {
1837 height = (mode == "CSS1Compat") ?
1838 document.documentElement.clientHeight :
1839 document.body.clientHeight;
1845 getViewportWidth: function() {
1846 var width = self.innerWidth;
1847 var mode = document.compatMode;
1849 if (mode || Roo.isIE) {
1850 width = (mode == "CSS1Compat") ?
1851 document.documentElement.clientWidth :
1852 document.body.clientWidth;
1857 isAncestor : function(p, c) {
1864 if (p.contains && !Roo.isSafari) {
1865 return p.contains(c);
1866 } else if (p.compareDocumentPosition) {
1867 return !!(p.compareDocumentPosition(c) & 16);
1869 var parent = c.parentNode;
1874 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1877 parent = parent.parentNode;
1883 getRegion : function(el) {
1884 return Roo.lib.Region.getRegion(el);
1887 getY : function(el) {
1888 return this.getXY(el)[1];
1891 getX : function(el) {
1892 return this.getXY(el)[0];
1895 getXY : function(el) {
1896 var p, pe, b, scroll, bd = document.body;
1897 el = Roo.getDom(el);
1898 var fly = Roo.lib.AnimBase.fly;
1899 if (el.getBoundingClientRect) {
1900 b = el.getBoundingClientRect();
1901 scroll = fly(document).getScroll();
1902 return [b.left + scroll.left, b.top + scroll.top];
1908 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1915 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1922 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1923 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1930 if (p != el && pe.getStyle('overflow') != 'visible') {
1938 if (Roo.isSafari && hasAbsolute) {
1943 if (Roo.isGecko && !hasAbsolute) {
1945 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1946 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1950 while (p && p != bd) {
1951 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1963 setXY : function(el, xy) {
1964 el = Roo.fly(el, '_setXY');
1966 var pts = el.translatePoints(xy);
1967 if (xy[0] !== false) {
1968 el.dom.style.left = pts.left + "px";
1970 if (xy[1] !== false) {
1971 el.dom.style.top = pts.top + "px";
1975 setX : function(el, x) {
1976 this.setXY(el, [x, false]);
1979 setY : function(el, y) {
1980 this.setXY(el, [false, y]);
1984 * Portions of this file are based on pieces of Yahoo User Interface Library
1985 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1986 * YUI licensed under the BSD License:
1987 * http://developer.yahoo.net/yui/license.txt
1988 * <script type="text/javascript">
1992 Roo.lib.Event = function() {
1993 var loadComplete = false;
1995 var unloadListeners = [];
1997 var onAvailStack = [];
1999 var lastError = null;
2012 startInterval: function() {
2013 if (!this._interval) {
2015 var callback = function() {
2016 self._tryPreloadAttach();
2018 this._interval = setInterval(callback, this.POLL_INTERVAL);
2023 onAvailable: function(p_id, p_fn, p_obj, p_override) {
2024 onAvailStack.push({ id: p_id,
2027 override: p_override,
2028 checkReady: false });
2030 retryCount = this.POLL_RETRYS;
2031 this.startInterval();
2035 addListener: function(el, eventName, fn) {
2036 el = Roo.getDom(el);
2041 if ("unload" == eventName) {
2042 unloadListeners[unloadListeners.length] =
2043 [el, eventName, fn];
2047 var wrappedFn = function(e) {
2048 return fn(Roo.lib.Event.getEvent(e));
2051 var li = [el, eventName, fn, wrappedFn];
2053 var index = listeners.length;
2054 listeners[index] = li;
2056 this.doAdd(el, eventName, wrappedFn, false);
2062 removeListener: function(el, eventName, fn) {
2065 el = Roo.getDom(el);
2068 return this.purgeElement(el, false, eventName);
2072 if ("unload" == eventName) {
2074 for (i = 0,len = unloadListeners.length; i < len; i++) {
2075 var li = unloadListeners[i];
2078 li[1] == eventName &&
2080 unloadListeners.splice(i, 1);
2088 var cacheItem = null;
2091 var index = arguments[3];
2093 if ("undefined" == typeof index) {
2094 index = this._getCacheIndex(el, eventName, fn);
2098 cacheItem = listeners[index];
2101 if (!el || !cacheItem) {
2105 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2107 delete listeners[index][this.WFN];
2108 delete listeners[index][this.FN];
2109 listeners.splice(index, 1);
2116 getTarget: function(ev, resolveTextNode) {
2117 ev = ev.browserEvent || ev;
2118 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2119 var t = ev.target || ev.srcElement;
2120 return this.resolveTextNode(t);
2124 resolveTextNode: function(node) {
2125 if (Roo.isSafari && node && 3 == node.nodeType) {
2126 return node.parentNode;
2133 getPageX: function(ev) {
2134 ev = ev.browserEvent || ev;
2135 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2137 if (!x && 0 !== x) {
2138 x = ev.clientX || 0;
2141 x += this.getScroll()[1];
2149 getPageY: function(ev) {
2150 ev = ev.browserEvent || ev;
2151 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2153 if (!y && 0 !== y) {
2154 y = ev.clientY || 0;
2157 y += this.getScroll()[0];
2166 getXY: function(ev) {
2167 ev = ev.browserEvent || ev;
2168 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2169 return [this.getPageX(ev), this.getPageY(ev)];
2173 getRelatedTarget: function(ev) {
2174 ev = ev.browserEvent || ev;
2175 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2176 var t = ev.relatedTarget;
2178 if (ev.type == "mouseout") {
2180 } else if (ev.type == "mouseover") {
2185 return this.resolveTextNode(t);
2189 getTime: function(ev) {
2190 ev = ev.browserEvent || ev;
2191 ev = ev.touches ? (ev.touches[0] || ev.changedTouches[0] || ev ) : ev;
2193 var t = new Date().getTime();
2197 this.lastError = ex;
2206 stopEvent: function(ev) {
2207 this.stopPropagation(ev);
2208 this.preventDefault(ev);
2212 stopPropagation: function(ev) {
2213 ev = ev.browserEvent || ev;
2214 if (ev.stopPropagation) {
2215 ev.stopPropagation();
2217 ev.cancelBubble = true;
2222 preventDefault: function(ev) {
2223 ev = ev.browserEvent || ev;
2224 if(ev.preventDefault) {
2225 ev.preventDefault();
2227 ev.returnValue = false;
2232 getEvent: function(e) {
2233 var ev = e || window.event;
2235 var c = this.getEvent.caller;
2237 ev = c.arguments[0];
2238 if (ev && Event == ev.constructor) {
2248 getCharCode: function(ev) {
2249 ev = ev.browserEvent || ev;
2250 return ev.charCode || ev.keyCode || 0;
2254 _getCacheIndex: function(el, eventName, fn) {
2255 for (var i = 0,len = listeners.length; i < len; ++i) {
2256 var li = listeners[i];
2258 li[this.FN] == fn &&
2259 li[this.EL] == el &&
2260 li[this.TYPE] == eventName) {
2272 getEl: function(id) {
2273 return document.getElementById(id);
2277 clearCache: function() {
2281 _load: function(e) {
2282 loadComplete = true;
2283 var EU = Roo.lib.Event;
2287 EU.doRemove(window, "load", EU._load);
2292 _tryPreloadAttach: function() {
2301 var tryAgain = !loadComplete;
2303 tryAgain = (retryCount > 0);
2308 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2309 var item = onAvailStack[i];
2311 var el = this.getEl(item.id);
2314 if (!item.checkReady ||
2317 (document && document.body)) {
2320 if (item.override) {
2321 if (item.override === true) {
2324 scope = item.override;
2327 item.fn.call(scope, item.obj);
2328 onAvailStack[i] = null;
2331 notAvail.push(item);
2336 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2340 this.startInterval();
2342 clearInterval(this._interval);
2343 this._interval = null;
2346 this.locked = false;
2353 purgeElement: function(el, recurse, eventName) {
2354 var elListeners = this.getListeners(el, eventName);
2356 for (var i = 0,len = elListeners.length; i < len; ++i) {
2357 var l = elListeners[i];
2358 this.removeListener(el, l.type, l.fn);
2362 if (recurse && el && el.childNodes) {
2363 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2364 this.purgeElement(el.childNodes[i], recurse, eventName);
2370 getListeners: function(el, eventName) {
2371 var results = [], searchLists;
2373 searchLists = [listeners, unloadListeners];
2374 } else if (eventName == "unload") {
2375 searchLists = [unloadListeners];
2377 searchLists = [listeners];
2380 for (var j = 0; j < searchLists.length; ++j) {
2381 var searchList = searchLists[j];
2382 if (searchList && searchList.length > 0) {
2383 for (var i = 0,len = searchList.length; i < len; ++i) {
2384 var l = searchList[i];
2385 if (l && l[this.EL] === el &&
2386 (!eventName || eventName === l[this.TYPE])) {
2391 adjust: l[this.ADJ_SCOPE],
2399 return (results.length) ? results : null;
2403 _unload: function(e) {
2405 var EU = Roo.lib.Event, i, j, l, len, index;
2407 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2408 l = unloadListeners[i];
2411 if (l[EU.ADJ_SCOPE]) {
2412 if (l[EU.ADJ_SCOPE] === true) {
2415 scope = l[EU.ADJ_SCOPE];
2418 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2419 unloadListeners[i] = null;
2425 unloadListeners = null;
2427 if (listeners && listeners.length > 0) {
2428 j = listeners.length;
2431 l = listeners[index];
2433 EU.removeListener(l[EU.EL], l[EU.TYPE],
2443 EU.doRemove(window, "unload", EU._unload);
2448 getScroll: function() {
2449 var dd = document.documentElement, db = document.body;
2450 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2451 return [dd.scrollTop, dd.scrollLeft];
2453 return [db.scrollTop, db.scrollLeft];
2460 doAdd: function () {
2461 if (window.addEventListener) {
2462 return function(el, eventName, fn, capture) {
2463 el.addEventListener(eventName, fn, (capture));
2465 } else if (window.attachEvent) {
2466 return function(el, eventName, fn, capture) {
2467 el.attachEvent("on" + eventName, fn);
2476 doRemove: function() {
2477 if (window.removeEventListener) {
2478 return function (el, eventName, fn, capture) {
2479 el.removeEventListener(eventName, fn, (capture));
2481 } else if (window.detachEvent) {
2482 return function (el, eventName, fn) {
2483 el.detachEvent("on" + eventName, fn);
2495 var E = Roo.lib.Event;
2496 E.on = E.addListener;
2497 E.un = E.removeListener;
2499 if (document && document.body) {
2502 E.doAdd(window, "load", E._load);
2504 E.doAdd(window, "unload", E._unload);
2505 E._tryPreloadAttach();
2509 * Portions of this file are based on pieces of Yahoo User Interface Library
2510 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2511 * YUI licensed under the BSD License:
2512 * http://developer.yahoo.net/yui/license.txt
2513 * <script type="text/javascript">
2519 * @class Roo.lib.Ajax
2526 request : function(method, uri, cb, data, options) {
2528 var hs = options.headers;
2531 if(hs.hasOwnProperty(h)){
2532 this.initHeader(h, hs[h], false);
2536 if(options.xmlData){
2537 this.initHeader('Content-Type', 'text/xml', false);
2539 data = options.xmlData;
2543 return this.asyncRequest(method, uri, cb, data);
2546 serializeForm : function(form) {
2547 if(typeof form == 'string') {
2548 form = (document.getElementById(form) || document.forms[form]);
2551 var el, name, val, disabled, data = '', hasSubmit = false;
2552 for (var i = 0; i < form.elements.length; i++) {
2553 el = form.elements[i];
2554 disabled = form.elements[i].disabled;
2555 name = form.elements[i].name;
2556 val = form.elements[i].value;
2558 if (!disabled && name){
2562 case 'select-multiple':
2563 for (var j = 0; j < el.options.length; j++) {
2564 if (el.options[j].selected) {
2566 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2569 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2577 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2590 if(hasSubmit == false) {
2591 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2596 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2601 data = data.substr(0, data.length - 1);
2609 useDefaultHeader:true,
2611 defaultPostHeader:'application/x-www-form-urlencoded',
2613 useDefaultXhrHeader:true,
2615 defaultXhrHeader:'XMLHttpRequest',
2617 hasDefaultHeaders:true,
2629 setProgId:function(id)
2631 this.activeX.unshift(id);
2634 setDefaultPostHeader:function(b)
2636 this.useDefaultHeader = b;
2639 setDefaultXhrHeader:function(b)
2641 this.useDefaultXhrHeader = b;
2644 setPollingInterval:function(i)
2646 if (typeof i == 'number' && isFinite(i)) {
2647 this.pollInterval = i;
2651 createXhrObject:function(transactionId)
2657 http = new XMLHttpRequest();
2659 obj = { conn:http, tId:transactionId };
2663 for (var i = 0; i < this.activeX.length; ++i) {
2667 http = new ActiveXObject(this.activeX[i]);
2669 obj = { conn:http, tId:transactionId };
2682 getConnectionObject:function()
2685 var tId = this.transactionId;
2689 o = this.createXhrObject(tId);
2691 this.transactionId++;
2702 asyncRequest:function(method, uri, callback, postData)
2704 var o = this.getConnectionObject();
2710 o.conn.open(method, uri, true);
2712 if (this.useDefaultXhrHeader) {
2713 if (!this.defaultHeaders['X-Requested-With']) {
2714 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2718 if(postData && this.useDefaultHeader){
2719 this.initHeader('Content-Type', this.defaultPostHeader);
2722 if (this.hasDefaultHeaders || this.hasHeaders) {
2726 this.handleReadyState(o, callback);
2727 o.conn.send(postData || null);
2733 handleReadyState:function(o, callback)
2737 if (callback && callback.timeout) {
2739 this.timeout[o.tId] = window.setTimeout(function() {
2740 oConn.abort(o, callback, true);
2741 }, callback.timeout);
2744 this.poll[o.tId] = window.setInterval(
2746 if (o.conn && o.conn.readyState == 4) {
2747 window.clearInterval(oConn.poll[o.tId]);
2748 delete oConn.poll[o.tId];
2750 if(callback && callback.timeout) {
2751 window.clearTimeout(oConn.timeout[o.tId]);
2752 delete oConn.timeout[o.tId];
2755 oConn.handleTransactionResponse(o, callback);
2758 , this.pollInterval);
2761 handleTransactionResponse:function(o, callback, isAbort)
2765 this.releaseObject(o);
2769 var httpStatus, responseObject;
2773 if (o.conn.status !== undefined && o.conn.status != 0) {
2774 httpStatus = o.conn.status;
2786 if (httpStatus >= 200 && httpStatus < 300) {
2787 responseObject = this.createResponseObject(o, callback.argument);
2788 if (callback.success) {
2789 if (!callback.scope) {
2790 callback.success(responseObject);
2795 callback.success.apply(callback.scope, [responseObject]);
2800 switch (httpStatus) {
2808 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2809 if (callback.failure) {
2810 if (!callback.scope) {
2811 callback.failure(responseObject);
2814 callback.failure.apply(callback.scope, [responseObject]);
2819 responseObject = this.createResponseObject(o, callback.argument);
2820 if (callback.failure) {
2821 if (!callback.scope) {
2822 callback.failure(responseObject);
2825 callback.failure.apply(callback.scope, [responseObject]);
2831 this.releaseObject(o);
2832 responseObject = null;
2835 createResponseObject:function(o, callbackArg)
2842 var headerStr = o.conn.getAllResponseHeaders();
2843 var header = headerStr.split('\n');
2844 for (var i = 0; i < header.length; i++) {
2845 var delimitPos = header[i].indexOf(':');
2846 if (delimitPos != -1) {
2847 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2855 obj.status = o.conn.status;
2856 obj.statusText = o.conn.statusText;
2857 obj.getResponseHeader = headerObj;
2858 obj.getAllResponseHeaders = headerStr;
2859 obj.responseText = o.conn.responseText;
2860 obj.responseXML = o.conn.responseXML;
2862 if (typeof callbackArg !== undefined) {
2863 obj.argument = callbackArg;
2869 createExceptionObject:function(tId, callbackArg, isAbort)
2872 var COMM_ERROR = 'communication failure';
2873 var ABORT_CODE = -1;
2874 var ABORT_ERROR = 'transaction aborted';
2880 obj.status = ABORT_CODE;
2881 obj.statusText = ABORT_ERROR;
2884 obj.status = COMM_CODE;
2885 obj.statusText = COMM_ERROR;
2889 obj.argument = callbackArg;
2895 initHeader:function(label, value, isDefault)
2897 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2899 if (headerObj[label] === undefined) {
2900 headerObj[label] = value;
2905 headerObj[label] = value + "," + headerObj[label];
2909 this.hasDefaultHeaders = true;
2912 this.hasHeaders = true;
2917 setHeader:function(o)
2919 if (this.hasDefaultHeaders) {
2920 for (var prop in this.defaultHeaders) {
2921 if (this.defaultHeaders.hasOwnProperty(prop)) {
2922 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2927 if (this.hasHeaders) {
2928 for (var prop in this.headers) {
2929 if (this.headers.hasOwnProperty(prop)) {
2930 o.conn.setRequestHeader(prop, this.headers[prop]);
2934 this.hasHeaders = false;
2938 resetDefaultHeaders:function() {
2939 delete this.defaultHeaders;
2940 this.defaultHeaders = {};
2941 this.hasDefaultHeaders = false;
2944 abort:function(o, callback, isTimeout)
2946 if(this.isCallInProgress(o)) {
2948 window.clearInterval(this.poll[o.tId]);
2949 delete this.poll[o.tId];
2951 delete this.timeout[o.tId];
2954 this.handleTransactionResponse(o, callback, true);
2964 isCallInProgress:function(o)
2967 return o.conn.readyState != 4 && o.conn.readyState != 0;
2976 releaseObject:function(o)
2985 'MSXML2.XMLHTTP.3.0',
2993 * Portions of this file are based on pieces of Yahoo User Interface Library
2994 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2995 * YUI licensed under the BSD License:
2996 * http://developer.yahoo.net/yui/license.txt
2997 * <script type="text/javascript">
3001 Roo.lib.Region = function(t, r, b, l) {
3011 Roo.lib.Region.prototype = {
3012 contains : function(region) {
3013 return ( region.left >= this.left &&
3014 region.right <= this.right &&
3015 region.top >= this.top &&
3016 region.bottom <= this.bottom );
3020 getArea : function() {
3021 return ( (this.bottom - this.top) * (this.right - this.left) );
3024 intersect : function(region) {
3025 var t = Math.max(this.top, region.top);
3026 var r = Math.min(this.right, region.right);
3027 var b = Math.min(this.bottom, region.bottom);
3028 var l = Math.max(this.left, region.left);
3030 if (b >= t && r >= l) {
3031 return new Roo.lib.Region(t, r, b, l);
3036 union : function(region) {
3037 var t = Math.min(this.top, region.top);
3038 var r = Math.max(this.right, region.right);
3039 var b = Math.max(this.bottom, region.bottom);
3040 var l = Math.min(this.left, region.left);
3042 return new Roo.lib.Region(t, r, b, l);
3045 adjust : function(t, l, b, r) {
3054 Roo.lib.Region.getRegion = function(el) {
3055 var p = Roo.lib.Dom.getXY(el);
3058 var r = p[0] + el.offsetWidth;
3059 var b = p[1] + el.offsetHeight;
3062 return new Roo.lib.Region(t, r, b, l);
3065 * Portions of this file are based on pieces of Yahoo User Interface Library
3066 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3067 * YUI licensed under the BSD License:
3068 * http://developer.yahoo.net/yui/license.txt
3069 * <script type="text/javascript">
3072 //@@dep Roo.lib.Region
3075 Roo.lib.Point = function(x, y) {
3076 if (x instanceof Array) {
3080 this.x = this.right = this.left = this[0] = x;
3081 this.y = this.top = this.bottom = this[1] = y;
3084 Roo.lib.Point.prototype = new Roo.lib.Region();
3086 * Portions of this file are based on pieces of Yahoo User Interface Library
3087 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3088 * YUI licensed under the BSD License:
3089 * http://developer.yahoo.net/yui/license.txt
3090 * <script type="text/javascript">
3097 scroll : function(el, args, duration, easing, cb, scope) {
3098 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3101 motion : function(el, args, duration, easing, cb, scope) {
3102 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3105 color : function(el, args, duration, easing, cb, scope) {
3106 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3109 run : function(el, args, duration, easing, cb, scope, type) {
3110 type = type || Roo.lib.AnimBase;
3111 if (typeof easing == "string") {
3112 easing = Roo.lib.Easing[easing];
3114 var anim = new type(el, args, duration, easing);
3115 anim.animateX(function() {
3116 Roo.callback(cb, scope);
3122 * Portions of this file are based on pieces of Yahoo User Interface Library
3123 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3124 * YUI licensed under the BSD License:
3125 * http://developer.yahoo.net/yui/license.txt
3126 * <script type="text/javascript">
3134 if (!libFlyweight) {
3135 libFlyweight = new Roo.Element.Flyweight();
3137 libFlyweight.dom = el;
3138 return libFlyweight;
3141 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3145 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3147 this.init(el, attributes, duration, method);
3151 Roo.lib.AnimBase.fly = fly;
3155 Roo.lib.AnimBase.prototype = {
3157 toString: function() {
3158 var el = this.getEl();
3159 var id = el.id || el.tagName;
3160 return ("Anim " + id);
3164 noNegatives: /width|height|opacity|padding/i,
3165 offsetAttribute: /^((width|height)|(top|left))$/,
3166 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3167 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3171 doMethod: function(attr, start, end) {
3172 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3176 setAttribute: function(attr, val, unit) {
3177 if (this.patterns.noNegatives.test(attr)) {
3178 val = (val > 0) ? val : 0;
3181 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3185 getAttribute: function(attr) {
3186 var el = this.getEl();
3187 var val = fly(el).getStyle(attr);
3189 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3190 return parseFloat(val);
3193 var a = this.patterns.offsetAttribute.exec(attr) || [];
3194 var pos = !!( a[3] );
3195 var box = !!( a[2] );
3198 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3199 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3208 getDefaultUnit: function(attr) {
3209 if (this.patterns.defaultUnit.test(attr)) {
3216 animateX : function(callback, scope) {
3217 var f = function() {
3218 this.onComplete.removeListener(f);
3219 if (typeof callback == "function") {
3220 callback.call(scope || this, this);
3223 this.onComplete.addListener(f, this);
3228 setRuntimeAttribute: function(attr) {
3231 var attributes = this.attributes;
3233 this.runtimeAttributes[attr] = {};
3235 var isset = function(prop) {
3236 return (typeof prop !== 'undefined');
3239 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3243 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3246 if (isset(attributes[attr]['to'])) {
3247 end = attributes[attr]['to'];
3248 } else if (isset(attributes[attr]['by'])) {
3249 if (start.constructor == Array) {
3251 for (var i = 0, len = start.length; i < len; ++i) {
3252 end[i] = start[i] + attributes[attr]['by'][i];
3255 end = start + attributes[attr]['by'];
3259 this.runtimeAttributes[attr].start = start;
3260 this.runtimeAttributes[attr].end = end;
3263 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3267 init: function(el, attributes, duration, method) {
3269 var isAnimated = false;
3272 var startTime = null;
3275 var actualFrames = 0;
3278 el = Roo.getDom(el);
3281 this.attributes = attributes || {};
3284 this.duration = duration || 1;
3287 this.method = method || Roo.lib.Easing.easeNone;
3290 this.useSeconds = true;
3293 this.currentFrame = 0;
3296 this.totalFrames = Roo.lib.AnimMgr.fps;
3299 this.getEl = function() {
3304 this.isAnimated = function() {
3309 this.getStartTime = function() {
3313 this.runtimeAttributes = {};
3316 this.animate = function() {
3317 if (this.isAnimated()) {
3321 this.currentFrame = 0;
3323 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3325 Roo.lib.AnimMgr.registerElement(this);
3329 this.stop = function(finish) {
3331 this.currentFrame = this.totalFrames;
3332 this._onTween.fire();
3334 Roo.lib.AnimMgr.stop(this);
3337 var onStart = function() {
3338 this.onStart.fire();
3340 this.runtimeAttributes = {};
3341 for (var attr in this.attributes) {
3342 this.setRuntimeAttribute(attr);
3347 startTime = new Date();
3351 var onTween = function() {
3353 duration: new Date() - this.getStartTime(),
3354 currentFrame: this.currentFrame
3357 data.toString = function() {
3359 'duration: ' + data.duration +
3360 ', currentFrame: ' + data.currentFrame
3364 this.onTween.fire(data);
3366 var runtimeAttributes = this.runtimeAttributes;
3368 for (var attr in runtimeAttributes) {
3369 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3375 var onComplete = function() {
3376 var actual_duration = (new Date() - startTime) / 1000 ;
3379 duration: actual_duration,
3380 frames: actualFrames,
3381 fps: actualFrames / actual_duration
3384 data.toString = function() {
3386 'duration: ' + data.duration +
3387 ', frames: ' + data.frames +
3388 ', fps: ' + data.fps
3394 this.onComplete.fire(data);
3398 this._onStart = new Roo.util.Event(this);
3399 this.onStart = new Roo.util.Event(this);
3400 this.onTween = new Roo.util.Event(this);
3401 this._onTween = new Roo.util.Event(this);
3402 this.onComplete = new Roo.util.Event(this);
3403 this._onComplete = new Roo.util.Event(this);
3404 this._onStart.addListener(onStart);
3405 this._onTween.addListener(onTween);
3406 this._onComplete.addListener(onComplete);
3411 * Portions of this file are based on pieces of Yahoo User Interface Library
3412 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3413 * YUI licensed under the BSD License:
3414 * http://developer.yahoo.net/yui/license.txt
3415 * <script type="text/javascript">
3419 Roo.lib.AnimMgr = new function() {
3436 this.registerElement = function(tween) {
3437 queue[queue.length] = tween;
3439 tween._onStart.fire();
3444 this.unRegister = function(tween, index) {
3445 tween._onComplete.fire();
3446 index = index || getIndex(tween);
3448 queue.splice(index, 1);
3452 if (tweenCount <= 0) {
3458 this.start = function() {
3459 if (thread === null) {
3460 thread = setInterval(this.run, this.delay);
3465 this.stop = function(tween) {
3467 clearInterval(thread);
3469 for (var i = 0, len = queue.length; i < len; ++i) {
3470 if (queue[0].isAnimated()) {
3471 this.unRegister(queue[0], 0);
3480 this.unRegister(tween);
3485 this.run = function() {
3486 for (var i = 0, len = queue.length; i < len; ++i) {
3487 var tween = queue[i];
3488 if (!tween || !tween.isAnimated()) {
3492 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3494 tween.currentFrame += 1;
3496 if (tween.useSeconds) {
3497 correctFrame(tween);
3499 tween._onTween.fire();
3502 Roo.lib.AnimMgr.stop(tween, i);
3507 var getIndex = function(anim) {
3508 for (var i = 0, len = queue.length; i < len; ++i) {
3509 if (queue[i] == anim) {
3517 var correctFrame = function(tween) {
3518 var frames = tween.totalFrames;
3519 var frame = tween.currentFrame;
3520 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3521 var elapsed = (new Date() - tween.getStartTime());
3524 if (elapsed < tween.duration * 1000) {
3525 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3527 tweak = frames - (frame + 1);
3529 if (tweak > 0 && isFinite(tweak)) {
3530 if (tween.currentFrame + tweak >= frames) {
3531 tweak = frames - (frame + 1);
3534 tween.currentFrame += tweak;
3540 * Portions of this file are based on pieces of Yahoo User Interface Library
3541 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3542 * YUI licensed under the BSD License:
3543 * http://developer.yahoo.net/yui/license.txt
3544 * <script type="text/javascript">
3547 Roo.lib.Bezier = new function() {
3549 this.getPosition = function(points, t) {
3550 var n = points.length;
3553 for (var i = 0; i < n; ++i) {
3554 tmp[i] = [points[i][0], points[i][1]];
3557 for (var j = 1; j < n; ++j) {
3558 for (i = 0; i < n - j; ++i) {
3559 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3560 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3564 return [ tmp[0][0], tmp[0][1] ];
3568 * Portions of this file are based on pieces of Yahoo User Interface Library
3569 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3570 * YUI licensed under the BSD License:
3571 * http://developer.yahoo.net/yui/license.txt
3572 * <script type="text/javascript">
3577 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3578 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3581 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3583 var fly = Roo.lib.AnimBase.fly;
3585 var superclass = Y.ColorAnim.superclass;
3586 var proto = Y.ColorAnim.prototype;
3588 proto.toString = function() {
3589 var el = this.getEl();
3590 var id = el.id || el.tagName;
3591 return ("ColorAnim " + id);
3594 proto.patterns.color = /color$/i;
3595 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3596 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3597 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3598 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3601 proto.parseColor = function(s) {
3602 if (s.length == 3) {
3606 var c = this.patterns.hex.exec(s);
3607 if (c && c.length == 4) {
3608 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3611 c = this.patterns.rgb.exec(s);
3612 if (c && c.length == 4) {
3613 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3616 c = this.patterns.hex3.exec(s);
3617 if (c && c.length == 4) {
3618 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3623 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3624 proto.getAttribute = function(attr) {
3625 var el = this.getEl();
3626 if (this.patterns.color.test(attr)) {
3627 var val = fly(el).getStyle(attr);
3629 if (this.patterns.transparent.test(val)) {
3630 var parent = el.parentNode;
3631 val = fly(parent).getStyle(attr);
3633 while (parent && this.patterns.transparent.test(val)) {
3634 parent = parent.parentNode;
3635 val = fly(parent).getStyle(attr);
3636 if (parent.tagName.toUpperCase() == 'HTML') {
3642 val = superclass.getAttribute.call(this, attr);
3647 proto.getAttribute = function(attr) {
3648 var el = this.getEl();
3649 if (this.patterns.color.test(attr)) {
3650 var val = fly(el).getStyle(attr);
3652 if (this.patterns.transparent.test(val)) {
3653 var parent = el.parentNode;
3654 val = fly(parent).getStyle(attr);
3656 while (parent && this.patterns.transparent.test(val)) {
3657 parent = parent.parentNode;
3658 val = fly(parent).getStyle(attr);
3659 if (parent.tagName.toUpperCase() == 'HTML') {
3665 val = superclass.getAttribute.call(this, attr);
3671 proto.doMethod = function(attr, start, end) {
3674 if (this.patterns.color.test(attr)) {
3676 for (var i = 0, len = start.length; i < len; ++i) {
3677 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3680 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3683 val = superclass.doMethod.call(this, attr, start, end);
3689 proto.setRuntimeAttribute = function(attr) {
3690 superclass.setRuntimeAttribute.call(this, attr);
3692 if (this.patterns.color.test(attr)) {
3693 var attributes = this.attributes;
3694 var start = this.parseColor(this.runtimeAttributes[attr].start);
3695 var end = this.parseColor(this.runtimeAttributes[attr].end);
3697 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3698 end = this.parseColor(attributes[attr].by);
3700 for (var i = 0, len = start.length; i < len; ++i) {
3701 end[i] = start[i] + end[i];
3705 this.runtimeAttributes[attr].start = start;
3706 this.runtimeAttributes[attr].end = end;
3712 * Portions of this file are based on pieces of Yahoo User Interface Library
3713 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3714 * YUI licensed under the BSD License:
3715 * http://developer.yahoo.net/yui/license.txt
3716 * <script type="text/javascript">
3722 easeNone: function (t, b, c, d) {
3723 return c * t / d + b;
3727 easeIn: function (t, b, c, d) {
3728 return c * (t /= d) * t + b;
3732 easeOut: function (t, b, c, d) {
3733 return -c * (t /= d) * (t - 2) + b;
3737 easeBoth: function (t, b, c, d) {
3738 if ((t /= d / 2) < 1) {
3739 return c / 2 * t * t + b;
3742 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3746 easeInStrong: function (t, b, c, d) {
3747 return c * (t /= d) * t * t * t + b;
3751 easeOutStrong: function (t, b, c, d) {
3752 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3756 easeBothStrong: function (t, b, c, d) {
3757 if ((t /= d / 2) < 1) {
3758 return c / 2 * t * t * t * t + b;
3761 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3766 elasticIn: function (t, b, c, d, a, p) {
3770 if ((t /= d) == 1) {
3777 if (!a || a < Math.abs(c)) {
3782 var s = p / (2 * Math.PI) * Math.asin(c / a);
3785 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3789 elasticOut: function (t, b, c, d, a, p) {
3793 if ((t /= d) == 1) {
3800 if (!a || a < Math.abs(c)) {
3805 var s = p / (2 * Math.PI) * Math.asin(c / a);
3808 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3812 elasticBoth: function (t, b, c, d, a, p) {
3817 if ((t /= d / 2) == 2) {
3825 if (!a || a < Math.abs(c)) {
3830 var s = p / (2 * Math.PI) * Math.asin(c / a);
3834 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3835 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3837 return a * Math.pow(2, -10 * (t -= 1)) *
3838 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3843 backIn: function (t, b, c, d, s) {
3844 if (typeof s == 'undefined') {
3847 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3851 backOut: function (t, b, c, d, s) {
3852 if (typeof s == 'undefined') {
3855 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3859 backBoth: function (t, b, c, d, s) {
3860 if (typeof s == 'undefined') {
3864 if ((t /= d / 2 ) < 1) {
3865 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3867 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3871 bounceIn: function (t, b, c, d) {
3872 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3876 bounceOut: function (t, b, c, d) {
3877 if ((t /= d) < (1 / 2.75)) {
3878 return c * (7.5625 * t * t) + b;
3879 } else if (t < (2 / 2.75)) {
3880 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3881 } else if (t < (2.5 / 2.75)) {
3882 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3884 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3888 bounceBoth: function (t, b, c, d) {
3890 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3892 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3895 * Portions of this file are based on pieces of Yahoo User Interface Library
3896 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3897 * YUI licensed under the BSD License:
3898 * http://developer.yahoo.net/yui/license.txt
3899 * <script type="text/javascript">
3903 Roo.lib.Motion = function(el, attributes, duration, method) {
3905 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3909 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3913 var superclass = Y.Motion.superclass;
3914 var proto = Y.Motion.prototype;
3916 proto.toString = function() {
3917 var el = this.getEl();
3918 var id = el.id || el.tagName;
3919 return ("Motion " + id);
3922 proto.patterns.points = /^points$/i;
3924 proto.setAttribute = function(attr, val, unit) {
3925 if (this.patterns.points.test(attr)) {
3926 unit = unit || 'px';
3927 superclass.setAttribute.call(this, 'left', val[0], unit);
3928 superclass.setAttribute.call(this, 'top', val[1], unit);
3930 superclass.setAttribute.call(this, attr, val, unit);
3934 proto.getAttribute = function(attr) {
3935 if (this.patterns.points.test(attr)) {
3937 superclass.getAttribute.call(this, 'left'),
3938 superclass.getAttribute.call(this, 'top')
3941 val = superclass.getAttribute.call(this, attr);
3947 proto.doMethod = function(attr, start, end) {
3950 if (this.patterns.points.test(attr)) {
3951 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3952 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3954 val = superclass.doMethod.call(this, attr, start, end);
3959 proto.setRuntimeAttribute = function(attr) {
3960 if (this.patterns.points.test(attr)) {
3961 var el = this.getEl();
3962 var attributes = this.attributes;
3964 var control = attributes['points']['control'] || [];
3968 if (control.length > 0 && !(control[0] instanceof Array)) {
3969 control = [control];
3972 for (i = 0,len = control.length; i < len; ++i) {
3973 tmp[i] = control[i];
3978 Roo.fly(el).position();
3980 if (isset(attributes['points']['from'])) {
3981 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3984 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3987 start = this.getAttribute('points');
3990 if (isset(attributes['points']['to'])) {
3991 end = translateValues.call(this, attributes['points']['to'], start);
3993 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3994 for (i = 0,len = control.length; i < len; ++i) {
3995 control[i] = translateValues.call(this, control[i], start);
3999 } else if (isset(attributes['points']['by'])) {
4000 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
4002 for (i = 0,len = control.length; i < len; ++i) {
4003 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
4007 this.runtimeAttributes[attr] = [start];
4009 if (control.length > 0) {
4010 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
4013 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
4016 superclass.setRuntimeAttribute.call(this, attr);
4020 var translateValues = function(val, start) {
4021 var pageXY = Roo.lib.Dom.getXY(this.getEl());
4022 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
4027 var isset = function(prop) {
4028 return (typeof prop !== 'undefined');
4032 * Portions of this file are based on pieces of Yahoo User Interface Library
4033 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
4034 * YUI licensed under the BSD License:
4035 * http://developer.yahoo.net/yui/license.txt
4036 * <script type="text/javascript">
4040 Roo.lib.Scroll = function(el, attributes, duration, method) {
4042 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
4046 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
4050 var superclass = Y.Scroll.superclass;
4051 var proto = Y.Scroll.prototype;
4053 proto.toString = function() {
4054 var el = this.getEl();
4055 var id = el.id || el.tagName;
4056 return ("Scroll " + id);
4059 proto.doMethod = function(attr, start, end) {
4062 if (attr == 'scroll') {
4064 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
4065 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
4069 val = superclass.doMethod.call(this, attr, start, end);
4074 proto.getAttribute = function(attr) {
4076 var el = this.getEl();
4078 if (attr == 'scroll') {
4079 val = [ el.scrollLeft, el.scrollTop ];
4081 val = superclass.getAttribute.call(this, attr);
4087 proto.setAttribute = function(attr, val, unit) {
4088 var el = this.getEl();
4090 if (attr == 'scroll') {
4091 el.scrollLeft = val[0];
4092 el.scrollTop = val[1];
4094 superclass.setAttribute.call(this, attr, val, unit);
4100 * Ext JS Library 1.1.1
4101 * Copyright(c) 2006-2007, Ext JS, LLC.
4103 * Originally Released Under LGPL - original licence link has changed is not relivant.
4106 * <script type="text/javascript">
4110 // nasty IE9 hack - what a pile of crap that is..
4112 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4113 Range.prototype.createContextualFragment = function (html) {
4114 var doc = window.document;
4115 var container = doc.createElement("div");
4116 container.innerHTML = html;
4117 var frag = doc.createDocumentFragment(), n;
4118 while ((n = container.firstChild)) {
4119 frag.appendChild(n);
4126 * @class Roo.DomHelper
4127 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4128 * 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>.
4131 Roo.DomHelper = function(){
4132 var tempTableEl = null;
4133 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4134 var tableRe = /^table|tbody|tr|td$/i;
4136 // build as innerHTML where available
4138 var createHtml = function(o){
4139 if(typeof o == 'string'){
4148 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4149 if(attr == "style"){
4151 if(typeof s == "function"){
4154 if(typeof s == "string"){
4155 b += ' style="' + s + '"';
4156 }else if(typeof s == "object"){
4159 if(typeof s[key] != "function"){
4160 b += key + ":" + s[key] + ";";
4167 b += ' class="' + o["cls"] + '"';
4168 }else if(attr == "htmlFor"){
4169 b += ' for="' + o["htmlFor"] + '"';
4171 b += " " + attr + '="' + o[attr] + '"';
4175 if(emptyTags.test(o.tag)){
4179 var cn = o.children || o.cn;
4181 //http://bugs.kde.org/show_bug.cgi?id=71506
4182 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4183 for(var i = 0, len = cn.length; i < len; i++) {
4184 b += createHtml(cn[i], b);
4187 b += createHtml(cn, b);
4193 b += "</" + o.tag + ">";
4200 var createDom = function(o, parentNode){
4202 // defininition craeted..
4204 if (o.ns && o.ns != 'html') {
4206 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4207 xmlns[o.ns] = o.xmlns;
4210 if (typeof(xmlns[o.ns]) == 'undefined') {
4211 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4217 if (typeof(o) == 'string') {
4218 return parentNode.appendChild(document.createTextNode(o));
4220 o.tag = o.tag || div;
4221 if (o.ns && Roo.isIE) {
4223 o.tag = o.ns + ':' + o.tag;
4226 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4227 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4230 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4231 attr == "style" || typeof o[attr] == "function") continue;
4233 if(attr=="cls" && Roo.isIE){
4234 el.className = o["cls"];
4236 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4237 else el[attr] = o[attr];
4240 Roo.DomHelper.applyStyles(el, o.style);
4241 var cn = o.children || o.cn;
4243 //http://bugs.kde.org/show_bug.cgi?id=71506
4244 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4245 for(var i = 0, len = cn.length; i < len; i++) {
4246 createDom(cn[i], el);
4253 el.innerHTML = o.html;
4256 parentNode.appendChild(el);
4261 var ieTable = function(depth, s, h, e){
4262 tempTableEl.innerHTML = [s, h, e].join('');
4263 var i = -1, el = tempTableEl;
4270 // kill repeat to save bytes
4274 tbe = '</tbody>'+te,
4280 * Nasty code for IE's broken table implementation
4282 var insertIntoTable = function(tag, where, el, html){
4284 tempTableEl = document.createElement('div');
4289 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4292 if(where == 'beforebegin'){
4296 before = el.nextSibling;
4299 node = ieTable(4, trs, html, tre);
4301 else if(tag == 'tr'){
4302 if(where == 'beforebegin'){
4305 node = ieTable(3, tbs, html, tbe);
4306 } else if(where == 'afterend'){
4307 before = el.nextSibling;
4309 node = ieTable(3, tbs, html, tbe);
4310 } else{ // INTO a TR
4311 if(where == 'afterbegin'){
4312 before = el.firstChild;
4314 node = ieTable(4, trs, html, tre);
4316 } else if(tag == 'tbody'){
4317 if(where == 'beforebegin'){
4320 node = ieTable(2, ts, html, te);
4321 } else if(where == 'afterend'){
4322 before = el.nextSibling;
4324 node = ieTable(2, ts, html, te);
4326 if(where == 'afterbegin'){
4327 before = el.firstChild;
4329 node = ieTable(3, tbs, html, tbe);
4332 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4335 if(where == 'afterbegin'){
4336 before = el.firstChild;
4338 node = ieTable(2, ts, html, te);
4340 el.insertBefore(node, before);
4345 /** True to force the use of DOM instead of html fragments @type Boolean */
4349 * Returns the markup for the passed Element(s) config
4350 * @param {Object} o The Dom object spec (and children)
4353 markup : function(o){
4354 return createHtml(o);
4358 * Applies a style specification to an element
4359 * @param {String/HTMLElement} el The element to apply styles to
4360 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4361 * a function which returns such a specification.
4363 applyStyles : function(el, styles){
4366 if(typeof styles == "string"){
4367 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4369 while ((matches = re.exec(styles)) != null){
4370 el.setStyle(matches[1], matches[2]);
4372 }else if (typeof styles == "object"){
4373 for (var style in styles){
4374 el.setStyle(style, styles[style]);
4376 }else if (typeof styles == "function"){
4377 Roo.DomHelper.applyStyles(el, styles.call());
4383 * Inserts an HTML fragment into the Dom
4384 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4385 * @param {HTMLElement} el The context element
4386 * @param {String} html The HTML fragmenet
4387 * @return {HTMLElement} The new node
4389 insertHtml : function(where, el, html){
4390 where = where.toLowerCase();
4391 if(el.insertAdjacentHTML){
4392 if(tableRe.test(el.tagName)){
4394 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4400 el.insertAdjacentHTML('BeforeBegin', html);
4401 return el.previousSibling;
4403 el.insertAdjacentHTML('AfterBegin', html);
4404 return el.firstChild;
4406 el.insertAdjacentHTML('BeforeEnd', html);
4407 return el.lastChild;
4409 el.insertAdjacentHTML('AfterEnd', html);
4410 return el.nextSibling;
4412 throw 'Illegal insertion point -> "' + where + '"';
4414 var range = el.ownerDocument.createRange();
4418 range.setStartBefore(el);
4419 frag = range.createContextualFragment(html);
4420 el.parentNode.insertBefore(frag, el);
4421 return el.previousSibling;
4424 range.setStartBefore(el.firstChild);
4425 frag = range.createContextualFragment(html);
4426 el.insertBefore(frag, el.firstChild);
4427 return el.firstChild;
4429 el.innerHTML = html;
4430 return el.firstChild;
4434 range.setStartAfter(el.lastChild);
4435 frag = range.createContextualFragment(html);
4436 el.appendChild(frag);
4437 return el.lastChild;
4439 el.innerHTML = html;
4440 return el.lastChild;
4443 range.setStartAfter(el);
4444 frag = range.createContextualFragment(html);
4445 el.parentNode.insertBefore(frag, el.nextSibling);
4446 return el.nextSibling;
4448 throw 'Illegal insertion point -> "' + where + '"';
4452 * Creates new Dom element(s) and inserts them before el
4453 * @param {String/HTMLElement/Element} el The context element
4454 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4455 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4456 * @return {HTMLElement/Roo.Element} The new node
4458 insertBefore : function(el, o, returnElement){
4459 return this.doInsert(el, o, returnElement, "beforeBegin");
4463 * Creates new Dom element(s) and inserts them after el
4464 * @param {String/HTMLElement/Element} el The context element
4465 * @param {Object} o The Dom object spec (and children)
4466 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4467 * @return {HTMLElement/Roo.Element} The new node
4469 insertAfter : function(el, o, returnElement){
4470 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4474 * Creates new Dom element(s) and inserts them as the first child of el
4475 * @param {String/HTMLElement/Element} el The context element
4476 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4477 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4478 * @return {HTMLElement/Roo.Element} The new node
4480 insertFirst : function(el, o, returnElement){
4481 return this.doInsert(el, o, returnElement, "afterBegin");
4485 doInsert : function(el, o, returnElement, pos, sibling){
4486 el = Roo.getDom(el);
4488 if(this.useDom || o.ns){
4489 newNode = createDom(o, null);
4490 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4492 var html = createHtml(o);
4493 newNode = this.insertHtml(pos, el, html);
4495 return returnElement ? Roo.get(newNode, true) : newNode;
4499 * Creates new Dom element(s) and appends them to el
4500 * @param {String/HTMLElement/Element} el The context element
4501 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4502 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4503 * @return {HTMLElement/Roo.Element} The new node
4505 append : function(el, o, returnElement){
4506 el = Roo.getDom(el);
4508 if(this.useDom || o.ns){
4509 newNode = createDom(o, null);
4510 el.appendChild(newNode);
4512 var html = createHtml(o);
4513 newNode = this.insertHtml("beforeEnd", el, html);
4515 return returnElement ? Roo.get(newNode, true) : newNode;
4519 * Creates new Dom element(s) and overwrites the contents of el with them
4520 * @param {String/HTMLElement/Element} el The context element
4521 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4522 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4523 * @return {HTMLElement/Roo.Element} The new node
4525 overwrite : function(el, o, returnElement){
4526 el = Roo.getDom(el);
4529 while (el.childNodes.length) {
4530 el.removeChild(el.firstChild);
4534 el.innerHTML = createHtml(o);
4537 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4541 * Creates a new Roo.DomHelper.Template from the Dom object spec
4542 * @param {Object} o The Dom object spec (and children)
4543 * @return {Roo.DomHelper.Template} The new template
4545 createTemplate : function(o){
4546 var html = createHtml(o);
4547 return new Roo.Template(html);
4553 * Ext JS Library 1.1.1
4554 * Copyright(c) 2006-2007, Ext JS, LLC.
4556 * Originally Released Under LGPL - original licence link has changed is not relivant.
4559 * <script type="text/javascript">
4563 * @class Roo.Template
4564 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4565 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4568 var t = new Roo.Template({
4569 html : '<div name="{id}">' +
4570 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4572 myformat: function (value, allValues) {
4573 return 'XX' + value;
4576 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4578 * For more information see this blog post with examples:
4579 * <a href="http://www.cnitblog.com/seeyeah/archive/2011/12/30/38728.html/">DomHelper
4580 - Create Elements using DOM, HTML fragments and Templates</a>.
4582 * @param {Object} cfg - Configuration object.
4584 Roo.Template = function(cfg){
4586 if(cfg instanceof Array){
4588 }else if(arguments.length > 1){
4589 cfg = Array.prototype.join.call(arguments, "");
4593 if (typeof(cfg) == 'object') {
4604 Roo.Template.prototype = {
4607 * @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..
4608 * it should be fixed so that template is observable...
4612 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4616 * Returns an HTML fragment of this template with the specified values applied.
4617 * @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'})
4618 * @return {String} The HTML fragment
4620 applyTemplate : function(values){
4624 return this.compiled(values);
4626 var useF = this.disableFormats !== true;
4627 var fm = Roo.util.Format, tpl = this;
4628 var fn = function(m, name, format, args){
4630 if(format.substr(0, 5) == "this."){
4631 return tpl.call(format.substr(5), values[name], values);
4634 // quoted values are required for strings in compiled templates,
4635 // but for non compiled we need to strip them
4636 // quoted reversed for jsmin
4637 var re = /^\s*['"](.*)["']\s*$/;
4638 args = args.split(',');
4639 for(var i = 0, len = args.length; i < len; i++){
4640 args[i] = args[i].replace(re, "$1");
4642 args = [values[name]].concat(args);
4644 args = [values[name]];
4646 return fm[format].apply(fm, args);
4649 return values[name] !== undefined ? values[name] : "";
4652 return this.html.replace(this.re, fn);
4670 this.loading = true;
4671 this.compiled = false;
4673 var cx = new Roo.data.Connection();
4677 success : function (response) {
4679 _t.html = response.responseText;
4683 failure : function(response) {
4684 Roo.log("Template failed to load from " + _t.url);
4691 * Sets the HTML used as the template and optionally compiles it.
4692 * @param {String} html
4693 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4694 * @return {Roo.Template} this
4696 set : function(html, compile){
4698 this.compiled = null;
4706 * True to disable format functions (defaults to false)
4709 disableFormats : false,
4712 * The regular expression used to match template variables
4716 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4719 * Compiles the template into an internal function, eliminating the RegEx overhead.
4720 * @return {Roo.Template} this
4722 compile : function(){
4723 var fm = Roo.util.Format;
4724 var useF = this.disableFormats !== true;
4725 var sep = Roo.isGecko ? "+" : ",";
4726 var fn = function(m, name, format, args){
4728 args = args ? ',' + args : "";
4729 if(format.substr(0, 5) != "this."){
4730 format = "fm." + format + '(';
4732 format = 'this.call("'+ format.substr(5) + '", ';
4736 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4738 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4741 // branched to use + in gecko and [].join() in others
4743 body = "this.compiled = function(values){ return '" +
4744 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4747 body = ["this.compiled = function(values){ return ['"];
4748 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4749 body.push("'].join('');};");
4750 body = body.join('');
4760 // private function used to call members
4761 call : function(fnName, value, allValues){
4762 return this[fnName](value, allValues);
4766 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4767 * @param {String/HTMLElement/Roo.Element} el The context element
4768 * @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'})
4769 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4770 * @return {HTMLElement/Roo.Element} The new node or Element
4772 insertFirst: function(el, values, returnElement){
4773 return this.doInsert('afterBegin', el, values, returnElement);
4777 * Applies the supplied values to the template and inserts the new node(s) before el.
4778 * @param {String/HTMLElement/Roo.Element} el The context element
4779 * @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'})
4780 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4781 * @return {HTMLElement/Roo.Element} The new node or Element
4783 insertBefore: function(el, values, returnElement){
4784 return this.doInsert('beforeBegin', el, values, returnElement);
4788 * Applies the supplied values to the template and inserts the new node(s) after el.
4789 * @param {String/HTMLElement/Roo.Element} el The context element
4790 * @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'})
4791 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4792 * @return {HTMLElement/Roo.Element} The new node or Element
4794 insertAfter : function(el, values, returnElement){
4795 return this.doInsert('afterEnd', el, values, returnElement);
4799 * Applies the supplied values to the template and appends the new node(s) to el.
4800 * @param {String/HTMLElement/Roo.Element} el The context element
4801 * @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'})
4802 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4803 * @return {HTMLElement/Roo.Element} The new node or Element
4805 append : function(el, values, returnElement){
4806 return this.doInsert('beforeEnd', el, values, returnElement);
4809 doInsert : function(where, el, values, returnEl){
4810 el = Roo.getDom(el);
4811 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4812 return returnEl ? Roo.get(newNode, true) : newNode;
4816 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4817 * @param {String/HTMLElement/Roo.Element} el The context element
4818 * @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'})
4819 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4820 * @return {HTMLElement/Roo.Element} The new node or Element
4822 overwrite : function(el, values, returnElement){
4823 el = Roo.getDom(el);
4824 el.innerHTML = this.applyTemplate(values);
4825 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4829 * Alias for {@link #applyTemplate}
4832 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4835 Roo.DomHelper.Template = Roo.Template;
4838 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4839 * @param {String/HTMLElement} el A DOM element or its id
4840 * @returns {Roo.Template} The created template
4843 Roo.Template.from = function(el){
4844 el = Roo.getDom(el);
4845 return new Roo.Template(el.value || el.innerHTML);
4848 * Ext JS Library 1.1.1
4849 * Copyright(c) 2006-2007, Ext JS, LLC.
4851 * Originally Released Under LGPL - original licence link has changed is not relivant.
4854 * <script type="text/javascript">
4859 * This is code is also distributed under MIT license for use
4860 * with jQuery and prototype JavaScript libraries.
4863 * @class Roo.DomQuery
4864 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).
4866 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>
4869 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.
4871 <h4>Element Selectors:</h4>
4873 <li> <b>*</b> any element</li>
4874 <li> <b>E</b> an element with the tag E</li>
4875 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4876 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4877 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4878 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4880 <h4>Attribute Selectors:</h4>
4881 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4883 <li> <b>E[foo]</b> has an attribute "foo"</li>
4884 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4885 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4886 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4887 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4888 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4889 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4891 <h4>Pseudo Classes:</h4>
4893 <li> <b>E:first-child</b> E is the first child of its parent</li>
4894 <li> <b>E:last-child</b> E is the last child of its parent</li>
4895 <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>
4896 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4897 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4898 <li> <b>E:only-child</b> E is the only child of its parent</li>
4899 <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>
4900 <li> <b>E:first</b> the first E in the resultset</li>
4901 <li> <b>E:last</b> the last E in the resultset</li>
4902 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4903 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4904 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4905 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4906 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4907 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4908 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4909 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4910 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4912 <h4>CSS Value Selectors:</h4>
4914 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4915 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4916 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4917 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4918 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4919 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4923 Roo.DomQuery = function(){
4924 var cache = {}, simpleCache = {}, valueCache = {};
4925 var nonSpace = /\S/;
4926 var trimRe = /^\s+|\s+$/g;
4927 var tplRe = /\{(\d+)\}/g;
4928 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4929 var tagTokenRe = /^(#)?([\w-\*]+)/;
4930 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4932 function child(p, index){
4934 var n = p.firstChild;
4936 if(n.nodeType == 1){
4947 while((n = n.nextSibling) && n.nodeType != 1);
4952 while((n = n.previousSibling) && n.nodeType != 1);
4956 function children(d){
4957 var n = d.firstChild, ni = -1;
4959 var nx = n.nextSibling;
4960 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4970 function byClassName(c, a, v){
4974 var r = [], ri = -1, cn;
4975 for(var i = 0, ci; ci = c[i]; i++){
4976 if((' '+ci.className+' ').indexOf(v) != -1){
4983 function attrValue(n, attr){
4984 if(!n.tagName && typeof n.length != "undefined"){
4993 if(attr == "class" || attr == "className"){
4996 return n.getAttribute(attr) || n[attr];
5000 function getNodes(ns, mode, tagName){
5001 var result = [], ri = -1, cs;
5005 tagName = tagName || "*";
5006 if(typeof ns.getElementsByTagName != "undefined"){
5010 for(var i = 0, ni; ni = ns[i]; i++){
5011 cs = ni.getElementsByTagName(tagName);
5012 for(var j = 0, ci; ci = cs[j]; j++){
5016 }else if(mode == "/" || mode == ">"){
5017 var utag = tagName.toUpperCase();
5018 for(var i = 0, ni, cn; ni = ns[i]; i++){
5019 cn = ni.children || ni.childNodes;
5020 for(var j = 0, cj; cj = cn[j]; j++){
5021 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
5026 }else if(mode == "+"){
5027 var utag = tagName.toUpperCase();
5028 for(var i = 0, n; n = ns[i]; i++){
5029 while((n = n.nextSibling) && n.nodeType != 1);
5030 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
5034 }else if(mode == "~"){
5035 for(var i = 0, n; n = ns[i]; i++){
5036 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
5045 function concat(a, b){
5049 for(var i = 0, l = b.length; i < l; i++){
5055 function byTag(cs, tagName){
5056 if(cs.tagName || cs == document){
5062 var r = [], ri = -1;
5063 tagName = tagName.toLowerCase();
5064 for(var i = 0, ci; ci = cs[i]; i++){
5065 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
5072 function byId(cs, attr, id){
5073 if(cs.tagName || cs == document){
5079 var r = [], ri = -1;
5080 for(var i = 0,ci; ci = cs[i]; i++){
5081 if(ci && ci.id == id){
5089 function byAttribute(cs, attr, value, op, custom){
5090 var r = [], ri = -1, st = custom=="{";
5091 var f = Roo.DomQuery.operators[op];
5092 for(var i = 0, ci; ci = cs[i]; i++){
5095 a = Roo.DomQuery.getStyle(ci, attr);
5097 else if(attr == "class" || attr == "className"){
5099 }else if(attr == "for"){
5101 }else if(attr == "href"){
5102 a = ci.getAttribute("href", 2);
5104 a = ci.getAttribute(attr);
5106 if((f && f(a, value)) || (!f && a)){
5113 function byPseudo(cs, name, value){
5114 return Roo.DomQuery.pseudos[name](cs, value);
5117 // This is for IE MSXML which does not support expandos.
5118 // IE runs the same speed using setAttribute, however FF slows way down
5119 // and Safari completely fails so they need to continue to use expandos.
5120 var isIE = window.ActiveXObject ? true : false;
5122 // this eval is stop the compressor from
5123 // renaming the variable to something shorter
5125 /** eval:var:batch */
5130 function nodupIEXml(cs){
5132 cs[0].setAttribute("_nodup", d);
5134 for(var i = 1, len = cs.length; i < len; i++){
5136 if(!c.getAttribute("_nodup") != d){
5137 c.setAttribute("_nodup", d);
5141 for(var i = 0, len = cs.length; i < len; i++){
5142 cs[i].removeAttribute("_nodup");
5151 var len = cs.length, c, i, r = cs, cj, ri = -1;
5152 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5155 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5156 return nodupIEXml(cs);
5160 for(i = 1; c = cs[i]; i++){
5165 for(var j = 0; j < i; j++){
5168 for(j = i+1; cj = cs[j]; j++){
5180 function quickDiffIEXml(c1, c2){
5182 for(var i = 0, len = c1.length; i < len; i++){
5183 c1[i].setAttribute("_qdiff", d);
5186 for(var i = 0, len = c2.length; i < len; i++){
5187 if(c2[i].getAttribute("_qdiff") != d){
5188 r[r.length] = c2[i];
5191 for(var i = 0, len = c1.length; i < len; i++){
5192 c1[i].removeAttribute("_qdiff");
5197 function quickDiff(c1, c2){
5198 var len1 = c1.length;
5202 if(isIE && c1[0].selectSingleNode){
5203 return quickDiffIEXml(c1, c2);
5206 for(var i = 0; i < len1; i++){
5210 for(var i = 0, len = c2.length; i < len; i++){
5211 if(c2[i]._qdiff != d){
5212 r[r.length] = c2[i];
5218 function quickId(ns, mode, root, id){
5220 var d = root.ownerDocument || root;
5221 return d.getElementById(id);
5223 ns = getNodes(ns, mode, "*");
5224 return byId(ns, null, id);
5228 getStyle : function(el, name){
5229 return Roo.fly(el).getStyle(name);
5232 * Compiles a selector/xpath query into a reusable function. The returned function
5233 * takes one parameter "root" (optional), which is the context node from where the query should start.
5234 * @param {String} selector The selector/xpath query
5235 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5236 * @return {Function}
5238 compile : function(path, type){
5239 type = type || "select";
5241 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5242 var q = path, mode, lq;
5243 var tk = Roo.DomQuery.matchers;
5244 var tklen = tk.length;
5247 // accept leading mode switch
5248 var lmode = q.match(modeRe);
5249 if(lmode && lmode[1]){
5250 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5251 q = q.replace(lmode[1], "");
5253 // strip leading slashes
5254 while(path.substr(0, 1)=="/"){
5255 path = path.substr(1);
5258 while(q && lq != q){
5260 var tm = q.match(tagTokenRe);
5261 if(type == "select"){
5264 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5266 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5268 q = q.replace(tm[0], "");
5269 }else if(q.substr(0, 1) != '@'){
5270 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5275 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5277 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5279 q = q.replace(tm[0], "");
5282 while(!(mm = q.match(modeRe))){
5283 var matched = false;
5284 for(var j = 0; j < tklen; j++){
5286 var m = q.match(t.re);
5288 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5291 q = q.replace(m[0], "");
5296 // prevent infinite loop on bad selector
5298 throw 'Error parsing selector, parsing failed at "' + q + '"';
5302 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5303 q = q.replace(mm[1], "");
5306 fn[fn.length] = "return nodup(n);\n}";
5309 * list of variables that need from compression as they are used by eval.
5319 * eval:var:byClassName
5321 * eval:var:byAttribute
5322 * eval:var:attrValue
5330 * Selects a group of elements.
5331 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5332 * @param {Node} root (optional) The start of the query (defaults to document).
5335 select : function(path, root, type){
5336 if(!root || root == document){
5339 if(typeof root == "string"){
5340 root = document.getElementById(root);
5342 var paths = path.split(",");
5344 for(var i = 0, len = paths.length; i < len; i++){
5345 var p = paths[i].replace(trimRe, "");
5347 cache[p] = Roo.DomQuery.compile(p);
5349 throw p + " is not a valid selector";
5352 var result = cache[p](root);
5353 if(result && result != document){
5354 results = results.concat(result);
5357 if(paths.length > 1){
5358 return nodup(results);
5364 * Selects a single element.
5365 * @param {String} selector The selector/xpath query
5366 * @param {Node} root (optional) The start of the query (defaults to document).
5369 selectNode : function(path, root){
5370 return Roo.DomQuery.select(path, root)[0];
5374 * Selects the value of a node, optionally replacing null with the defaultValue.
5375 * @param {String} selector The selector/xpath query
5376 * @param {Node} root (optional) The start of the query (defaults to document).
5377 * @param {String} defaultValue
5379 selectValue : function(path, root, defaultValue){
5380 path = path.replace(trimRe, "");
5381 if(!valueCache[path]){
5382 valueCache[path] = Roo.DomQuery.compile(path, "select");
5384 var n = valueCache[path](root);
5385 n = n[0] ? n[0] : n;
5386 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5387 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5391 * Selects the value of a node, parsing integers and floats.
5392 * @param {String} selector The selector/xpath query
5393 * @param {Node} root (optional) The start of the query (defaults to document).
5394 * @param {Number} defaultValue
5397 selectNumber : function(path, root, defaultValue){
5398 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5399 return parseFloat(v);
5403 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5404 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5405 * @param {String} selector The simple selector to test
5408 is : function(el, ss){
5409 if(typeof el == "string"){
5410 el = document.getElementById(el);
5412 var isArray = (el instanceof Array);
5413 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5414 return isArray ? (result.length == el.length) : (result.length > 0);
5418 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5419 * @param {Array} el An array of elements to filter
5420 * @param {String} selector The simple selector to test
5421 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5422 * the selector instead of the ones that match
5425 filter : function(els, ss, nonMatches){
5426 ss = ss.replace(trimRe, "");
5427 if(!simpleCache[ss]){
5428 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5430 var result = simpleCache[ss](els);
5431 return nonMatches ? quickDiff(result, els) : result;
5435 * Collection of matching regular expressions and code snippets.
5439 select: 'n = byClassName(n, null, " {1} ");'
5441 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5442 select: 'n = byPseudo(n, "{1}", "{2}");'
5444 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5445 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5448 select: 'n = byId(n, null, "{1}");'
5451 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5456 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5457 * 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, > <.
5460 "=" : function(a, v){
5463 "!=" : function(a, v){
5466 "^=" : function(a, v){
5467 return a && a.substr(0, v.length) == v;
5469 "$=" : function(a, v){
5470 return a && a.substr(a.length-v.length) == v;
5472 "*=" : function(a, v){
5473 return a && a.indexOf(v) !== -1;
5475 "%=" : function(a, v){
5476 return (a % v) == 0;
5478 "|=" : function(a, v){
5479 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5481 "~=" : function(a, v){
5482 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5487 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5488 * and the argument (if any) supplied in the selector.
5491 "first-child" : function(c){
5492 var r = [], ri = -1, n;
5493 for(var i = 0, ci; ci = n = c[i]; i++){
5494 while((n = n.previousSibling) && n.nodeType != 1);
5502 "last-child" : function(c){
5503 var r = [], ri = -1, n;
5504 for(var i = 0, ci; ci = n = c[i]; i++){
5505 while((n = n.nextSibling) && n.nodeType != 1);
5513 "nth-child" : function(c, a) {
5514 var r = [], ri = -1;
5515 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5516 var f = (m[1] || 1) - 0, l = m[2] - 0;
5517 for(var i = 0, n; n = c[i]; i++){
5518 var pn = n.parentNode;
5519 if (batch != pn._batch) {
5521 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5522 if(cn.nodeType == 1){
5529 if (l == 0 || n.nodeIndex == l){
5532 } else if ((n.nodeIndex + l) % f == 0){
5540 "only-child" : function(c){
5541 var r = [], ri = -1;;
5542 for(var i = 0, ci; ci = c[i]; i++){
5543 if(!prev(ci) && !next(ci)){
5550 "empty" : function(c){
5551 var r = [], ri = -1;
5552 for(var i = 0, ci; ci = c[i]; i++){
5553 var cns = ci.childNodes, j = 0, cn, empty = true;
5556 if(cn.nodeType == 1 || cn.nodeType == 3){
5568 "contains" : function(c, v){
5569 var r = [], ri = -1;
5570 for(var i = 0, ci; ci = c[i]; i++){
5571 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5578 "nodeValue" : function(c, v){
5579 var r = [], ri = -1;
5580 for(var i = 0, ci; ci = c[i]; i++){
5581 if(ci.firstChild && ci.firstChild.nodeValue == v){
5588 "checked" : function(c){
5589 var r = [], ri = -1;
5590 for(var i = 0, ci; ci = c[i]; i++){
5591 if(ci.checked == true){
5598 "not" : function(c, ss){
5599 return Roo.DomQuery.filter(c, ss, true);
5602 "odd" : function(c){
5603 return this["nth-child"](c, "odd");
5606 "even" : function(c){
5607 return this["nth-child"](c, "even");
5610 "nth" : function(c, a){
5611 return c[a-1] || [];
5614 "first" : function(c){
5618 "last" : function(c){
5619 return c[c.length-1] || [];
5622 "has" : function(c, ss){
5623 var s = Roo.DomQuery.select;
5624 var r = [], ri = -1;
5625 for(var i = 0, ci; ci = c[i]; i++){
5626 if(s(ss, ci).length > 0){
5633 "next" : function(c, ss){
5634 var is = Roo.DomQuery.is;
5635 var r = [], ri = -1;
5636 for(var i = 0, ci; ci = c[i]; i++){
5645 "prev" : function(c, ss){
5646 var is = Roo.DomQuery.is;
5647 var r = [], ri = -1;
5648 for(var i = 0, ci; ci = c[i]; i++){
5661 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5662 * @param {String} path The selector/xpath query
5663 * @param {Node} root (optional) The start of the query (defaults to document).
5668 Roo.query = Roo.DomQuery.select;
5671 * Ext JS Library 1.1.1
5672 * Copyright(c) 2006-2007, Ext JS, LLC.
5674 * Originally Released Under LGPL - original licence link has changed is not relivant.
5677 * <script type="text/javascript">
5681 * @class Roo.util.Observable
5682 * Base class that provides a common interface for publishing events. Subclasses are expected to
5683 * to have a property "events" with all the events defined.<br>
5686 Employee = function(name){
5693 Roo.extend(Employee, Roo.util.Observable);
5695 * @param {Object} config properties to use (incuding events / listeners)
5698 Roo.util.Observable = function(cfg){
5701 this.addEvents(cfg.events || {});
5703 delete cfg.events; // make sure
5706 Roo.apply(this, cfg);
5709 this.on(this.listeners);
5710 delete this.listeners;
5713 Roo.util.Observable.prototype = {
5715 * @cfg {Object} listeners list of events and functions to call for this object,
5719 'click' : function(e) {
5729 * Fires the specified event with the passed parameters (minus the event name).
5730 * @param {String} eventName
5731 * @param {Object...} args Variable number of parameters are passed to handlers
5732 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5734 fireEvent : function(){
5735 var ce = this.events[arguments[0].toLowerCase()];
5736 if(typeof ce == "object"){
5737 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5744 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5747 * Appends an event handler to this component
5748 * @param {String} eventName The type of event to listen for
5749 * @param {Function} handler The method the event invokes
5750 * @param {Object} scope (optional) The scope in which to execute the handler
5751 * function. The handler function's "this" context.
5752 * @param {Object} options (optional) An object containing handler configuration
5753 * properties. This may contain any of the following properties:<ul>
5754 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5755 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5756 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5757 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5758 * by the specified number of milliseconds. If the event fires again within that time, the original
5759 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5762 * <b>Combining Options</b><br>
5763 * Using the options argument, it is possible to combine different types of listeners:<br>
5765 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5767 el.on('click', this.onClick, this, {
5774 * <b>Attaching multiple handlers in 1 call</b><br>
5775 * The method also allows for a single argument to be passed which is a config object containing properties
5776 * which specify multiple handlers.
5785 fn: this.onMouseOver,
5789 fn: this.onMouseOut,
5795 * Or a shorthand syntax which passes the same scope object to all handlers:
5798 'click': this.onClick,
5799 'mouseover': this.onMouseOver,
5800 'mouseout': this.onMouseOut,
5805 addListener : function(eventName, fn, scope, o){
5806 if(typeof eventName == "object"){
5809 if(this.filterOptRe.test(e)){
5812 if(typeof o[e] == "function"){
5814 this.addListener(e, o[e], o.scope, o);
5816 // individual options
5817 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5822 o = (!o || typeof o == "boolean") ? {} : o;
5823 eventName = eventName.toLowerCase();
5824 var ce = this.events[eventName] || true;
5825 if(typeof ce == "boolean"){
5826 ce = new Roo.util.Event(this, eventName);
5827 this.events[eventName] = ce;
5829 ce.addListener(fn, scope, o);
5833 * Removes a listener
5834 * @param {String} eventName The type of event to listen for
5835 * @param {Function} handler The handler to remove
5836 * @param {Object} scope (optional) The scope (this object) for the handler
5838 removeListener : function(eventName, fn, scope){
5839 var ce = this.events[eventName.toLowerCase()];
5840 if(typeof ce == "object"){
5841 ce.removeListener(fn, scope);
5846 * Removes all listeners for this object
5848 purgeListeners : function(){
5849 for(var evt in this.events){
5850 if(typeof this.events[evt] == "object"){
5851 this.events[evt].clearListeners();
5856 relayEvents : function(o, events){
5857 var createHandler = function(ename){
5859 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5862 for(var i = 0, len = events.length; i < len; i++){
5863 var ename = events[i];
5864 if(!this.events[ename]){ this.events[ename] = true; };
5865 o.on(ename, createHandler(ename), this);
5870 * Used to define events on this Observable
5871 * @param {Object} object The object with the events defined
5873 addEvents : function(o){
5877 Roo.applyIf(this.events, o);
5881 * Checks to see if this object has any listeners for a specified event
5882 * @param {String} eventName The name of the event to check for
5883 * @return {Boolean} True if the event is being listened for, else false
5885 hasListener : function(eventName){
5886 var e = this.events[eventName];
5887 return typeof e == "object" && e.listeners.length > 0;
5891 * Appends an event handler to this element (shorthand for addListener)
5892 * @param {String} eventName The type of event to listen for
5893 * @param {Function} handler The method the event invokes
5894 * @param {Object} scope (optional) The scope in which to execute the handler
5895 * function. The handler function's "this" context.
5896 * @param {Object} options (optional)
5899 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5901 * Removes a listener (shorthand for removeListener)
5902 * @param {String} eventName The type of event to listen for
5903 * @param {Function} handler The handler to remove
5904 * @param {Object} scope (optional) The scope (this object) for the handler
5907 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5910 * Starts capture on the specified Observable. All events will be passed
5911 * to the supplied function with the event name + standard signature of the event
5912 * <b>before</b> the event is fired. If the supplied function returns false,
5913 * the event will not fire.
5914 * @param {Observable} o The Observable to capture
5915 * @param {Function} fn The function to call
5916 * @param {Object} scope (optional) The scope (this object) for the fn
5919 Roo.util.Observable.capture = function(o, fn, scope){
5920 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5924 * Removes <b>all</b> added captures from the Observable.
5925 * @param {Observable} o The Observable to release
5928 Roo.util.Observable.releaseCapture = function(o){
5929 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5934 var createBuffered = function(h, o, scope){
5935 var task = new Roo.util.DelayedTask();
5937 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5941 var createSingle = function(h, e, fn, scope){
5943 e.removeListener(fn, scope);
5944 return h.apply(scope, arguments);
5948 var createDelayed = function(h, o, scope){
5950 var args = Array.prototype.slice.call(arguments, 0);
5951 setTimeout(function(){
5952 h.apply(scope, args);
5957 Roo.util.Event = function(obj, name){
5960 this.listeners = [];
5963 Roo.util.Event.prototype = {
5964 addListener : function(fn, scope, options){
5965 var o = options || {};
5966 scope = scope || this.obj;
5967 if(!this.isListening(fn, scope)){
5968 var l = {fn: fn, scope: scope, options: o};
5971 h = createDelayed(h, o, scope);
5974 h = createSingle(h, this, fn, scope);
5977 h = createBuffered(h, o, scope);
5980 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5981 this.listeners.push(l);
5983 this.listeners = this.listeners.slice(0);
5984 this.listeners.push(l);
5989 findListener : function(fn, scope){
5990 scope = scope || this.obj;
5991 var ls = this.listeners;
5992 for(var i = 0, len = ls.length; i < len; i++){
5994 if(l.fn == fn && l.scope == scope){
6001 isListening : function(fn, scope){
6002 return this.findListener(fn, scope) != -1;
6005 removeListener : function(fn, scope){
6007 if((index = this.findListener(fn, scope)) != -1){
6009 this.listeners.splice(index, 1);
6011 this.listeners = this.listeners.slice(0);
6012 this.listeners.splice(index, 1);
6019 clearListeners : function(){
6020 this.listeners = [];
6024 var ls = this.listeners, scope, len = ls.length;
6027 var args = Array.prototype.slice.call(arguments, 0);
6028 for(var i = 0; i < len; i++){
6030 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
6031 this.firing = false;
6035 this.firing = false;
6042 * Ext JS Library 1.1.1
6043 * Copyright(c) 2006-2007, Ext JS, LLC.
6045 * Originally Released Under LGPL - original licence link has changed is not relivant.
6048 * <script type="text/javascript">
6052 * @class Roo.EventManager
6053 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
6054 * several useful events directly.
6055 * See {@link Roo.EventObject} for more details on normalized event objects.
6058 Roo.EventManager = function(){
6059 var docReadyEvent, docReadyProcId, docReadyState = false;
6060 var resizeEvent, resizeTask, textEvent, textSize;
6061 var E = Roo.lib.Event;
6062 var D = Roo.lib.Dom;
6067 var fireDocReady = function(){
6069 docReadyState = true;
6072 clearInterval(docReadyProcId);
6074 if(Roo.isGecko || Roo.isOpera) {
6075 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
6078 var defer = document.getElementById("ie-deferred-loader");
6080 defer.onreadystatechange = null;
6081 defer.parentNode.removeChild(defer);
6085 docReadyEvent.fire();
6086 docReadyEvent.clearListeners();
6091 var initDocReady = function(){
6092 docReadyEvent = new Roo.util.Event();
6093 if(Roo.isGecko || Roo.isOpera) {
6094 document.addEventListener("DOMContentLoaded", fireDocReady, false);
6096 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
6097 var defer = document.getElementById("ie-deferred-loader");
6098 defer.onreadystatechange = function(){
6099 if(this.readyState == "complete"){
6103 }else if(Roo.isSafari){
6104 docReadyProcId = setInterval(function(){
6105 var rs = document.readyState;
6106 if(rs == "complete") {
6111 // no matter what, make sure it fires on load
6112 E.on(window, "load", fireDocReady);
6115 var createBuffered = function(h, o){
6116 var task = new Roo.util.DelayedTask(h);
6118 // create new event object impl so new events don't wipe out properties
6119 e = new Roo.EventObjectImpl(e);
6120 task.delay(o.buffer, h, null, [e]);
6124 var createSingle = function(h, el, ename, fn){
6126 Roo.EventManager.removeListener(el, ename, fn);
6131 var createDelayed = function(h, o){
6133 // create new event object impl so new events don't wipe out properties
6134 e = new Roo.EventObjectImpl(e);
6135 setTimeout(function(){
6140 var transitionEndVal = false;
6142 var transitionEnd = function()
6144 if (transitionEndVal) {
6145 return transitionEndVal;
6147 var el = document.createElement('div');
6149 var transEndEventNames = {
6150 WebkitTransition : 'webkitTransitionEnd',
6151 MozTransition : 'transitionend',
6152 OTransition : 'oTransitionEnd otransitionend',
6153 transition : 'transitionend'
6156 for (var name in transEndEventNames) {
6157 if (el.style[name] !== undefined) {
6158 transitionEndVal = transEndEventNames[name];
6159 return transitionEndVal ;
6165 var listen = function(element, ename, opt, fn, scope){
6166 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6167 fn = fn || o.fn; scope = scope || o.scope;
6168 var el = Roo.getDom(element);
6172 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6175 if (ename == 'transitionend') {
6176 ename = transitionEnd();
6178 var h = function(e){
6179 e = Roo.EventObject.setEvent(e);
6182 t = e.getTarget(o.delegate, el);
6189 if(o.stopEvent === true){
6192 if(o.preventDefault === true){
6195 if(o.stopPropagation === true){
6196 e.stopPropagation();
6199 if(o.normalized === false){
6203 fn.call(scope || el, e, t, o);
6206 h = createDelayed(h, o);
6209 h = createSingle(h, el, ename, fn);
6212 h = createBuffered(h, o);
6214 fn._handlers = fn._handlers || [];
6217 fn._handlers.push([Roo.id(el), ename, h]);
6222 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6223 el.addEventListener("DOMMouseScroll", h, false);
6224 E.on(window, 'unload', function(){
6225 el.removeEventListener("DOMMouseScroll", h, false);
6228 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6229 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6234 var stopListening = function(el, ename, fn){
6235 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6237 for(var i = 0, len = hds.length; i < len; i++){
6239 if(h[0] == id && h[1] == ename){
6246 E.un(el, ename, hd);
6247 el = Roo.getDom(el);
6248 if(ename == "mousewheel" && el.addEventListener){
6249 el.removeEventListener("DOMMouseScroll", hd, false);
6251 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6252 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6256 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6263 * @scope Roo.EventManager
6268 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6269 * object with a Roo.EventObject
6270 * @param {Function} fn The method the event invokes
6271 * @param {Object} scope An object that becomes the scope of the handler
6272 * @param {boolean} override If true, the obj passed in becomes
6273 * the execution scope of the listener
6274 * @return {Function} The wrapped function
6277 wrap : function(fn, scope, override){
6279 Roo.EventObject.setEvent(e);
6280 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6285 * Appends an event handler to an element (shorthand for addListener)
6286 * @param {String/HTMLElement} element The html element or id to assign the
6287 * @param {String} eventName The type of event to listen for
6288 * @param {Function} handler The method the event invokes
6289 * @param {Object} scope (optional) The scope in which to execute the handler
6290 * function. The handler function's "this" context.
6291 * @param {Object} options (optional) An object containing handler configuration
6292 * properties. This may contain any of the following properties:<ul>
6293 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6294 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6295 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6296 * <li>preventDefault {Boolean} True to prevent the default action</li>
6297 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6298 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6299 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6300 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6301 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6302 * by the specified number of milliseconds. If the event fires again within that time, the original
6303 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6306 * <b>Combining Options</b><br>
6307 * Using the options argument, it is possible to combine different types of listeners:<br>
6309 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6311 el.on('click', this.onClick, this, {
6318 * <b>Attaching multiple handlers in 1 call</b><br>
6319 * The method also allows for a single argument to be passed which is a config object containing properties
6320 * which specify multiple handlers.
6330 fn: this.onMouseOver
6339 * Or a shorthand syntax:<br>
6342 'click' : this.onClick,
6343 'mouseover' : this.onMouseOver,
6344 'mouseout' : this.onMouseOut
6348 addListener : function(element, eventName, fn, scope, options){
6349 if(typeof eventName == "object"){
6355 if(typeof o[e] == "function"){
6357 listen(element, e, o, o[e], o.scope);
6359 // individual options
6360 listen(element, e, o[e]);
6365 return listen(element, eventName, options, fn, scope);
6369 * Removes an event handler
6371 * @param {String/HTMLElement} element The id or html element to remove the
6373 * @param {String} eventName The type of event
6374 * @param {Function} fn
6375 * @return {Boolean} True if a listener was actually removed
6377 removeListener : function(element, eventName, fn){
6378 return stopListening(element, eventName, fn);
6382 * Fires when the document is ready (before onload and before images are loaded). Can be
6383 * accessed shorthanded Roo.onReady().
6384 * @param {Function} fn The method the event invokes
6385 * @param {Object} scope An object that becomes the scope of the handler
6386 * @param {boolean} options
6388 onDocumentReady : function(fn, scope, options){
6389 if(docReadyState){ // if it already fired
6390 docReadyEvent.addListener(fn, scope, options);
6391 docReadyEvent.fire();
6392 docReadyEvent.clearListeners();
6398 docReadyEvent.addListener(fn, scope, options);
6402 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6403 * @param {Function} fn The method the event invokes
6404 * @param {Object} scope An object that becomes the scope of the handler
6405 * @param {boolean} options
6407 onWindowResize : function(fn, scope, options){
6409 resizeEvent = new Roo.util.Event();
6410 resizeTask = new Roo.util.DelayedTask(function(){
6411 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6413 E.on(window, "resize", function(){
6415 resizeTask.delay(50);
6417 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6421 resizeEvent.addListener(fn, scope, options);
6425 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6426 * @param {Function} fn The method the event invokes
6427 * @param {Object} scope An object that becomes the scope of the handler
6428 * @param {boolean} options
6430 onTextResize : function(fn, scope, options){
6432 textEvent = new Roo.util.Event();
6433 var textEl = new Roo.Element(document.createElement('div'));
6434 textEl.dom.className = 'x-text-resize';
6435 textEl.dom.innerHTML = 'X';
6436 textEl.appendTo(document.body);
6437 textSize = textEl.dom.offsetHeight;
6438 setInterval(function(){
6439 if(textEl.dom.offsetHeight != textSize){
6440 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6442 }, this.textResizeInterval);
6444 textEvent.addListener(fn, scope, options);
6448 * Removes the passed window resize listener.
6449 * @param {Function} fn The method the event invokes
6450 * @param {Object} scope The scope of handler
6452 removeResizeListener : function(fn, scope){
6454 resizeEvent.removeListener(fn, scope);
6459 fireResize : function(){
6461 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6465 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6469 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6471 textResizeInterval : 50
6476 * @scopeAlias pub=Roo.EventManager
6480 * Appends an event handler to an element (shorthand for addListener)
6481 * @param {String/HTMLElement} element The html element or id to assign the
6482 * @param {String} eventName The type of event to listen for
6483 * @param {Function} handler The method the event invokes
6484 * @param {Object} scope (optional) The scope in which to execute the handler
6485 * function. The handler function's "this" context.
6486 * @param {Object} options (optional) An object containing handler configuration
6487 * properties. This may contain any of the following properties:<ul>
6488 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6489 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6490 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6491 * <li>preventDefault {Boolean} True to prevent the default action</li>
6492 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6493 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6494 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6495 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6496 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6497 * by the specified number of milliseconds. If the event fires again within that time, the original
6498 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6501 * <b>Combining Options</b><br>
6502 * Using the options argument, it is possible to combine different types of listeners:<br>
6504 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6506 el.on('click', this.onClick, this, {
6513 * <b>Attaching multiple handlers in 1 call</b><br>
6514 * The method also allows for a single argument to be passed which is a config object containing properties
6515 * which specify multiple handlers.
6525 fn: this.onMouseOver
6534 * Or a shorthand syntax:<br>
6537 'click' : this.onClick,
6538 'mouseover' : this.onMouseOver,
6539 'mouseout' : this.onMouseOut
6543 pub.on = pub.addListener;
6544 pub.un = pub.removeListener;
6546 pub.stoppedMouseDownEvent = new Roo.util.Event();
6550 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6551 * @param {Function} fn The method the event invokes
6552 * @param {Object} scope An object that becomes the scope of the handler
6553 * @param {boolean} override If true, the obj passed in becomes
6554 * the execution scope of the listener
6558 Roo.onReady = Roo.EventManager.onDocumentReady;
6560 Roo.onReady(function(){
6561 var bd = Roo.get(document.body);
6566 : Roo.isGecko ? "roo-gecko"
6567 : Roo.isOpera ? "roo-opera"
6568 : Roo.isSafari ? "roo-safari" : ""];
6571 cls.push("roo-mac");
6574 cls.push("roo-linux");
6576 if(Roo.isBorderBox){
6577 cls.push('roo-border-box');
6579 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6580 var p = bd.dom.parentNode;
6582 p.className += ' roo-strict';
6585 bd.addClass(cls.join(' '));
6589 * @class Roo.EventObject
6590 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6591 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6594 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6596 var target = e.getTarget();
6599 var myDiv = Roo.get("myDiv");
6600 myDiv.on("click", handleClick);
6602 Roo.EventManager.on("myDiv", 'click', handleClick);
6603 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6607 Roo.EventObject = function(){
6609 var E = Roo.lib.Event;
6611 // safari keypress events for special keys return bad keycodes
6614 63235 : 39, // right
6617 63276 : 33, // page up
6618 63277 : 34, // page down
6619 63272 : 46, // delete
6624 // normalize button clicks
6625 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6626 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6628 Roo.EventObjectImpl = function(e){
6630 this.setEvent(e.browserEvent || e);
6633 Roo.EventObjectImpl.prototype = {
6635 * Used to fix doc tools.
6636 * @scope Roo.EventObject.prototype
6642 /** The normal browser event */
6643 browserEvent : null,
6644 /** The button pressed in a mouse event */
6646 /** True if the shift key was down during the event */
6648 /** True if the control key was down during the event */
6650 /** True if the alt key was down during the event */
6709 setEvent : function(e){
6710 if(e == this || (e && e.browserEvent)){ // already wrapped
6713 this.browserEvent = e;
6715 // normalize buttons
6716 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6717 if(e.type == 'click' && this.button == -1){
6721 this.shiftKey = e.shiftKey;
6722 // mac metaKey behaves like ctrlKey
6723 this.ctrlKey = e.ctrlKey || e.metaKey;
6724 this.altKey = e.altKey;
6725 // in getKey these will be normalized for the mac
6726 this.keyCode = e.keyCode;
6727 // keyup warnings on firefox.
6728 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6729 // cache the target for the delayed and or buffered events
6730 this.target = E.getTarget(e);
6732 this.xy = E.getXY(e);
6735 this.shiftKey = false;
6736 this.ctrlKey = false;
6737 this.altKey = false;
6747 * Stop the event (preventDefault and stopPropagation)
6749 stopEvent : function(){
6750 if(this.browserEvent){
6751 if(this.browserEvent.type == 'mousedown'){
6752 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6754 E.stopEvent(this.browserEvent);
6759 * Prevents the browsers default handling of the event.
6761 preventDefault : function(){
6762 if(this.browserEvent){
6763 E.preventDefault(this.browserEvent);
6768 isNavKeyPress : function(){
6769 var k = this.keyCode;
6770 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6771 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6774 isSpecialKey : function(){
6775 var k = this.keyCode;
6776 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6777 (k == 16) || (k == 17) ||
6778 (k >= 18 && k <= 20) ||
6779 (k >= 33 && k <= 35) ||
6780 (k >= 36 && k <= 39) ||
6781 (k >= 44 && k <= 45);
6784 * Cancels bubbling of the event.
6786 stopPropagation : function(){
6787 if(this.browserEvent){
6788 if(this.type == 'mousedown'){
6789 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6791 E.stopPropagation(this.browserEvent);
6796 * Gets the key code for the event.
6799 getCharCode : function(){
6800 return this.charCode || this.keyCode;
6804 * Returns a normalized keyCode for the event.
6805 * @return {Number} The key code
6807 getKey : function(){
6808 var k = this.keyCode || this.charCode;
6809 return Roo.isSafari ? (safariKeys[k] || k) : k;
6813 * Gets the x coordinate of the event.
6816 getPageX : function(){
6821 * Gets the y coordinate of the event.
6824 getPageY : function(){
6829 * Gets the time of the event.
6832 getTime : function(){
6833 if(this.browserEvent){
6834 return E.getTime(this.browserEvent);
6840 * Gets the page coordinates of the event.
6841 * @return {Array} The xy values like [x, y]
6848 * Gets the target for the event.
6849 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6850 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6851 search as a number or element (defaults to 10 || document.body)
6852 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6853 * @return {HTMLelement}
6855 getTarget : function(selector, maxDepth, returnEl){
6856 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6859 * Gets the related target.
6860 * @return {HTMLElement}
6862 getRelatedTarget : function(){
6863 if(this.browserEvent){
6864 return E.getRelatedTarget(this.browserEvent);
6870 * Normalizes mouse wheel delta across browsers
6871 * @return {Number} The delta
6873 getWheelDelta : function(){
6874 var e = this.browserEvent;
6876 if(e.wheelDelta){ /* IE/Opera. */
6877 delta = e.wheelDelta/120;
6878 }else if(e.detail){ /* Mozilla case. */
6879 delta = -e.detail/3;
6885 * Returns true if the control, meta, shift or alt key was pressed during this event.
6888 hasModifier : function(){
6889 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6893 * Returns true if the target of this event equals el or is a child of el
6894 * @param {String/HTMLElement/Element} el
6895 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6898 within : function(el, related){
6899 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6900 return t && Roo.fly(el).contains(t);
6903 getPoint : function(){
6904 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6908 return new Roo.EventObjectImpl();
6913 * Ext JS Library 1.1.1
6914 * Copyright(c) 2006-2007, Ext JS, LLC.
6916 * Originally Released Under LGPL - original licence link has changed is not relivant.
6919 * <script type="text/javascript">
6923 // was in Composite Element!??!?!
6926 var D = Roo.lib.Dom;
6927 var E = Roo.lib.Event;
6928 var A = Roo.lib.Anim;
6930 // local style camelizing for speed
6932 var camelRe = /(-[a-z])/gi;
6933 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6934 var view = document.defaultView;
6937 * @class Roo.Element
6938 * Represents an Element in the DOM.<br><br>
6941 var el = Roo.get("my-div");
6944 var el = getEl("my-div");
6946 // or with a DOM element
6947 var el = Roo.get(myDivElement);
6949 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6950 * each call instead of constructing a new one.<br><br>
6951 * <b>Animations</b><br />
6952 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6953 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6955 Option Default Description
6956 --------- -------- ---------------------------------------------
6957 duration .35 The duration of the animation in seconds
6958 easing easeOut The YUI easing method
6959 callback none A function to execute when the anim completes
6960 scope this The scope (this) of the callback function
6962 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6963 * manipulate the animation. Here's an example:
6965 var el = Roo.get("my-div");
6970 // default animation
6971 el.setWidth(100, true);
6973 // animation with some options set
6980 // using the "anim" property to get the Anim object
6986 el.setWidth(100, opt);
6988 if(opt.anim.isAnimated()){
6992 * <b> Composite (Collections of) Elements</b><br />
6993 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6994 * @constructor Create a new Element directly.
6995 * @param {String/HTMLElement} element
6996 * @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).
6998 Roo.Element = function(element, forceNew){
6999 var dom = typeof element == "string" ?
7000 document.getElementById(element) : element;
7001 if(!dom){ // invalid id/element
7005 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
7006 return Roo.Element.cache[id];
7016 * The DOM element ID
7019 this.id = id || Roo.id(dom);
7022 var El = Roo.Element;
7026 * The element's default display mode (defaults to "")
7029 originalDisplay : "",
7033 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
7038 * Sets the element's visibility mode. When setVisible() is called it
7039 * will use this to determine whether to set the visibility or the display property.
7040 * @param visMode Element.VISIBILITY or Element.DISPLAY
7041 * @return {Roo.Element} this
7043 setVisibilityMode : function(visMode){
7044 this.visibilityMode = visMode;
7048 * Convenience method for setVisibilityMode(Element.DISPLAY)
7049 * @param {String} display (optional) What to set display to when visible
7050 * @return {Roo.Element} this
7052 enableDisplayMode : function(display){
7053 this.setVisibilityMode(El.DISPLAY);
7054 if(typeof display != "undefined") this.originalDisplay = display;
7059 * 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)
7060 * @param {String} selector The simple selector to test
7061 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7062 search as a number or element (defaults to 10 || document.body)
7063 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7064 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7066 findParent : function(simpleSelector, maxDepth, returnEl){
7067 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
7068 maxDepth = maxDepth || 50;
7069 if(typeof maxDepth != "number"){
7070 stopEl = Roo.getDom(maxDepth);
7073 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
7074 if(dq.is(p, simpleSelector)){
7075 return returnEl ? Roo.get(p) : p;
7085 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
7086 * @param {String} selector The simple selector to test
7087 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7088 search as a number or element (defaults to 10 || document.body)
7089 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
7090 * @return {HTMLElement} The matching DOM node (or null if no match was found)
7092 findParentNode : function(simpleSelector, maxDepth, returnEl){
7093 var p = Roo.fly(this.dom.parentNode, '_internal');
7094 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
7098 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
7099 * This is a shortcut for findParentNode() that always returns an Roo.Element.
7100 * @param {String} selector The simple selector to test
7101 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
7102 search as a number or element (defaults to 10 || document.body)
7103 * @return {Roo.Element} The matching DOM node (or null if no match was found)
7105 up : function(simpleSelector, maxDepth){
7106 return this.findParentNode(simpleSelector, maxDepth, true);
7112 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
7113 * @param {String} selector The simple selector to test
7114 * @return {Boolean} True if this element matches the selector, else false
7116 is : function(simpleSelector){
7117 return Roo.DomQuery.is(this.dom, simpleSelector);
7121 * Perform animation on this element.
7122 * @param {Object} args The YUI animation control args
7123 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
7124 * @param {Function} onComplete (optional) Function to call when animation completes
7125 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
7126 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
7127 * @return {Roo.Element} this
7129 animate : function(args, duration, onComplete, easing, animType){
7130 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
7135 * @private Internal animation call
7137 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
7138 animType = animType || 'run';
7140 var anim = Roo.lib.Anim[animType](
7142 (opt.duration || defaultDur) || .35,
7143 (opt.easing || defaultEase) || 'easeOut',
7145 Roo.callback(cb, this);
7146 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7154 // private legacy anim prep
7155 preanim : function(a, i){
7156 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7160 * Removes worthless text nodes
7161 * @param {Boolean} forceReclean (optional) By default the element
7162 * keeps track if it has been cleaned already so
7163 * you can call this over and over. However, if you update the element and
7164 * need to force a reclean, you can pass true.
7166 clean : function(forceReclean){
7167 if(this.isCleaned && forceReclean !== true){
7171 var d = this.dom, n = d.firstChild, ni = -1;
7173 var nx = n.nextSibling;
7174 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7181 this.isCleaned = true;
7186 calcOffsetsTo : function(el){
7189 var restorePos = false;
7190 if(el.getStyle('position') == 'static'){
7191 el.position('relative');
7196 while(op && op != d && op.tagName != 'HTML'){
7199 op = op.offsetParent;
7202 el.position('static');
7208 * Scrolls this element into view within the passed container.
7209 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7210 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7211 * @return {Roo.Element} this
7213 scrollIntoView : function(container, hscroll){
7214 var c = Roo.getDom(container) || document.body;
7217 var o = this.calcOffsetsTo(c),
7220 b = t+el.offsetHeight,
7221 r = l+el.offsetWidth;
7223 var ch = c.clientHeight;
7224 var ct = parseInt(c.scrollTop, 10);
7225 var cl = parseInt(c.scrollLeft, 10);
7227 var cr = cl + c.clientWidth;
7235 if(hscroll !== false){
7239 c.scrollLeft = r-c.clientWidth;
7246 scrollChildIntoView : function(child, hscroll){
7247 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7251 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7252 * the new height may not be available immediately.
7253 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7254 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7255 * @param {Function} onComplete (optional) Function to call when animation completes
7256 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7257 * @return {Roo.Element} this
7259 autoHeight : function(animate, duration, onComplete, easing){
7260 var oldHeight = this.getHeight();
7262 this.setHeight(1); // force clipping
7263 setTimeout(function(){
7264 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7266 this.setHeight(height);
7268 if(typeof onComplete == "function"){
7272 this.setHeight(oldHeight); // restore original height
7273 this.setHeight(height, animate, duration, function(){
7275 if(typeof onComplete == "function") onComplete();
7276 }.createDelegate(this), easing);
7278 }.createDelegate(this), 0);
7283 * Returns true if this element is an ancestor of the passed element
7284 * @param {HTMLElement/String} el The element to check
7285 * @return {Boolean} True if this element is an ancestor of el, else false
7287 contains : function(el){
7288 if(!el){return false;}
7289 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7293 * Checks whether the element is currently visible using both visibility and display properties.
7294 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7295 * @return {Boolean} True if the element is currently visible, else false
7297 isVisible : function(deep) {
7298 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7299 if(deep !== true || !vis){
7302 var p = this.dom.parentNode;
7303 while(p && p.tagName.toLowerCase() != "body"){
7304 if(!Roo.fly(p, '_isVisible').isVisible()){
7313 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7314 * @param {String} selector The CSS selector
7315 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7316 * @return {CompositeElement/CompositeElementLite} The composite element
7318 select : function(selector, unique){
7319 return El.select(selector, unique, this.dom);
7323 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7324 * @param {String} selector The CSS selector
7325 * @return {Array} An array of the matched nodes
7327 query : function(selector, unique){
7328 return Roo.DomQuery.select(selector, this.dom);
7332 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7333 * @param {String} selector The CSS selector
7334 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7335 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7337 child : function(selector, returnDom){
7338 var n = Roo.DomQuery.selectNode(selector, this.dom);
7339 return returnDom ? n : Roo.get(n);
7343 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7344 * @param {String} selector The CSS selector
7345 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7346 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7348 down : function(selector, returnDom){
7349 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7350 return returnDom ? n : Roo.get(n);
7354 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7355 * @param {String} group The group the DD object is member of
7356 * @param {Object} config The DD config object
7357 * @param {Object} overrides An object containing methods to override/implement on the DD object
7358 * @return {Roo.dd.DD} The DD object
7360 initDD : function(group, config, overrides){
7361 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7362 return Roo.apply(dd, overrides);
7366 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7367 * @param {String} group The group the DDProxy object is member of
7368 * @param {Object} config The DDProxy config object
7369 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7370 * @return {Roo.dd.DDProxy} The DDProxy object
7372 initDDProxy : function(group, config, overrides){
7373 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7374 return Roo.apply(dd, overrides);
7378 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7379 * @param {String} group The group the DDTarget object is member of
7380 * @param {Object} config The DDTarget config object
7381 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7382 * @return {Roo.dd.DDTarget} The DDTarget object
7384 initDDTarget : function(group, config, overrides){
7385 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7386 return Roo.apply(dd, overrides);
7390 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7391 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7392 * @param {Boolean} visible Whether the element is visible
7393 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7394 * @return {Roo.Element} this
7396 setVisible : function(visible, animate){
7398 if(this.visibilityMode == El.DISPLAY){
7399 this.setDisplayed(visible);
7402 this.dom.style.visibility = visible ? "visible" : "hidden";
7405 // closure for composites
7407 var visMode = this.visibilityMode;
7409 this.setOpacity(.01);
7410 this.setVisible(true);
7412 this.anim({opacity: { to: (visible?1:0) }},
7413 this.preanim(arguments, 1),
7414 null, .35, 'easeIn', function(){
7416 if(visMode == El.DISPLAY){
7417 dom.style.display = "none";
7419 dom.style.visibility = "hidden";
7421 Roo.get(dom).setOpacity(1);
7429 * Returns true if display is not "none"
7432 isDisplayed : function() {
7433 return this.getStyle("display") != "none";
7437 * Toggles the element's visibility or display, depending on visibility mode.
7438 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7439 * @return {Roo.Element} this
7441 toggle : function(animate){
7442 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7447 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7448 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7449 * @return {Roo.Element} this
7451 setDisplayed : function(value) {
7452 if(typeof value == "boolean"){
7453 value = value ? this.originalDisplay : "none";
7455 this.setStyle("display", value);
7460 * Tries to focus the element. Any exceptions are caught and ignored.
7461 * @return {Roo.Element} this
7463 focus : function() {
7471 * Tries to blur the element. Any exceptions are caught and ignored.
7472 * @return {Roo.Element} this
7482 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7483 * @param {String/Array} className The CSS class to add, or an array of classes
7484 * @return {Roo.Element} this
7486 addClass : function(className){
7487 if(className instanceof Array){
7488 for(var i = 0, len = className.length; i < len; i++) {
7489 this.addClass(className[i]);
7492 if(className && !this.hasClass(className)){
7493 this.dom.className = this.dom.className + " " + className;
7500 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7501 * @param {String/Array} className The CSS class to add, or an array of classes
7502 * @return {Roo.Element} this
7504 radioClass : function(className){
7505 var siblings = this.dom.parentNode.childNodes;
7506 for(var i = 0; i < siblings.length; i++) {
7507 var s = siblings[i];
7508 if(s.nodeType == 1){
7509 Roo.get(s).removeClass(className);
7512 this.addClass(className);
7517 * Removes one or more CSS classes from the element.
7518 * @param {String/Array} className The CSS class to remove, or an array of classes
7519 * @return {Roo.Element} this
7521 removeClass : function(className){
7522 if(!className || !this.dom.className){
7525 if(className instanceof Array){
7526 for(var i = 0, len = className.length; i < len; i++) {
7527 this.removeClass(className[i]);
7530 if(this.hasClass(className)){
7531 var re = this.classReCache[className];
7533 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7534 this.classReCache[className] = re;
7536 this.dom.className =
7537 this.dom.className.replace(re, " ");
7547 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7548 * @param {String} className The CSS class to toggle
7549 * @return {Roo.Element} this
7551 toggleClass : function(className){
7552 if(this.hasClass(className)){
7553 this.removeClass(className);
7555 this.addClass(className);
7561 * Checks if the specified CSS class exists on this element's DOM node.
7562 * @param {String} className The CSS class to check for
7563 * @return {Boolean} True if the class exists, else false
7565 hasClass : function(className){
7566 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7570 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7571 * @param {String} oldClassName The CSS class to replace
7572 * @param {String} newClassName The replacement CSS class
7573 * @return {Roo.Element} this
7575 replaceClass : function(oldClassName, newClassName){
7576 this.removeClass(oldClassName);
7577 this.addClass(newClassName);
7582 * Returns an object with properties matching the styles requested.
7583 * For example, el.getStyles('color', 'font-size', 'width') might return
7584 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7585 * @param {String} style1 A style name
7586 * @param {String} style2 A style name
7587 * @param {String} etc.
7588 * @return {Object} The style object
7590 getStyles : function(){
7591 var a = arguments, len = a.length, r = {};
7592 for(var i = 0; i < len; i++){
7593 r[a[i]] = this.getStyle(a[i]);
7599 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7600 * @param {String} property The style property whose value is returned.
7601 * @return {String} The current value of the style property for this element.
7603 getStyle : function(){
7604 return view && view.getComputedStyle ?
7606 var el = this.dom, v, cs, camel;
7607 if(prop == 'float'){
7610 if(el.style && (v = el.style[prop])){
7613 if(cs = view.getComputedStyle(el, "")){
7614 if(!(camel = propCache[prop])){
7615 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7622 var el = this.dom, v, cs, camel;
7623 if(prop == 'opacity'){
7624 if(typeof el.style.filter == 'string'){
7625 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7627 var fv = parseFloat(m[1]);
7629 return fv ? fv / 100 : 0;
7634 }else if(prop == 'float'){
7635 prop = "styleFloat";
7637 if(!(camel = propCache[prop])){
7638 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7640 if(v = el.style[camel]){
7643 if(cs = el.currentStyle){
7651 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7652 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7653 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7654 * @return {Roo.Element} this
7656 setStyle : function(prop, value){
7657 if(typeof prop == "string"){
7659 if (prop == 'float') {
7660 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7665 if(!(camel = propCache[prop])){
7666 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7669 if(camel == 'opacity') {
7670 this.setOpacity(value);
7672 this.dom.style[camel] = value;
7675 for(var style in prop){
7676 if(typeof prop[style] != "function"){
7677 this.setStyle(style, prop[style]);
7685 * More flexible version of {@link #setStyle} for setting style properties.
7686 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7687 * a function which returns such a specification.
7688 * @return {Roo.Element} this
7690 applyStyles : function(style){
7691 Roo.DomHelper.applyStyles(this.dom, style);
7696 * 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).
7697 * @return {Number} The X position of the element
7700 return D.getX(this.dom);
7704 * 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).
7705 * @return {Number} The Y position of the element
7708 return D.getY(this.dom);
7712 * 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).
7713 * @return {Array} The XY position of the element
7716 return D.getXY(this.dom);
7720 * 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).
7721 * @param {Number} The X position of the element
7722 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7723 * @return {Roo.Element} this
7725 setX : function(x, animate){
7727 D.setX(this.dom, x);
7729 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7735 * 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).
7736 * @param {Number} The Y position of the element
7737 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7738 * @return {Roo.Element} this
7740 setY : function(y, animate){
7742 D.setY(this.dom, y);
7744 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7750 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7751 * @param {String} left The left CSS property value
7752 * @return {Roo.Element} this
7754 setLeft : function(left){
7755 this.setStyle("left", this.addUnits(left));
7760 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7761 * @param {String} top The top CSS property value
7762 * @return {Roo.Element} this
7764 setTop : function(top){
7765 this.setStyle("top", this.addUnits(top));
7770 * Sets the element's CSS right style.
7771 * @param {String} right The right CSS property value
7772 * @return {Roo.Element} this
7774 setRight : function(right){
7775 this.setStyle("right", this.addUnits(right));
7780 * Sets the element's CSS bottom style.
7781 * @param {String} bottom The bottom CSS property value
7782 * @return {Roo.Element} this
7784 setBottom : function(bottom){
7785 this.setStyle("bottom", this.addUnits(bottom));
7790 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7791 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7792 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7793 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7794 * @return {Roo.Element} this
7796 setXY : function(pos, animate){
7798 D.setXY(this.dom, pos);
7800 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7806 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7807 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7808 * @param {Number} x X value for new position (coordinates are page-based)
7809 * @param {Number} y Y value for new position (coordinates are page-based)
7810 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7811 * @return {Roo.Element} this
7813 setLocation : function(x, y, animate){
7814 this.setXY([x, y], this.preanim(arguments, 2));
7819 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7820 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7821 * @param {Number} x X value for new position (coordinates are page-based)
7822 * @param {Number} y Y value for new position (coordinates are page-based)
7823 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7824 * @return {Roo.Element} this
7826 moveTo : function(x, y, animate){
7827 this.setXY([x, y], this.preanim(arguments, 2));
7832 * Returns the region of the given element.
7833 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7834 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7836 getRegion : function(){
7837 return D.getRegion(this.dom);
7841 * Returns the offset height of the element
7842 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7843 * @return {Number} The element's height
7845 getHeight : function(contentHeight){
7846 var h = this.dom.offsetHeight || 0;
7847 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7851 * Returns the offset width of the element
7852 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7853 * @return {Number} The element's width
7855 getWidth : function(contentWidth){
7856 var w = this.dom.offsetWidth || 0;
7857 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7861 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7862 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7863 * if a height has not been set using CSS.
7866 getComputedHeight : function(){
7867 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7869 h = parseInt(this.getStyle('height'), 10) || 0;
7870 if(!this.isBorderBox()){
7871 h += this.getFrameWidth('tb');
7878 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7879 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7880 * if a width has not been set using CSS.
7883 getComputedWidth : function(){
7884 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7886 w = parseInt(this.getStyle('width'), 10) || 0;
7887 if(!this.isBorderBox()){
7888 w += this.getFrameWidth('lr');
7895 * Returns the size of the element.
7896 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7897 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7899 getSize : function(contentSize){
7900 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7904 * Returns the width and height of the viewport.
7905 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7907 getViewSize : function(){
7908 var d = this.dom, doc = document, aw = 0, ah = 0;
7909 if(d == doc || d == doc.body){
7910 return {width : D.getViewWidth(), height: D.getViewHeight()};
7913 width : d.clientWidth,
7914 height: d.clientHeight
7920 * Returns the value of the "value" attribute
7921 * @param {Boolean} asNumber true to parse the value as a number
7922 * @return {String/Number}
7924 getValue : function(asNumber){
7925 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7929 adjustWidth : function(width){
7930 if(typeof width == "number"){
7931 if(this.autoBoxAdjust && !this.isBorderBox()){
7932 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7942 adjustHeight : function(height){
7943 if(typeof height == "number"){
7944 if(this.autoBoxAdjust && !this.isBorderBox()){
7945 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7955 * Set the width of the element
7956 * @param {Number} width The new width
7957 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7958 * @return {Roo.Element} this
7960 setWidth : function(width, animate){
7961 width = this.adjustWidth(width);
7963 this.dom.style.width = this.addUnits(width);
7965 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7971 * Set the height of the element
7972 * @param {Number} height The new height
7973 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7974 * @return {Roo.Element} this
7976 setHeight : function(height, animate){
7977 height = this.adjustHeight(height);
7979 this.dom.style.height = this.addUnits(height);
7981 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7987 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7988 * @param {Number} width The new width
7989 * @param {Number} height The new height
7990 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7991 * @return {Roo.Element} this
7993 setSize : function(width, height, animate){
7994 if(typeof width == "object"){ // in case of object from getSize()
7995 height = width.height; width = width.width;
7997 width = this.adjustWidth(width); height = this.adjustHeight(height);
7999 this.dom.style.width = this.addUnits(width);
8000 this.dom.style.height = this.addUnits(height);
8002 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
8008 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
8009 * @param {Number} x X value for new position (coordinates are page-based)
8010 * @param {Number} y Y value for new position (coordinates are page-based)
8011 * @param {Number} width The new width
8012 * @param {Number} height The new height
8013 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8014 * @return {Roo.Element} this
8016 setBounds : function(x, y, width, height, animate){
8018 this.setSize(width, height);
8019 this.setLocation(x, y);
8021 width = this.adjustWidth(width); height = this.adjustHeight(height);
8022 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
8023 this.preanim(arguments, 4), 'motion');
8029 * 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.
8030 * @param {Roo.lib.Region} region The region to fill
8031 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8032 * @return {Roo.Element} this
8034 setRegion : function(region, animate){
8035 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
8040 * Appends an event handler
8042 * @param {String} eventName The type of event to append
8043 * @param {Function} fn The method the event invokes
8044 * @param {Object} scope (optional) The scope (this object) of the fn
8045 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
8047 addListener : function(eventName, fn, scope, options){
8049 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
8054 * Removes an event handler from this element
8055 * @param {String} eventName the type of event to remove
8056 * @param {Function} fn the method the event invokes
8057 * @return {Roo.Element} this
8059 removeListener : function(eventName, fn){
8060 Roo.EventManager.removeListener(this.dom, eventName, fn);
8065 * Removes all previous added listeners from this element
8066 * @return {Roo.Element} this
8068 removeAllListeners : function(){
8069 E.purgeElement(this.dom);
8073 relayEvent : function(eventName, observable){
8074 this.on(eventName, function(e){
8075 observable.fireEvent(eventName, e);
8080 * Set the opacity of the element
8081 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
8082 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8083 * @return {Roo.Element} this
8085 setOpacity : function(opacity, animate){
8087 var s = this.dom.style;
8090 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
8091 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
8093 s.opacity = opacity;
8096 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
8102 * Gets the left X coordinate
8103 * @param {Boolean} local True to get the local css position instead of page coordinate
8106 getLeft : function(local){
8110 return parseInt(this.getStyle("left"), 10) || 0;
8115 * Gets the right X coordinate of the element (element X position + element width)
8116 * @param {Boolean} local True to get the local css position instead of page coordinate
8119 getRight : function(local){
8121 return this.getX() + this.getWidth();
8123 return (this.getLeft(true) + this.getWidth()) || 0;
8128 * Gets the top Y coordinate
8129 * @param {Boolean} local True to get the local css position instead of page coordinate
8132 getTop : function(local) {
8136 return parseInt(this.getStyle("top"), 10) || 0;
8141 * Gets the bottom Y coordinate of the element (element Y position + element height)
8142 * @param {Boolean} local True to get the local css position instead of page coordinate
8145 getBottom : function(local){
8147 return this.getY() + this.getHeight();
8149 return (this.getTop(true) + this.getHeight()) || 0;
8154 * Initializes positioning on this element. If a desired position is not passed, it will make the
8155 * the element positioned relative IF it is not already positioned.
8156 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8157 * @param {Number} zIndex (optional) The zIndex to apply
8158 * @param {Number} x (optional) Set the page X position
8159 * @param {Number} y (optional) Set the page Y position
8161 position : function(pos, zIndex, x, y){
8163 if(this.getStyle('position') == 'static'){
8164 this.setStyle('position', 'relative');
8167 this.setStyle("position", pos);
8170 this.setStyle("z-index", zIndex);
8172 if(x !== undefined && y !== undefined){
8174 }else if(x !== undefined){
8176 }else if(y !== undefined){
8182 * Clear positioning back to the default when the document was loaded
8183 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8184 * @return {Roo.Element} this
8186 clearPositioning : function(value){
8194 "position" : "static"
8200 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8201 * snapshot before performing an update and then restoring the element.
8204 getPositioning : function(){
8205 var l = this.getStyle("left");
8206 var t = this.getStyle("top");
8208 "position" : this.getStyle("position"),
8210 "right" : l ? "" : this.getStyle("right"),
8212 "bottom" : t ? "" : this.getStyle("bottom"),
8213 "z-index" : this.getStyle("z-index")
8218 * Gets the width of the border(s) for the specified side(s)
8219 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8220 * passing lr would get the border (l)eft width + the border (r)ight width.
8221 * @return {Number} The width of the sides passed added together
8223 getBorderWidth : function(side){
8224 return this.addStyles(side, El.borders);
8228 * Gets the width of the padding(s) for the specified side(s)
8229 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8230 * passing lr would get the padding (l)eft + the padding (r)ight.
8231 * @return {Number} The padding of the sides passed added together
8233 getPadding : function(side){
8234 return this.addStyles(side, El.paddings);
8238 * Set positioning with an object returned by getPositioning().
8239 * @param {Object} posCfg
8240 * @return {Roo.Element} this
8242 setPositioning : function(pc){
8243 this.applyStyles(pc);
8244 if(pc.right == "auto"){
8245 this.dom.style.right = "";
8247 if(pc.bottom == "auto"){
8248 this.dom.style.bottom = "";
8254 fixDisplay : function(){
8255 if(this.getStyle("display") == "none"){
8256 this.setStyle("visibility", "hidden");
8257 this.setStyle("display", this.originalDisplay); // first try reverting to default
8258 if(this.getStyle("display") == "none"){ // if that fails, default to block
8259 this.setStyle("display", "block");
8265 * Quick set left and top adding default units
8266 * @param {String} left The left CSS property value
8267 * @param {String} top The top CSS property value
8268 * @return {Roo.Element} this
8270 setLeftTop : function(left, top){
8271 this.dom.style.left = this.addUnits(left);
8272 this.dom.style.top = this.addUnits(top);
8277 * Move this element relative to its current position.
8278 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8279 * @param {Number} distance How far to move the element in pixels
8280 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8281 * @return {Roo.Element} this
8283 move : function(direction, distance, animate){
8284 var xy = this.getXY();
8285 direction = direction.toLowerCase();
8289 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8293 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8298 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8303 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8310 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8311 * @return {Roo.Element} this
8314 if(!this.isClipped){
8315 this.isClipped = true;
8316 this.originalClip = {
8317 "o": this.getStyle("overflow"),
8318 "x": this.getStyle("overflow-x"),
8319 "y": this.getStyle("overflow-y")
8321 this.setStyle("overflow", "hidden");
8322 this.setStyle("overflow-x", "hidden");
8323 this.setStyle("overflow-y", "hidden");
8329 * Return clipping (overflow) to original clipping before clip() was called
8330 * @return {Roo.Element} this
8332 unclip : function(){
8334 this.isClipped = false;
8335 var o = this.originalClip;
8336 if(o.o){this.setStyle("overflow", o.o);}
8337 if(o.x){this.setStyle("overflow-x", o.x);}
8338 if(o.y){this.setStyle("overflow-y", o.y);}
8345 * Gets the x,y coordinates specified by the anchor position on the element.
8346 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8347 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8348 * {width: (target width), height: (target height)} (defaults to the element's current size)
8349 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8350 * @return {Array} [x, y] An array containing the element's x and y coordinates
8352 getAnchorXY : function(anchor, local, s){
8353 //Passing a different size is useful for pre-calculating anchors,
8354 //especially for anchored animations that change the el size.
8356 var w, h, vp = false;
8359 if(d == document.body || d == document){
8361 w = D.getViewWidth(); h = D.getViewHeight();
8363 w = this.getWidth(); h = this.getHeight();
8366 w = s.width; h = s.height;
8368 var x = 0, y = 0, r = Math.round;
8369 switch((anchor || "tl").toLowerCase()){
8411 var sc = this.getScroll();
8412 return [x + sc.left, y + sc.top];
8414 //Add the element's offset xy
8415 var o = this.getXY();
8416 return [x+o[0], y+o[1]];
8420 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8421 * supported position values.
8422 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8423 * @param {String} position The position to align to.
8424 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8425 * @return {Array} [x, y]
8427 getAlignToXY : function(el, p, o){
8431 throw "Element.alignTo with an element that doesn't exist";
8433 var c = false; //constrain to viewport
8434 var p1 = "", p2 = "";
8441 }else if(p.indexOf("-") == -1){
8444 p = p.toLowerCase();
8445 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8447 throw "Element.alignTo with an invalid alignment " + p;
8449 p1 = m[1]; p2 = m[2]; c = !!m[3];
8451 //Subtract the aligned el's internal xy from the target's offset xy
8452 //plus custom offset to get the aligned el's new offset xy
8453 var a1 = this.getAnchorXY(p1, true);
8454 var a2 = el.getAnchorXY(p2, false);
8455 var x = a2[0] - a1[0] + o[0];
8456 var y = a2[1] - a1[1] + o[1];
8458 //constrain the aligned el to viewport if necessary
8459 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8460 // 5px of margin for ie
8461 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8463 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8464 //perpendicular to the vp border, allow the aligned el to slide on that border,
8465 //otherwise swap the aligned el to the opposite border of the target.
8466 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8467 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8468 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8469 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8472 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8473 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8475 if((x+w) > dw + scrollX){
8476 x = swapX ? r.left-w : dw+scrollX-w;
8479 x = swapX ? r.right : scrollX;
8481 if((y+h) > dh + scrollY){
8482 y = swapY ? r.top-h : dh+scrollY-h;
8485 y = swapY ? r.bottom : scrollY;
8492 getConstrainToXY : function(){
8493 var os = {top:0, left:0, bottom:0, right: 0};
8495 return function(el, local, offsets, proposedXY){
8497 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8499 var vw, vh, vx = 0, vy = 0;
8500 if(el.dom == document.body || el.dom == document){
8501 vw = Roo.lib.Dom.getViewWidth();
8502 vh = Roo.lib.Dom.getViewHeight();
8504 vw = el.dom.clientWidth;
8505 vh = el.dom.clientHeight;
8507 var vxy = el.getXY();
8513 var s = el.getScroll();
8515 vx += offsets.left + s.left;
8516 vy += offsets.top + s.top;
8518 vw -= offsets.right;
8519 vh -= offsets.bottom;
8524 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8525 var x = xy[0], y = xy[1];
8526 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8528 // only move it if it needs it
8531 // first validate right/bottom
8540 // then make sure top/left isn't negative
8549 return moved ? [x, y] : false;
8554 adjustForConstraints : function(xy, parent, offsets){
8555 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8559 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8560 * document it aligns it to the viewport.
8561 * The position parameter is optional, and can be specified in any one of the following formats:
8563 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8564 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8565 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8566 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8567 * <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
8568 * element's anchor point, and the second value is used as the target's anchor point.</li>
8570 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8571 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8572 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8573 * that specified in order to enforce the viewport constraints.
8574 * Following are all of the supported anchor positions:
8577 ----- -----------------------------
8578 tl The top left corner (default)
8579 t The center of the top edge
8580 tr The top right corner
8581 l The center of the left edge
8582 c In the center of the element
8583 r The center of the right edge
8584 bl The bottom left corner
8585 b The center of the bottom edge
8586 br The bottom right corner
8590 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8591 el.alignTo("other-el");
8593 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8594 el.alignTo("other-el", "tr?");
8596 // align the bottom right corner of el with the center left edge of other-el
8597 el.alignTo("other-el", "br-l?");
8599 // align the center of el with the bottom left corner of other-el and
8600 // adjust the x position by -6 pixels (and the y position by 0)
8601 el.alignTo("other-el", "c-bl", [-6, 0]);
8603 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8604 * @param {String} position The position to align to.
8605 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8606 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8607 * @return {Roo.Element} this
8609 alignTo : function(element, position, offsets, animate){
8610 var xy = this.getAlignToXY(element, position, offsets);
8611 this.setXY(xy, this.preanim(arguments, 3));
8616 * Anchors an element to another element and realigns it when the window is resized.
8617 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8618 * @param {String} position The position to align to.
8619 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8620 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8621 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8622 * is a number, it is used as the buffer delay (defaults to 50ms).
8623 * @param {Function} callback The function to call after the animation finishes
8624 * @return {Roo.Element} this
8626 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8627 var action = function(){
8628 this.alignTo(el, alignment, offsets, animate);
8629 Roo.callback(callback, this);
8631 Roo.EventManager.onWindowResize(action, this);
8632 var tm = typeof monitorScroll;
8633 if(tm != 'undefined'){
8634 Roo.EventManager.on(window, 'scroll', action, this,
8635 {buffer: tm == 'number' ? monitorScroll : 50});
8637 action.call(this); // align immediately
8641 * Clears any opacity settings from this element. Required in some cases for IE.
8642 * @return {Roo.Element} this
8644 clearOpacity : function(){
8645 if (window.ActiveXObject) {
8646 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8647 this.dom.style.filter = "";
8650 this.dom.style.opacity = "";
8651 this.dom.style["-moz-opacity"] = "";
8652 this.dom.style["-khtml-opacity"] = "";
8658 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8659 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8660 * @return {Roo.Element} this
8662 hide : function(animate){
8663 this.setVisible(false, this.preanim(arguments, 0));
8668 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8669 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8670 * @return {Roo.Element} this
8672 show : function(animate){
8673 this.setVisible(true, this.preanim(arguments, 0));
8678 * @private Test if size has a unit, otherwise appends the default
8680 addUnits : function(size){
8681 return Roo.Element.addUnits(size, this.defaultUnit);
8685 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8686 * @return {Roo.Element} this
8688 beginMeasure : function(){
8690 if(el.offsetWidth || el.offsetHeight){
8691 return this; // offsets work already
8694 var p = this.dom, b = document.body; // start with this element
8695 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8696 var pe = Roo.get(p);
8697 if(pe.getStyle('display') == 'none'){
8698 changed.push({el: p, visibility: pe.getStyle("visibility")});
8699 p.style.visibility = "hidden";
8700 p.style.display = "block";
8704 this._measureChanged = changed;
8710 * Restores displays to before beginMeasure was called
8711 * @return {Roo.Element} this
8713 endMeasure : function(){
8714 var changed = this._measureChanged;
8716 for(var i = 0, len = changed.length; i < len; i++) {
8718 r.el.style.visibility = r.visibility;
8719 r.el.style.display = "none";
8721 this._measureChanged = null;
8727 * Update the innerHTML of this element, optionally searching for and processing scripts
8728 * @param {String} html The new HTML
8729 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8730 * @param {Function} callback For async script loading you can be noticed when the update completes
8731 * @return {Roo.Element} this
8733 update : function(html, loadScripts, callback){
8734 if(typeof html == "undefined"){
8737 if(loadScripts !== true){
8738 this.dom.innerHTML = html;
8739 if(typeof callback == "function"){
8747 html += '<span id="' + id + '"></span>';
8749 E.onAvailable(id, function(){
8750 var hd = document.getElementsByTagName("head")[0];
8751 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8752 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8753 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8756 while(match = re.exec(html)){
8757 var attrs = match[1];
8758 var srcMatch = attrs ? attrs.match(srcRe) : false;
8759 if(srcMatch && srcMatch[2]){
8760 var s = document.createElement("script");
8761 s.src = srcMatch[2];
8762 var typeMatch = attrs.match(typeRe);
8763 if(typeMatch && typeMatch[2]){
8764 s.type = typeMatch[2];
8767 }else if(match[2] && match[2].length > 0){
8768 if(window.execScript) {
8769 window.execScript(match[2]);
8777 window.eval(match[2]);
8781 var el = document.getElementById(id);
8782 if(el){el.parentNode.removeChild(el);}
8783 if(typeof callback == "function"){
8787 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8792 * Direct access to the UpdateManager update() method (takes the same parameters).
8793 * @param {String/Function} url The url for this request or a function to call to get the url
8794 * @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}
8795 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8796 * @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.
8797 * @return {Roo.Element} this
8800 var um = this.getUpdateManager();
8801 um.update.apply(um, arguments);
8806 * Gets this element's UpdateManager
8807 * @return {Roo.UpdateManager} The UpdateManager
8809 getUpdateManager : function(){
8810 if(!this.updateManager){
8811 this.updateManager = new Roo.UpdateManager(this);
8813 return this.updateManager;
8817 * Disables text selection for this element (normalized across browsers)
8818 * @return {Roo.Element} this
8820 unselectable : function(){
8821 this.dom.unselectable = "on";
8822 this.swallowEvent("selectstart", true);
8823 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8824 this.addClass("x-unselectable");
8829 * Calculates the x, y to center this element on the screen
8830 * @return {Array} The x, y values [x, y]
8832 getCenterXY : function(){
8833 return this.getAlignToXY(document, 'c-c');
8837 * Centers the Element in either the viewport, or another Element.
8838 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8840 center : function(centerIn){
8841 this.alignTo(centerIn || document, 'c-c');
8846 * Tests various css rules/browsers to determine if this element uses a border box
8849 isBorderBox : function(){
8850 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8854 * Return a box {x, y, width, height} that can be used to set another elements
8855 * size/location to match this element.
8856 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8857 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8858 * @return {Object} box An object in the format {x, y, width, height}
8860 getBox : function(contentBox, local){
8865 var left = parseInt(this.getStyle("left"), 10) || 0;
8866 var top = parseInt(this.getStyle("top"), 10) || 0;
8869 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8871 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8873 var l = this.getBorderWidth("l")+this.getPadding("l");
8874 var r = this.getBorderWidth("r")+this.getPadding("r");
8875 var t = this.getBorderWidth("t")+this.getPadding("t");
8876 var b = this.getBorderWidth("b")+this.getPadding("b");
8877 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)};
8879 bx.right = bx.x + bx.width;
8880 bx.bottom = bx.y + bx.height;
8885 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8886 for more information about the sides.
8887 * @param {String} sides
8890 getFrameWidth : function(sides, onlyContentBox){
8891 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8895 * 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.
8896 * @param {Object} box The box to fill {x, y, width, height}
8897 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8898 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8899 * @return {Roo.Element} this
8901 setBox : function(box, adjust, animate){
8902 var w = box.width, h = box.height;
8903 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8904 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8905 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8907 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8912 * Forces the browser to repaint this element
8913 * @return {Roo.Element} this
8915 repaint : function(){
8917 this.addClass("x-repaint");
8918 setTimeout(function(){
8919 Roo.get(dom).removeClass("x-repaint");
8925 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8926 * then it returns the calculated width of the sides (see getPadding)
8927 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8928 * @return {Object/Number}
8930 getMargins : function(side){
8933 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8934 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8935 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8936 right: parseInt(this.getStyle("margin-right"), 10) || 0
8939 return this.addStyles(side, El.margins);
8944 addStyles : function(sides, styles){
8946 for(var i = 0, len = sides.length; i < len; i++){
8947 v = this.getStyle(styles[sides.charAt(i)]);
8949 w = parseInt(v, 10);
8957 * Creates a proxy element of this element
8958 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8959 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8960 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8961 * @return {Roo.Element} The new proxy element
8963 createProxy : function(config, renderTo, matchBox){
8965 renderTo = Roo.getDom(renderTo);
8967 renderTo = document.body;
8969 config = typeof config == "object" ?
8970 config : {tag : "div", cls: config};
8971 var proxy = Roo.DomHelper.append(renderTo, config, true);
8973 proxy.setBox(this.getBox());
8979 * Puts a mask over this element to disable user interaction. Requires core.css.
8980 * This method can only be applied to elements which accept child nodes.
8981 * @param {String} msg (optional) A message to display in the mask
8982 * @param {String} msgCls (optional) A css class to apply to the msg element
8983 * @return {Element} The mask element
8985 mask : function(msg, msgCls)
8987 if(this.getStyle("position") == "static" && this.dom.tagName !== 'BODY'){
8988 this.setStyle("position", "relative");
8991 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8993 this.addClass("x-masked");
8994 this._mask.setDisplayed(true);
8999 while (dom && dom.style) {
9000 if (!isNaN(parseInt(dom.style.zIndex))) {
9001 z = Math.max(z, parseInt(dom.style.zIndex));
9003 dom = dom.parentNode;
9005 // if we are masking the body - then it hides everything..
9006 if (this.dom == document.body) {
9008 this._mask.setWidth(Roo.lib.Dom.getDocumentWidth());
9009 this._mask.setHeight(Roo.lib.Dom.getDocumentHeight());
9012 if(typeof msg == 'string'){
9014 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
9016 var mm = this._maskMsg;
9017 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
9018 if (mm.dom.firstChild) { // weird IE issue?
9019 mm.dom.firstChild.innerHTML = msg;
9021 mm.setDisplayed(true);
9023 mm.setStyle('z-index', z + 102);
9025 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
9026 this._mask.setHeight(this.getHeight());
9028 this._mask.setStyle('z-index', z + 100);
9034 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
9035 * it is cached for reuse.
9037 unmask : function(removeEl){
9039 if(removeEl === true){
9040 this._mask.remove();
9043 this._maskMsg.remove();
9044 delete this._maskMsg;
9047 this._mask.setDisplayed(false);
9049 this._maskMsg.setDisplayed(false);
9053 this.removeClass("x-masked");
9057 * Returns true if this element is masked
9060 isMasked : function(){
9061 return this._mask && this._mask.isVisible();
9065 * Creates an iframe shim for this element to keep selects and other windowed objects from
9067 * @return {Roo.Element} The new shim element
9069 createShim : function(){
9070 var el = document.createElement('iframe');
9071 el.frameBorder = 'no';
9072 el.className = 'roo-shim';
9073 if(Roo.isIE && Roo.isSecure){
9074 el.src = Roo.SSL_SECURE_URL;
9076 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
9077 shim.autoBoxAdjust = false;
9082 * Removes this element from the DOM and deletes it from the cache
9084 remove : function(){
9085 if(this.dom.parentNode){
9086 this.dom.parentNode.removeChild(this.dom);
9088 delete El.cache[this.dom.id];
9092 * Sets up event handlers to add and remove a css class when the mouse is over this element
9093 * @param {String} className
9094 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
9095 * mouseout events for children elements
9096 * @return {Roo.Element} this
9098 addClassOnOver : function(className, preventFlicker){
9099 this.on("mouseover", function(){
9100 Roo.fly(this, '_internal').addClass(className);
9102 var removeFn = function(e){
9103 if(preventFlicker !== true || !e.within(this, true)){
9104 Roo.fly(this, '_internal').removeClass(className);
9107 this.on("mouseout", removeFn, this.dom);
9112 * Sets up event handlers to add and remove a css class when this element has the focus
9113 * @param {String} className
9114 * @return {Roo.Element} this
9116 addClassOnFocus : function(className){
9117 this.on("focus", function(){
9118 Roo.fly(this, '_internal').addClass(className);
9120 this.on("blur", function(){
9121 Roo.fly(this, '_internal').removeClass(className);
9126 * 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)
9127 * @param {String} className
9128 * @return {Roo.Element} this
9130 addClassOnClick : function(className){
9132 this.on("mousedown", function(){
9133 Roo.fly(dom, '_internal').addClass(className);
9134 var d = Roo.get(document);
9135 var fn = function(){
9136 Roo.fly(dom, '_internal').removeClass(className);
9137 d.removeListener("mouseup", fn);
9139 d.on("mouseup", fn);
9145 * Stops the specified event from bubbling and optionally prevents the default action
9146 * @param {String} eventName
9147 * @param {Boolean} preventDefault (optional) true to prevent the default action too
9148 * @return {Roo.Element} this
9150 swallowEvent : function(eventName, preventDefault){
9151 var fn = function(e){
9152 e.stopPropagation();
9157 if(eventName instanceof Array){
9158 for(var i = 0, len = eventName.length; i < len; i++){
9159 this.on(eventName[i], fn);
9163 this.on(eventName, fn);
9170 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
9173 * Sizes this element to its parent element's dimensions performing
9174 * neccessary box adjustments.
9175 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9176 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9177 * @return {Roo.Element} this
9179 fitToParent : function(monitorResize, targetParent) {
9180 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9181 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9182 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9185 var p = Roo.get(targetParent || this.dom.parentNode);
9186 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9187 if (monitorResize === true) {
9188 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9189 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9195 * Gets the next sibling, skipping text nodes
9196 * @return {HTMLElement} The next sibling or null
9198 getNextSibling : function(){
9199 var n = this.dom.nextSibling;
9200 while(n && n.nodeType != 1){
9207 * Gets the previous sibling, skipping text nodes
9208 * @return {HTMLElement} The previous sibling or null
9210 getPrevSibling : function(){
9211 var n = this.dom.previousSibling;
9212 while(n && n.nodeType != 1){
9213 n = n.previousSibling;
9220 * Appends the passed element(s) to this element
9221 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9222 * @return {Roo.Element} this
9224 appendChild: function(el){
9231 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9232 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9233 * automatically generated with the specified attributes.
9234 * @param {HTMLElement} insertBefore (optional) a child element of this element
9235 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9236 * @return {Roo.Element} The new child element
9238 createChild: function(config, insertBefore, returnDom){
9239 config = config || {tag:'div'};
9241 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9243 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9247 * Appends this element to the passed element
9248 * @param {String/HTMLElement/Element} el The new parent element
9249 * @return {Roo.Element} this
9251 appendTo: function(el){
9252 el = Roo.getDom(el);
9253 el.appendChild(this.dom);
9258 * Inserts this element before the passed element in the DOM
9259 * @param {String/HTMLElement/Element} el The element to insert before
9260 * @return {Roo.Element} this
9262 insertBefore: function(el){
9263 el = Roo.getDom(el);
9264 el.parentNode.insertBefore(this.dom, el);
9269 * Inserts this element after the passed element in the DOM
9270 * @param {String/HTMLElement/Element} el The element to insert after
9271 * @return {Roo.Element} this
9273 insertAfter: function(el){
9274 el = Roo.getDom(el);
9275 el.parentNode.insertBefore(this.dom, el.nextSibling);
9280 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9281 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9282 * @return {Roo.Element} The new child
9284 insertFirst: function(el, returnDom){
9286 if(typeof el == 'object' && !el.nodeType){ // dh config
9287 return this.createChild(el, this.dom.firstChild, returnDom);
9289 el = Roo.getDom(el);
9290 this.dom.insertBefore(el, this.dom.firstChild);
9291 return !returnDom ? Roo.get(el) : el;
9296 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9297 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9298 * @param {String} where (optional) 'before' or 'after' defaults to before
9299 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9300 * @return {Roo.Element} the inserted Element
9302 insertSibling: function(el, where, returnDom){
9303 where = where ? where.toLowerCase() : 'before';
9305 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9307 if(typeof el == 'object' && !el.nodeType){ // dh config
9308 if(where == 'after' && !this.dom.nextSibling){
9309 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9311 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9315 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9316 where == 'before' ? this.dom : this.dom.nextSibling);
9325 * Creates and wraps this element with another element
9326 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9327 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9328 * @return {HTMLElement/Element} The newly created wrapper element
9330 wrap: function(config, returnDom){
9332 config = {tag: "div"};
9334 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9335 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9340 * Replaces the passed element with this element
9341 * @param {String/HTMLElement/Element} el The element to replace
9342 * @return {Roo.Element} this
9344 replace: function(el){
9346 this.insertBefore(el);
9352 * Inserts an html fragment into this element
9353 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9354 * @param {String} html The HTML fragment
9355 * @param {Boolean} returnEl True to return an Roo.Element
9356 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9358 insertHtml : function(where, html, returnEl){
9359 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9360 return returnEl ? Roo.get(el) : el;
9364 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9365 * @param {Object} o The object with the attributes
9366 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9367 * @return {Roo.Element} this
9369 set : function(o, useSet){
9371 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9373 if(attr == "style" || typeof o[attr] == "function") continue;
9375 el.className = o["cls"];
9377 if(useSet) el.setAttribute(attr, o[attr]);
9378 else el[attr] = o[attr];
9382 Roo.DomHelper.applyStyles(el, o.style);
9388 * Convenience method for constructing a KeyMap
9389 * @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:
9390 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9391 * @param {Function} fn The function to call
9392 * @param {Object} scope (optional) The scope of the function
9393 * @return {Roo.KeyMap} The KeyMap created
9395 addKeyListener : function(key, fn, scope){
9397 if(typeof key != "object" || key instanceof Array){
9413 return new Roo.KeyMap(this, config);
9417 * Creates a KeyMap for this element
9418 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9419 * @return {Roo.KeyMap} The KeyMap created
9421 addKeyMap : function(config){
9422 return new Roo.KeyMap(this, config);
9426 * Returns true if this element is scrollable.
9429 isScrollable : function(){
9431 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9435 * 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().
9436 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9437 * @param {Number} value The new scroll value
9438 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9439 * @return {Element} this
9442 scrollTo : function(side, value, animate){
9443 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9445 this.dom[prop] = value;
9447 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9448 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9454 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9455 * within this element's scrollable range.
9456 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9457 * @param {Number} distance How far to scroll the element in pixels
9458 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9459 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9460 * was scrolled as far as it could go.
9462 scroll : function(direction, distance, animate){
9463 if(!this.isScrollable()){
9467 var l = el.scrollLeft, t = el.scrollTop;
9468 var w = el.scrollWidth, h = el.scrollHeight;
9469 var cw = el.clientWidth, ch = el.clientHeight;
9470 direction = direction.toLowerCase();
9471 var scrolled = false;
9472 var a = this.preanim(arguments, 2);
9477 var v = Math.min(l + distance, w-cw);
9478 this.scrollTo("left", v, a);
9485 var v = Math.max(l - distance, 0);
9486 this.scrollTo("left", v, a);
9494 var v = Math.max(t - distance, 0);
9495 this.scrollTo("top", v, a);
9503 var v = Math.min(t + distance, h-ch);
9504 this.scrollTo("top", v, a);
9513 * Translates the passed page coordinates into left/top css values for this element
9514 * @param {Number/Array} x The page x or an array containing [x, y]
9515 * @param {Number} y The page y
9516 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9518 translatePoints : function(x, y){
9519 if(typeof x == 'object' || x instanceof Array){
9522 var p = this.getStyle('position');
9523 var o = this.getXY();
9525 var l = parseInt(this.getStyle('left'), 10);
9526 var t = parseInt(this.getStyle('top'), 10);
9529 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9532 t = (p == "relative") ? 0 : this.dom.offsetTop;
9535 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9539 * Returns the current scroll position of the element.
9540 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9542 getScroll : function(){
9543 var d = this.dom, doc = document;
9544 if(d == doc || d == doc.body){
9545 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9546 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9547 return {left: l, top: t};
9549 return {left: d.scrollLeft, top: d.scrollTop};
9554 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9555 * are convert to standard 6 digit hex color.
9556 * @param {String} attr The css attribute
9557 * @param {String} defaultValue The default value to use when a valid color isn't found
9558 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9561 getColor : function(attr, defaultValue, prefix){
9562 var v = this.getStyle(attr);
9563 if(!v || v == "transparent" || v == "inherit") {
9564 return defaultValue;
9566 var color = typeof prefix == "undefined" ? "#" : prefix;
9567 if(v.substr(0, 4) == "rgb("){
9568 var rvs = v.slice(4, v.length -1).split(",");
9569 for(var i = 0; i < 3; i++){
9570 var h = parseInt(rvs[i]).toString(16);
9577 if(v.substr(0, 1) == "#"){
9579 for(var i = 1; i < 4; i++){
9580 var c = v.charAt(i);
9583 }else if(v.length == 7){
9584 color += v.substr(1);
9588 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9592 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9593 * gradient background, rounded corners and a 4-way shadow.
9594 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9595 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9596 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9597 * @return {Roo.Element} this
9599 boxWrap : function(cls){
9600 cls = cls || 'x-box';
9601 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9602 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9607 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9608 * @param {String} namespace The namespace in which to look for the attribute
9609 * @param {String} name The attribute name
9610 * @return {String} The attribute value
9612 getAttributeNS : Roo.isIE ? function(ns, name){
9614 var type = typeof d[ns+":"+name];
9615 if(type != 'undefined' && type != 'unknown'){
9616 return d[ns+":"+name];
9619 } : function(ns, name){
9621 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9626 * Sets or Returns the value the dom attribute value
9627 * @param {String|Object} name The attribute name (or object to set multiple attributes)
9628 * @param {String} value (optional) The value to set the attribute to
9629 * @return {String} The attribute value
9631 attr : function(name){
9632 if (arguments.length > 1) {
9633 this.dom.setAttribute(name, arguments[1]);
9634 return arguments[1];
9636 if (typeof(name) == 'object') {
9637 for(var i in name) {
9638 this.attr(i, name[i]);
9644 if (!this.dom.hasAttribute(name)) {
9647 return this.dom.getAttribute(name);
9654 var ep = El.prototype;
9657 * Appends an event handler (Shorthand for addListener)
9658 * @param {String} eventName The type of event to append
9659 * @param {Function} fn The method the event invokes
9660 * @param {Object} scope (optional) The scope (this object) of the fn
9661 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9664 ep.on = ep.addListener;
9666 ep.mon = ep.addListener;
9669 * Removes an event handler from this element (shorthand for removeListener)
9670 * @param {String} eventName the type of event to remove
9671 * @param {Function} fn the method the event invokes
9672 * @return {Roo.Element} this
9675 ep.un = ep.removeListener;
9678 * true to automatically adjust width and height settings for box-model issues (default to true)
9680 ep.autoBoxAdjust = true;
9683 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9686 El.addUnits = function(v, defaultUnit){
9687 if(v === "" || v == "auto"){
9690 if(v === undefined){
9693 if(typeof v == "number" || !El.unitPattern.test(v)){
9694 return v + (defaultUnit || 'px');
9699 // special markup used throughout Roo when box wrapping elements
9700 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>';
9702 * Visibility mode constant - Use visibility to hide element
9708 * Visibility mode constant - Use display to hide element
9714 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9715 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9716 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9728 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9729 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9730 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9731 * @return {Element} The Element object
9734 El.get = function(el){
9736 if(!el){ return null; }
9737 if(typeof el == "string"){ // element id
9738 if(!(elm = document.getElementById(el))){
9741 if(ex = El.cache[el]){
9744 ex = El.cache[el] = new El(elm);
9747 }else if(el.tagName){ // dom element
9751 if(ex = El.cache[id]){
9754 ex = El.cache[id] = new El(el);
9757 }else if(el instanceof El){
9759 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9760 // catch case where it hasn't been appended
9761 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9764 }else if(el.isComposite){
9766 }else if(el instanceof Array){
9767 return El.select(el);
9768 }else if(el == document){
9769 // create a bogus element object representing the document object
9771 var f = function(){};
9772 f.prototype = El.prototype;
9774 docEl.dom = document;
9782 El.uncache = function(el){
9783 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9785 delete El.cache[a[i].id || a[i]];
9791 // Garbage collection - uncache elements/purge listeners on orphaned elements
9792 // so we don't hold a reference and cause the browser to retain them
9793 El.garbageCollect = function(){
9794 if(!Roo.enableGarbageCollector){
9795 clearInterval(El.collectorThread);
9798 for(var eid in El.cache){
9799 var el = El.cache[eid], d = el.dom;
9800 // -------------------------------------------------------
9801 // Determining what is garbage:
9802 // -------------------------------------------------------
9804 // dom node is null, definitely garbage
9805 // -------------------------------------------------------
9807 // no parentNode == direct orphan, definitely garbage
9808 // -------------------------------------------------------
9809 // !d.offsetParent && !document.getElementById(eid)
9810 // display none elements have no offsetParent so we will
9811 // also try to look it up by it's id. However, check
9812 // offsetParent first so we don't do unneeded lookups.
9813 // This enables collection of elements that are not orphans
9814 // directly, but somewhere up the line they have an orphan
9816 // -------------------------------------------------------
9817 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9818 delete El.cache[eid];
9819 if(d && Roo.enableListenerCollection){
9825 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9829 El.Flyweight = function(dom){
9832 El.Flyweight.prototype = El.prototype;
9834 El._flyweights = {};
9836 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9837 * the dom node can be overwritten by other code.
9838 * @param {String/HTMLElement} el The dom node or id
9839 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9840 * prevent conflicts (e.g. internally Roo uses "_internal")
9842 * @return {Element} The shared Element object
9844 El.fly = function(el, named){
9845 named = named || '_global';
9846 el = Roo.getDom(el);
9850 if(!El._flyweights[named]){
9851 El._flyweights[named] = new El.Flyweight();
9853 El._flyweights[named].dom = el;
9854 return El._flyweights[named];
9858 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9859 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9860 * Shorthand of {@link Roo.Element#get}
9861 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9862 * @return {Element} The Element object
9868 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9869 * the dom node can be overwritten by other code.
9870 * Shorthand of {@link Roo.Element#fly}
9871 * @param {String/HTMLElement} el The dom node or id
9872 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9873 * prevent conflicts (e.g. internally Roo uses "_internal")
9875 * @return {Element} The shared Element object
9881 // speedy lookup for elements never to box adjust
9882 var noBoxAdjust = Roo.isStrict ? {
9885 input:1, select:1, textarea:1
9887 if(Roo.isIE || Roo.isGecko){
9888 noBoxAdjust['button'] = 1;
9892 Roo.EventManager.on(window, 'unload', function(){
9894 delete El._flyweights;
9902 Roo.Element.selectorFunction = Roo.DomQuery.select;
9905 Roo.Element.select = function(selector, unique, root){
9907 if(typeof selector == "string"){
9908 els = Roo.Element.selectorFunction(selector, root);
9909 }else if(selector.length !== undefined){
9912 throw "Invalid selector";
9914 if(unique === true){
9915 return new Roo.CompositeElement(els);
9917 return new Roo.CompositeElementLite(els);
9921 * Selects elements based on the passed CSS selector to enable working on them as 1.
9922 * @param {String/Array} selector The CSS selector or an array of elements
9923 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9924 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9925 * @return {CompositeElementLite/CompositeElement}
9929 Roo.select = Roo.Element.select;
9946 * Ext JS Library 1.1.1
9947 * Copyright(c) 2006-2007, Ext JS, LLC.
9949 * Originally Released Under LGPL - original licence link has changed is not relivant.
9952 * <script type="text/javascript">
9957 //Notifies Element that fx methods are available
9958 Roo.enableFx = true;
9962 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9963 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9964 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9965 * Element effects to work.</p><br/>
9967 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9968 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9969 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9970 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9971 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9972 * expected results and should be done with care.</p><br/>
9974 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9975 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9978 ----- -----------------------------
9979 tl The top left corner
9980 t The center of the top edge
9981 tr The top right corner
9982 l The center of the left edge
9983 r The center of the right edge
9984 bl The bottom left corner
9985 b The center of the bottom edge
9986 br The bottom right corner
9988 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9989 * below are common options that can be passed to any Fx method.</b>
9990 * @cfg {Function} callback A function called when the effect is finished
9991 * @cfg {Object} scope The scope of the effect function
9992 * @cfg {String} easing A valid Easing value for the effect
9993 * @cfg {String} afterCls A css class to apply after the effect
9994 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9995 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9996 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9997 * effects that end with the element being visually hidden, ignored otherwise)
9998 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9999 * a function which returns such a specification that will be applied to the Element after the effect finishes
10000 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
10001 * @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
10002 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
10006 * Slides the element into view. An anchor point can be optionally passed to set the point of
10007 * origin for the slide effect. This function automatically handles wrapping the element with
10008 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10011 // default: slide the element in from the top
10014 // custom: slide the element in from the right with a 2-second duration
10015 el.slideIn('r', { duration: 2 });
10017 // common config options shown with default values
10023 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10024 * @param {Object} options (optional) Object literal with any of the Fx config options
10025 * @return {Roo.Element} The Element
10027 slideIn : function(anchor, o){
10028 var el = this.getFxEl();
10031 el.queueFx(o, function(){
10033 anchor = anchor || "t";
10035 // fix display to visibility
10038 // restore values after effect
10039 var r = this.getFxRestore();
10040 var b = this.getBox();
10041 // fixed size for slide
10045 var wrap = this.fxWrap(r.pos, o, "hidden");
10047 var st = this.dom.style;
10048 st.visibility = "visible";
10049 st.position = "absolute";
10051 // clear out temp styles after slide and unwrap
10052 var after = function(){
10053 el.fxUnwrap(wrap, r.pos, o);
10054 st.width = r.width;
10055 st.height = r.height;
10058 // time to calc the positions
10059 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
10061 switch(anchor.toLowerCase()){
10063 wrap.setSize(b.width, 0);
10064 st.left = st.bottom = "0";
10068 wrap.setSize(0, b.height);
10069 st.right = st.top = "0";
10073 wrap.setSize(0, b.height);
10074 wrap.setX(b.right);
10075 st.left = st.top = "0";
10076 a = {width: bw, points: pt};
10079 wrap.setSize(b.width, 0);
10080 wrap.setY(b.bottom);
10081 st.left = st.top = "0";
10082 a = {height: bh, points: pt};
10085 wrap.setSize(0, 0);
10086 st.right = st.bottom = "0";
10087 a = {width: bw, height: bh};
10090 wrap.setSize(0, 0);
10091 wrap.setY(b.y+b.height);
10092 st.right = st.top = "0";
10093 a = {width: bw, height: bh, points: pt};
10096 wrap.setSize(0, 0);
10097 wrap.setXY([b.right, b.bottom]);
10098 st.left = st.top = "0";
10099 a = {width: bw, height: bh, points: pt};
10102 wrap.setSize(0, 0);
10103 wrap.setX(b.x+b.width);
10104 st.left = st.bottom = "0";
10105 a = {width: bw, height: bh, points: pt};
10108 this.dom.style.visibility = "visible";
10111 arguments.callee.anim = wrap.fxanim(a,
10121 * Slides the element out of view. An anchor point can be optionally passed to set the end point
10122 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
10123 * 'hidden') but block elements will still take up space in the document. The element must be removed
10124 * from the DOM using the 'remove' config option if desired. This function automatically handles
10125 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
10128 // default: slide the element out to the top
10131 // custom: slide the element out to the right with a 2-second duration
10132 el.slideOut('r', { duration: 2 });
10134 // common config options shown with default values
10142 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
10143 * @param {Object} options (optional) Object literal with any of the Fx config options
10144 * @return {Roo.Element} The Element
10146 slideOut : function(anchor, o){
10147 var el = this.getFxEl();
10150 el.queueFx(o, function(){
10152 anchor = anchor || "t";
10154 // restore values after effect
10155 var r = this.getFxRestore();
10157 var b = this.getBox();
10158 // fixed size for slide
10162 var wrap = this.fxWrap(r.pos, o, "visible");
10164 var st = this.dom.style;
10165 st.visibility = "visible";
10166 st.position = "absolute";
10170 var after = function(){
10172 el.setDisplayed(false);
10177 el.fxUnwrap(wrap, r.pos, o);
10179 st.width = r.width;
10180 st.height = r.height;
10185 var a, zero = {to: 0};
10186 switch(anchor.toLowerCase()){
10188 st.left = st.bottom = "0";
10189 a = {height: zero};
10192 st.right = st.top = "0";
10196 st.left = st.top = "0";
10197 a = {width: zero, points: {to:[b.right, b.y]}};
10200 st.left = st.top = "0";
10201 a = {height: zero, points: {to:[b.x, b.bottom]}};
10204 st.right = st.bottom = "0";
10205 a = {width: zero, height: zero};
10208 st.right = st.top = "0";
10209 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10212 st.left = st.top = "0";
10213 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10216 st.left = st.bottom = "0";
10217 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10221 arguments.callee.anim = wrap.fxanim(a,
10231 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10232 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10233 * The element must be removed from the DOM using the 'remove' config option if desired.
10239 // common config options shown with default values
10247 * @param {Object} options (optional) Object literal with any of the Fx config options
10248 * @return {Roo.Element} The Element
10250 puff : function(o){
10251 var el = this.getFxEl();
10254 el.queueFx(o, function(){
10255 this.clearOpacity();
10258 // restore values after effect
10259 var r = this.getFxRestore();
10260 var st = this.dom.style;
10262 var after = function(){
10264 el.setDisplayed(false);
10271 el.setPositioning(r.pos);
10272 st.width = r.width;
10273 st.height = r.height;
10278 var width = this.getWidth();
10279 var height = this.getHeight();
10281 arguments.callee.anim = this.fxanim({
10282 width : {to: this.adjustWidth(width * 2)},
10283 height : {to: this.adjustHeight(height * 2)},
10284 points : {by: [-(width * .5), -(height * .5)]},
10286 fontSize: {to:200, unit: "%"}
10297 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10298 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10299 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10305 // all config options shown with default values
10313 * @param {Object} options (optional) Object literal with any of the Fx config options
10314 * @return {Roo.Element} The Element
10316 switchOff : function(o){
10317 var el = this.getFxEl();
10320 el.queueFx(o, function(){
10321 this.clearOpacity();
10324 // restore values after effect
10325 var r = this.getFxRestore();
10326 var st = this.dom.style;
10328 var after = function(){
10330 el.setDisplayed(false);
10336 el.setPositioning(r.pos);
10337 st.width = r.width;
10338 st.height = r.height;
10343 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10344 this.clearOpacity();
10348 points:{by:[0, this.getHeight() * .5]}
10349 }, o, 'motion', 0.3, 'easeIn', after);
10350 }).defer(100, this);
10357 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10358 * changed using the "attr" config option) and then fading back to the original color. If no original
10359 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10362 // default: highlight background to yellow
10365 // custom: highlight foreground text to blue for 2 seconds
10366 el.highlight("0000ff", { attr: 'color', duration: 2 });
10368 // common config options shown with default values
10369 el.highlight("ffff9c", {
10370 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10371 endColor: (current color) or "ffffff",
10376 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10377 * @param {Object} options (optional) Object literal with any of the Fx config options
10378 * @return {Roo.Element} The Element
10380 highlight : function(color, o){
10381 var el = this.getFxEl();
10384 el.queueFx(o, function(){
10385 color = color || "ffff9c";
10386 attr = o.attr || "backgroundColor";
10388 this.clearOpacity();
10391 var origColor = this.getColor(attr);
10392 var restoreColor = this.dom.style[attr];
10393 endColor = (o.endColor || origColor) || "ffffff";
10395 var after = function(){
10396 el.dom.style[attr] = restoreColor;
10401 a[attr] = {from: color, to: endColor};
10402 arguments.callee.anim = this.fxanim(a,
10412 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10415 // default: a single light blue ripple
10418 // custom: 3 red ripples lasting 3 seconds total
10419 el.frame("ff0000", 3, { duration: 3 });
10421 // common config options shown with default values
10422 el.frame("C3DAF9", 1, {
10423 duration: 1 //duration of entire animation (not each individual ripple)
10424 // Note: Easing is not configurable and will be ignored if included
10427 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10428 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10429 * @param {Object} options (optional) Object literal with any of the Fx config options
10430 * @return {Roo.Element} The Element
10432 frame : function(color, count, o){
10433 var el = this.getFxEl();
10436 el.queueFx(o, function(){
10437 color = color || "#C3DAF9";
10438 if(color.length == 6){
10439 color = "#" + color;
10441 count = count || 1;
10442 duration = o.duration || 1;
10445 var b = this.getBox();
10446 var animFn = function(){
10447 var proxy = this.createProxy({
10450 visbility:"hidden",
10451 position:"absolute",
10452 "z-index":"35000", // yee haw
10453 border:"0px solid " + color
10456 var scale = Roo.isBorderBox ? 2 : 1;
10458 top:{from:b.y, to:b.y - 20},
10459 left:{from:b.x, to:b.x - 20},
10460 borderWidth:{from:0, to:10},
10461 opacity:{from:1, to:0},
10462 height:{from:b.height, to:(b.height + (20*scale))},
10463 width:{from:b.width, to:(b.width + (20*scale))}
10464 }, duration, function(){
10468 animFn.defer((duration/2)*1000, this);
10479 * Creates a pause before any subsequent queued effects begin. If there are
10480 * no effects queued after the pause it will have no effect.
10485 * @param {Number} seconds The length of time to pause (in seconds)
10486 * @return {Roo.Element} The Element
10488 pause : function(seconds){
10489 var el = this.getFxEl();
10492 el.queueFx(o, function(){
10493 setTimeout(function(){
10495 }, seconds * 1000);
10501 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10502 * using the "endOpacity" config option.
10505 // default: fade in from opacity 0 to 100%
10508 // custom: fade in from opacity 0 to 75% over 2 seconds
10509 el.fadeIn({ endOpacity: .75, duration: 2});
10511 // common config options shown with default values
10513 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10518 * @param {Object} options (optional) Object literal with any of the Fx config options
10519 * @return {Roo.Element} The Element
10521 fadeIn : function(o){
10522 var el = this.getFxEl();
10524 el.queueFx(o, function(){
10525 this.setOpacity(0);
10527 this.dom.style.visibility = 'visible';
10528 var to = o.endOpacity || 1;
10529 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10530 o, null, .5, "easeOut", function(){
10532 this.clearOpacity();
10541 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10542 * using the "endOpacity" config option.
10545 // default: fade out from the element's current opacity to 0
10548 // custom: fade out from the element's current opacity to 25% over 2 seconds
10549 el.fadeOut({ endOpacity: .25, duration: 2});
10551 // common config options shown with default values
10553 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10560 * @param {Object} options (optional) Object literal with any of the Fx config options
10561 * @return {Roo.Element} The Element
10563 fadeOut : function(o){
10564 var el = this.getFxEl();
10566 el.queueFx(o, function(){
10567 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10568 o, null, .5, "easeOut", function(){
10569 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10570 this.dom.style.display = "none";
10572 this.dom.style.visibility = "hidden";
10574 this.clearOpacity();
10582 * Animates the transition of an element's dimensions from a starting height/width
10583 * to an ending height/width.
10586 // change height and width to 100x100 pixels
10587 el.scale(100, 100);
10589 // common config options shown with default values. The height and width will default to
10590 // the element's existing values if passed as null.
10593 [element's height], {
10598 * @param {Number} width The new width (pass undefined to keep the original width)
10599 * @param {Number} height The new height (pass undefined to keep the original height)
10600 * @param {Object} options (optional) Object literal with any of the Fx config options
10601 * @return {Roo.Element} The Element
10603 scale : function(w, h, o){
10604 this.shift(Roo.apply({}, o, {
10612 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10613 * Any of these properties not specified in the config object will not be changed. This effect
10614 * requires that at least one new dimension, position or opacity setting must be passed in on
10615 * the config object in order for the function to have any effect.
10618 // slide the element horizontally to x position 200 while changing the height and opacity
10619 el.shift({ x: 200, height: 50, opacity: .8 });
10621 // common config options shown with default values.
10623 width: [element's width],
10624 height: [element's height],
10625 x: [element's x position],
10626 y: [element's y position],
10627 opacity: [element's opacity],
10632 * @param {Object} options Object literal with any of the Fx config options
10633 * @return {Roo.Element} The Element
10635 shift : function(o){
10636 var el = this.getFxEl();
10638 el.queueFx(o, function(){
10639 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10640 if(w !== undefined){
10641 a.width = {to: this.adjustWidth(w)};
10643 if(h !== undefined){
10644 a.height = {to: this.adjustHeight(h)};
10646 if(x !== undefined || y !== undefined){
10648 x !== undefined ? x : this.getX(),
10649 y !== undefined ? y : this.getY()
10652 if(op !== undefined){
10653 a.opacity = {to: op};
10655 if(o.xy !== undefined){
10656 a.points = {to: o.xy};
10658 arguments.callee.anim = this.fxanim(a,
10659 o, 'motion', .35, "easeOut", function(){
10667 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10668 * ending point of the effect.
10671 // default: slide the element downward while fading out
10674 // custom: slide the element out to the right with a 2-second duration
10675 el.ghost('r', { duration: 2 });
10677 // common config options shown with default values
10685 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10686 * @param {Object} options (optional) Object literal with any of the Fx config options
10687 * @return {Roo.Element} The Element
10689 ghost : function(anchor, o){
10690 var el = this.getFxEl();
10693 el.queueFx(o, function(){
10694 anchor = anchor || "b";
10696 // restore values after effect
10697 var r = this.getFxRestore();
10698 var w = this.getWidth(),
10699 h = this.getHeight();
10701 var st = this.dom.style;
10703 var after = function(){
10705 el.setDisplayed(false);
10711 el.setPositioning(r.pos);
10712 st.width = r.width;
10713 st.height = r.height;
10718 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10719 switch(anchor.toLowerCase()){
10746 arguments.callee.anim = this.fxanim(a,
10756 * Ensures that all effects queued after syncFx is called on the element are
10757 * run concurrently. This is the opposite of {@link #sequenceFx}.
10758 * @return {Roo.Element} The Element
10760 syncFx : function(){
10761 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10770 * Ensures that all effects queued after sequenceFx is called on the element are
10771 * run in sequence. This is the opposite of {@link #syncFx}.
10772 * @return {Roo.Element} The Element
10774 sequenceFx : function(){
10775 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10777 concurrent : false,
10784 nextFx : function(){
10785 var ef = this.fxQueue[0];
10792 * Returns true if the element has any effects actively running or queued, else returns false.
10793 * @return {Boolean} True if element has active effects, else false
10795 hasActiveFx : function(){
10796 return this.fxQueue && this.fxQueue[0];
10800 * Stops any running effects and clears the element's internal effects queue if it contains
10801 * any additional effects that haven't started yet.
10802 * @return {Roo.Element} The Element
10804 stopFx : function(){
10805 if(this.hasActiveFx()){
10806 var cur = this.fxQueue[0];
10807 if(cur && cur.anim && cur.anim.isAnimated()){
10808 this.fxQueue = [cur]; // clear out others
10809 cur.anim.stop(true);
10816 beforeFx : function(o){
10817 if(this.hasActiveFx() && !o.concurrent){
10828 * Returns true if the element is currently blocking so that no other effect can be queued
10829 * until this effect is finished, else returns false if blocking is not set. This is commonly
10830 * used to ensure that an effect initiated by a user action runs to completion prior to the
10831 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10832 * @return {Boolean} True if blocking, else false
10834 hasFxBlock : function(){
10835 var q = this.fxQueue;
10836 return q && q[0] && q[0].block;
10840 queueFx : function(o, fn){
10844 if(!this.hasFxBlock()){
10845 Roo.applyIf(o, this.fxDefaults);
10847 var run = this.beforeFx(o);
10848 fn.block = o.block;
10849 this.fxQueue.push(fn);
10861 fxWrap : function(pos, o, vis){
10863 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10866 wrapXY = this.getXY();
10868 var div = document.createElement("div");
10869 div.style.visibility = vis;
10870 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10871 wrap.setPositioning(pos);
10872 if(wrap.getStyle("position") == "static"){
10873 wrap.position("relative");
10875 this.clearPositioning('auto');
10877 wrap.dom.appendChild(this.dom);
10879 wrap.setXY(wrapXY);
10886 fxUnwrap : function(wrap, pos, o){
10887 this.clearPositioning();
10888 this.setPositioning(pos);
10890 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10896 getFxRestore : function(){
10897 var st = this.dom.style;
10898 return {pos: this.getPositioning(), width: st.width, height : st.height};
10902 afterFx : function(o){
10904 this.applyStyles(o.afterStyle);
10907 this.addClass(o.afterCls);
10909 if(o.remove === true){
10912 Roo.callback(o.callback, o.scope, [this]);
10914 this.fxQueue.shift();
10920 getFxEl : function(){ // support for composite element fx
10921 return Roo.get(this.dom);
10925 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10926 animType = animType || 'run';
10928 var anim = Roo.lib.Anim[animType](
10930 (opt.duration || defaultDur) || .35,
10931 (opt.easing || defaultEase) || 'easeOut',
10933 Roo.callback(cb, this);
10942 // backwords compat
10943 Roo.Fx.resize = Roo.Fx.scale;
10945 //When included, Roo.Fx is automatically applied to Element so that all basic
10946 //effects are available directly via the Element API
10947 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10949 * Ext JS Library 1.1.1
10950 * Copyright(c) 2006-2007, Ext JS, LLC.
10952 * Originally Released Under LGPL - original licence link has changed is not relivant.
10955 * <script type="text/javascript">
10960 * @class Roo.CompositeElement
10961 * Standard composite class. Creates a Roo.Element for every element in the collection.
10963 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10964 * actions will be performed on all the elements in this collection.</b>
10966 * All methods return <i>this</i> and can be chained.
10968 var els = Roo.select("#some-el div.some-class", true);
10969 // or select directly from an existing element
10970 var el = Roo.get('some-el');
10971 el.select('div.some-class', true);
10973 els.setWidth(100); // all elements become 100 width
10974 els.hide(true); // all elements fade out and hide
10976 els.setWidth(100).hide(true);
10979 Roo.CompositeElement = function(els){
10980 this.elements = [];
10981 this.addElements(els);
10983 Roo.CompositeElement.prototype = {
10985 addElements : function(els){
10986 if(!els) return this;
10987 if(typeof els == "string"){
10988 els = Roo.Element.selectorFunction(els);
10990 var yels = this.elements;
10991 var index = yels.length-1;
10992 for(var i = 0, len = els.length; i < len; i++) {
10993 yels[++index] = Roo.get(els[i]);
10999 * Clears this composite and adds the elements returned by the passed selector.
11000 * @param {String/Array} els A string CSS selector, an array of elements or an element
11001 * @return {CompositeElement} this
11003 fill : function(els){
11004 this.elements = [];
11010 * Filters this composite to only elements that match the passed selector.
11011 * @param {String} selector A string CSS selector
11012 * @param {Boolean} inverse return inverse filter (not matches)
11013 * @return {CompositeElement} this
11015 filter : function(selector, inverse){
11017 inverse = inverse || false;
11018 this.each(function(el){
11019 var match = inverse ? !el.is(selector) : el.is(selector);
11021 els[els.length] = el.dom;
11028 invoke : function(fn, args){
11029 var els = this.elements;
11030 for(var i = 0, len = els.length; i < len; i++) {
11031 Roo.Element.prototype[fn].apply(els[i], args);
11036 * Adds elements to this composite.
11037 * @param {String/Array} els A string CSS selector, an array of elements or an element
11038 * @return {CompositeElement} this
11040 add : function(els){
11041 if(typeof els == "string"){
11042 this.addElements(Roo.Element.selectorFunction(els));
11043 }else if(els.length !== undefined){
11044 this.addElements(els);
11046 this.addElements([els]);
11051 * Calls the passed function passing (el, this, index) for each element in this composite.
11052 * @param {Function} fn The function to call
11053 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11054 * @return {CompositeElement} this
11056 each : function(fn, scope){
11057 var els = this.elements;
11058 for(var i = 0, len = els.length; i < len; i++){
11059 if(fn.call(scope || els[i], els[i], this, i) === false) {
11067 * Returns the Element object at the specified index
11068 * @param {Number} index
11069 * @return {Roo.Element}
11071 item : function(index){
11072 return this.elements[index] || null;
11076 * Returns the first Element
11077 * @return {Roo.Element}
11079 first : function(){
11080 return this.item(0);
11084 * Returns the last Element
11085 * @return {Roo.Element}
11088 return this.item(this.elements.length-1);
11092 * Returns the number of elements in this composite
11095 getCount : function(){
11096 return this.elements.length;
11100 * Returns true if this composite contains the passed element
11103 contains : function(el){
11104 return this.indexOf(el) !== -1;
11108 * Returns true if this composite contains the passed element
11111 indexOf : function(el){
11112 return this.elements.indexOf(Roo.get(el));
11117 * Removes the specified element(s).
11118 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
11119 * or an array of any of those.
11120 * @param {Boolean} removeDom (optional) True to also remove the element from the document
11121 * @return {CompositeElement} this
11123 removeElement : function(el, removeDom){
11124 if(el instanceof Array){
11125 for(var i = 0, len = el.length; i < len; i++){
11126 this.removeElement(el[i]);
11130 var index = typeof el == 'number' ? el : this.indexOf(el);
11133 var d = this.elements[index];
11137 d.parentNode.removeChild(d);
11140 this.elements.splice(index, 1);
11146 * Replaces the specified element with the passed element.
11147 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
11149 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
11150 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
11151 * @return {CompositeElement} this
11153 replaceElement : function(el, replacement, domReplace){
11154 var index = typeof el == 'number' ? el : this.indexOf(el);
11157 this.elements[index].replaceWith(replacement);
11159 this.elements.splice(index, 1, Roo.get(replacement))
11166 * Removes all elements.
11168 clear : function(){
11169 this.elements = [];
11173 Roo.CompositeElement.createCall = function(proto, fnName){
11174 if(!proto[fnName]){
11175 proto[fnName] = function(){
11176 return this.invoke(fnName, arguments);
11180 for(var fnName in Roo.Element.prototype){
11181 if(typeof Roo.Element.prototype[fnName] == "function"){
11182 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
11188 * Ext JS Library 1.1.1
11189 * Copyright(c) 2006-2007, Ext JS, LLC.
11191 * Originally Released Under LGPL - original licence link has changed is not relivant.
11194 * <script type="text/javascript">
11198 * @class Roo.CompositeElementLite
11199 * @extends Roo.CompositeElement
11200 * Flyweight composite class. Reuses the same Roo.Element for element operations.
11202 var els = Roo.select("#some-el div.some-class");
11203 // or select directly from an existing element
11204 var el = Roo.get('some-el');
11205 el.select('div.some-class');
11207 els.setWidth(100); // all elements become 100 width
11208 els.hide(true); // all elements fade out and hide
11210 els.setWidth(100).hide(true);
11211 </code></pre><br><br>
11212 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11213 * actions will be performed on all the elements in this collection.</b>
11215 Roo.CompositeElementLite = function(els){
11216 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11217 this.el = new Roo.Element.Flyweight();
11219 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11220 addElements : function(els){
11222 if(els instanceof Array){
11223 this.elements = this.elements.concat(els);
11225 var yels = this.elements;
11226 var index = yels.length-1;
11227 for(var i = 0, len = els.length; i < len; i++) {
11228 yels[++index] = els[i];
11234 invoke : function(fn, args){
11235 var els = this.elements;
11237 for(var i = 0, len = els.length; i < len; i++) {
11239 Roo.Element.prototype[fn].apply(el, args);
11244 * Returns a flyweight Element of the dom element object at the specified index
11245 * @param {Number} index
11246 * @return {Roo.Element}
11248 item : function(index){
11249 if(!this.elements[index]){
11252 this.el.dom = this.elements[index];
11256 // fixes scope with flyweight
11257 addListener : function(eventName, handler, scope, opt){
11258 var els = this.elements;
11259 for(var i = 0, len = els.length; i < len; i++) {
11260 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11266 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11267 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11268 * a reference to the dom node, use el.dom.</b>
11269 * @param {Function} fn The function to call
11270 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11271 * @return {CompositeElement} this
11273 each : function(fn, scope){
11274 var els = this.elements;
11276 for(var i = 0, len = els.length; i < len; i++){
11278 if(fn.call(scope || el, el, this, i) === false){
11285 indexOf : function(el){
11286 return this.elements.indexOf(Roo.getDom(el));
11289 replaceElement : function(el, replacement, domReplace){
11290 var index = typeof el == 'number' ? el : this.indexOf(el);
11292 replacement = Roo.getDom(replacement);
11294 var d = this.elements[index];
11295 d.parentNode.insertBefore(replacement, d);
11296 d.parentNode.removeChild(d);
11298 this.elements.splice(index, 1, replacement);
11303 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11307 * Ext JS Library 1.1.1
11308 * Copyright(c) 2006-2007, Ext JS, LLC.
11310 * Originally Released Under LGPL - original licence link has changed is not relivant.
11313 * <script type="text/javascript">
11319 * @class Roo.data.Connection
11320 * @extends Roo.util.Observable
11321 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11322 * either to a configured URL, or to a URL specified at request time.<br><br>
11324 * Requests made by this class are asynchronous, and will return immediately. No data from
11325 * the server will be available to the statement immediately following the {@link #request} call.
11326 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11328 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11329 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11330 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11331 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11332 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11333 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11334 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11335 * standard DOM methods.
11337 * @param {Object} config a configuration object.
11339 Roo.data.Connection = function(config){
11340 Roo.apply(this, config);
11343 * @event beforerequest
11344 * Fires before a network request is made to retrieve a data object.
11345 * @param {Connection} conn This Connection object.
11346 * @param {Object} options The options config object passed to the {@link #request} method.
11348 "beforerequest" : true,
11350 * @event requestcomplete
11351 * Fires if the request was successfully completed.
11352 * @param {Connection} conn This Connection object.
11353 * @param {Object} response The XHR object containing the response data.
11354 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11355 * @param {Object} options The options config object passed to the {@link #request} method.
11357 "requestcomplete" : true,
11359 * @event requestexception
11360 * Fires if an error HTTP status was returned from the server.
11361 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11362 * @param {Connection} conn This Connection object.
11363 * @param {Object} response The XHR object containing the response data.
11364 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11365 * @param {Object} options The options config object passed to the {@link #request} method.
11367 "requestexception" : true
11369 Roo.data.Connection.superclass.constructor.call(this);
11372 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11374 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11377 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11378 * extra parameters to each request made by this object. (defaults to undefined)
11381 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11382 * to each request made by this object. (defaults to undefined)
11385 * @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)
11388 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11392 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11398 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11401 disableCaching: true,
11404 * Sends an HTTP request to a remote server.
11405 * @param {Object} options An object which may contain the following properties:<ul>
11406 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11407 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11408 * request, a url encoded string or a function to call to get either.</li>
11409 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11410 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11411 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11412 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11413 * <li>options {Object} The parameter to the request call.</li>
11414 * <li>success {Boolean} True if the request succeeded.</li>
11415 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11417 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11418 * The callback is passed the following parameters:<ul>
11419 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11420 * <li>options {Object} The parameter to the request call.</li>
11422 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11423 * The callback is passed the following parameters:<ul>
11424 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11425 * <li>options {Object} The parameter to the request call.</li>
11427 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11428 * for the callback function. Defaults to the browser window.</li>
11429 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11430 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11431 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11432 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11433 * params for the post data. Any params will be appended to the URL.</li>
11434 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11436 * @return {Number} transactionId
11438 request : function(o){
11439 if(this.fireEvent("beforerequest", this, o) !== false){
11442 if(typeof p == "function"){
11443 p = p.call(o.scope||window, o);
11445 if(typeof p == "object"){
11446 p = Roo.urlEncode(o.params);
11448 if(this.extraParams){
11449 var extras = Roo.urlEncode(this.extraParams);
11450 p = p ? (p + '&' + extras) : extras;
11453 var url = o.url || this.url;
11454 if(typeof url == 'function'){
11455 url = url.call(o.scope||window, o);
11459 var form = Roo.getDom(o.form);
11460 url = url || form.action;
11462 var enctype = form.getAttribute("enctype");
11463 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11464 return this.doFormUpload(o, p, url);
11466 var f = Roo.lib.Ajax.serializeForm(form);
11467 p = p ? (p + '&' + f) : f;
11470 var hs = o.headers;
11471 if(this.defaultHeaders){
11472 hs = Roo.apply(hs || {}, this.defaultHeaders);
11479 success: this.handleResponse,
11480 failure: this.handleFailure,
11482 argument: {options: o},
11483 timeout : o.timeout || this.timeout
11486 var method = o.method||this.method||(p ? "POST" : "GET");
11488 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11489 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11492 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11496 }else if(this.autoAbort !== false){
11500 if((method == 'GET' && p) || o.xmlData){
11501 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11504 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11505 return this.transId;
11507 Roo.callback(o.callback, o.scope, [o, null, null]);
11513 * Determine whether this object has a request outstanding.
11514 * @param {Number} transactionId (Optional) defaults to the last transaction
11515 * @return {Boolean} True if there is an outstanding request.
11517 isLoading : function(transId){
11519 return Roo.lib.Ajax.isCallInProgress(transId);
11521 return this.transId ? true : false;
11526 * Aborts any outstanding request.
11527 * @param {Number} transactionId (Optional) defaults to the last transaction
11529 abort : function(transId){
11530 if(transId || this.isLoading()){
11531 Roo.lib.Ajax.abort(transId || this.transId);
11536 handleResponse : function(response){
11537 this.transId = false;
11538 var options = response.argument.options;
11539 response.argument = options ? options.argument : null;
11540 this.fireEvent("requestcomplete", this, response, options);
11541 Roo.callback(options.success, options.scope, [response, options]);
11542 Roo.callback(options.callback, options.scope, [options, true, response]);
11546 handleFailure : function(response, e){
11547 this.transId = false;
11548 var options = response.argument.options;
11549 response.argument = options ? options.argument : null;
11550 this.fireEvent("requestexception", this, response, options, e);
11551 Roo.callback(options.failure, options.scope, [response, options]);
11552 Roo.callback(options.callback, options.scope, [options, false, response]);
11556 doFormUpload : function(o, ps, url){
11558 var frame = document.createElement('iframe');
11561 frame.className = 'x-hidden';
11563 frame.src = Roo.SSL_SECURE_URL;
11565 document.body.appendChild(frame);
11568 document.frames[id].name = id;
11571 var form = Roo.getDom(o.form);
11573 form.method = 'POST';
11574 form.enctype = form.encoding = 'multipart/form-data';
11580 if(ps){ // add dynamic params
11582 ps = Roo.urlDecode(ps, false);
11584 if(ps.hasOwnProperty(k)){
11585 hd = document.createElement('input');
11586 hd.type = 'hidden';
11589 form.appendChild(hd);
11596 var r = { // bogus response object
11601 r.argument = o ? o.argument : null;
11606 doc = frame.contentWindow.document;
11608 doc = (frame.contentDocument || window.frames[id].document);
11610 if(doc && doc.body){
11611 r.responseText = doc.body.innerHTML;
11613 if(doc && doc.XMLDocument){
11614 r.responseXML = doc.XMLDocument;
11616 r.responseXML = doc;
11623 Roo.EventManager.removeListener(frame, 'load', cb, this);
11625 this.fireEvent("requestcomplete", this, r, o);
11626 Roo.callback(o.success, o.scope, [r, o]);
11627 Roo.callback(o.callback, o.scope, [o, true, r]);
11629 setTimeout(function(){document.body.removeChild(frame);}, 100);
11632 Roo.EventManager.on(frame, 'load', cb, this);
11635 if(hiddens){ // remove dynamic params
11636 for(var i = 0, len = hiddens.length; i < len; i++){
11637 form.removeChild(hiddens[i]);
11644 * Ext JS Library 1.1.1
11645 * Copyright(c) 2006-2007, Ext JS, LLC.
11647 * Originally Released Under LGPL - original licence link has changed is not relivant.
11650 * <script type="text/javascript">
11654 * Global Ajax request class.
11657 * @extends Roo.data.Connection
11660 * @cfg {String} url The default URL to be used for requests to the server. (defaults to undefined)
11661 * @cfg {Object} extraParams An object containing properties which are used as extra parameters to each request made by this object. (defaults to undefined)
11662 * @cfg {Object} defaultHeaders An object containing request headers which are added to each request made by this object. (defaults to undefined)
11663 * @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)
11664 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11665 * @cfg {Boolean} autoAbort (Optional) Whether a new request should abort any pending requests. (defaults to false)
11666 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11668 Roo.Ajax = new Roo.data.Connection({
11677 * Serialize the passed form into a url encoded string
11679 * @param {String/HTMLElement} form
11682 serializeForm : function(form){
11683 return Roo.lib.Ajax.serializeForm(form);
11687 * Ext JS Library 1.1.1
11688 * Copyright(c) 2006-2007, Ext JS, LLC.
11690 * Originally Released Under LGPL - original licence link has changed is not relivant.
11693 * <script type="text/javascript">
11698 * @class Roo.UpdateManager
11699 * @extends Roo.util.Observable
11700 * Provides AJAX-style update for Element object.<br><br>
11703 * // Get it from a Roo.Element object
11704 * var el = Roo.get("foo");
11705 * var mgr = el.getUpdateManager();
11706 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11708 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11710 * // or directly (returns the same UpdateManager instance)
11711 * var mgr = new Roo.UpdateManager("myElementId");
11712 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11713 * mgr.on("update", myFcnNeedsToKnow);
11715 // short handed call directly from the element object
11716 Roo.get("foo").load({
11720 text: "Loading Foo..."
11724 * Create new UpdateManager directly.
11725 * @param {String/HTMLElement/Roo.Element} el The element to update
11726 * @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).
11728 Roo.UpdateManager = function(el, forceNew){
11730 if(!forceNew && el.updateManager){
11731 return el.updateManager;
11734 * The Element object
11735 * @type Roo.Element
11739 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11742 this.defaultUrl = null;
11746 * @event beforeupdate
11747 * Fired before an update is made, return false from your handler and the update is cancelled.
11748 * @param {Roo.Element} el
11749 * @param {String/Object/Function} url
11750 * @param {String/Object} params
11752 "beforeupdate": true,
11755 * Fired after successful update is made.
11756 * @param {Roo.Element} el
11757 * @param {Object} oResponseObject The response Object
11762 * Fired on update failure.
11763 * @param {Roo.Element} el
11764 * @param {Object} oResponseObject The response Object
11768 var d = Roo.UpdateManager.defaults;
11770 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11773 this.sslBlankUrl = d.sslBlankUrl;
11775 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11778 this.disableCaching = d.disableCaching;
11780 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11783 this.indicatorText = d.indicatorText;
11785 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11788 this.showLoadIndicator = d.showLoadIndicator;
11790 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11793 this.timeout = d.timeout;
11796 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11799 this.loadScripts = d.loadScripts;
11802 * Transaction object of current executing transaction
11804 this.transaction = null;
11809 this.autoRefreshProcId = null;
11811 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11814 this.refreshDelegate = this.refresh.createDelegate(this);
11816 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11819 this.updateDelegate = this.update.createDelegate(this);
11821 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11824 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11828 this.successDelegate = this.processSuccess.createDelegate(this);
11832 this.failureDelegate = this.processFailure.createDelegate(this);
11834 if(!this.renderer){
11836 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11838 this.renderer = new Roo.UpdateManager.BasicRenderer();
11841 Roo.UpdateManager.superclass.constructor.call(this);
11844 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11846 * Get the Element this UpdateManager is bound to
11847 * @return {Roo.Element} The element
11849 getEl : function(){
11853 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11854 * @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:
11857 url: "your-url.php",<br/>
11858 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11859 callback: yourFunction,<br/>
11860 scope: yourObject, //(optional scope) <br/>
11861 discardUrl: false, <br/>
11862 nocache: false,<br/>
11863 text: "Loading...",<br/>
11865 scripts: false<br/>
11868 * The only required property is url. The optional properties nocache, text and scripts
11869 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11870 * @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}
11871 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11872 * @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.
11874 update : function(url, params, callback, discardUrl){
11875 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11876 var method = this.method,
11878 if(typeof url == "object"){ // must be config object
11881 params = params || cfg.params;
11882 callback = callback || cfg.callback;
11883 discardUrl = discardUrl || cfg.discardUrl;
11884 if(callback && cfg.scope){
11885 callback = callback.createDelegate(cfg.scope);
11887 if(typeof cfg.method != "undefined"){method = cfg.method;};
11888 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11889 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11890 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11891 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11893 this.showLoading();
11895 this.defaultUrl = url;
11897 if(typeof url == "function"){
11898 url = url.call(this);
11901 method = method || (params ? "POST" : "GET");
11902 if(method == "GET"){
11903 url = this.prepareUrl(url);
11906 var o = Roo.apply(cfg ||{}, {
11909 success: this.successDelegate,
11910 failure: this.failureDelegate,
11911 callback: undefined,
11912 timeout: (this.timeout*1000),
11913 argument: {"url": url, "form": null, "callback": callback, "params": params}
11915 Roo.log("updated manager called with timeout of " + o.timeout);
11916 this.transaction = Roo.Ajax.request(o);
11921 * 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.
11922 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11923 * @param {String/HTMLElement} form The form Id or form element
11924 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11925 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11926 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11928 formUpdate : function(form, url, reset, callback){
11929 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11930 if(typeof url == "function"){
11931 url = url.call(this);
11933 form = Roo.getDom(form);
11934 this.transaction = Roo.Ajax.request({
11937 success: this.successDelegate,
11938 failure: this.failureDelegate,
11939 timeout: (this.timeout*1000),
11940 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11942 this.showLoading.defer(1, this);
11947 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11948 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11950 refresh : function(callback){
11951 if(this.defaultUrl == null){
11954 this.update(this.defaultUrl, null, callback, true);
11958 * Set this element to auto refresh.
11959 * @param {Number} interval How often to update (in seconds).
11960 * @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)
11961 * @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}
11962 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11963 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11965 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11967 this.update(url || this.defaultUrl, params, callback, true);
11969 if(this.autoRefreshProcId){
11970 clearInterval(this.autoRefreshProcId);
11972 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11976 * Stop auto refresh on this element.
11978 stopAutoRefresh : function(){
11979 if(this.autoRefreshProcId){
11980 clearInterval(this.autoRefreshProcId);
11981 delete this.autoRefreshProcId;
11985 isAutoRefreshing : function(){
11986 return this.autoRefreshProcId ? true : false;
11989 * Called to update the element to "Loading" state. Override to perform custom action.
11991 showLoading : function(){
11992 if(this.showLoadIndicator){
11993 this.el.update(this.indicatorText);
11998 * Adds unique parameter to query string if disableCaching = true
12001 prepareUrl : function(url){
12002 if(this.disableCaching){
12003 var append = "_dc=" + (new Date().getTime());
12004 if(url.indexOf("?") !== -1){
12005 url += "&" + append;
12007 url += "?" + append;
12016 processSuccess : function(response){
12017 this.transaction = null;
12018 if(response.argument.form && response.argument.reset){
12019 try{ // put in try/catch since some older FF releases had problems with this
12020 response.argument.form.reset();
12023 if(this.loadScripts){
12024 this.renderer.render(this.el, response, this,
12025 this.updateComplete.createDelegate(this, [response]));
12027 this.renderer.render(this.el, response, this);
12028 this.updateComplete(response);
12032 updateComplete : function(response){
12033 this.fireEvent("update", this.el, response);
12034 if(typeof response.argument.callback == "function"){
12035 response.argument.callback(this.el, true, response);
12042 processFailure : function(response){
12043 this.transaction = null;
12044 this.fireEvent("failure", this.el, response);
12045 if(typeof response.argument.callback == "function"){
12046 response.argument.callback(this.el, false, response);
12051 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
12052 * @param {Object} renderer The object implementing the render() method
12054 setRenderer : function(renderer){
12055 this.renderer = renderer;
12058 getRenderer : function(){
12059 return this.renderer;
12063 * Set the defaultUrl used for updates
12064 * @param {String/Function} defaultUrl The url or a function to call to get the url
12066 setDefaultUrl : function(defaultUrl){
12067 this.defaultUrl = defaultUrl;
12071 * Aborts the executing transaction
12073 abort : function(){
12074 if(this.transaction){
12075 Roo.Ajax.abort(this.transaction);
12080 * Returns true if an update is in progress
12081 * @return {Boolean}
12083 isUpdating : function(){
12084 if(this.transaction){
12085 return Roo.Ajax.isLoading(this.transaction);
12092 * @class Roo.UpdateManager.defaults
12093 * @static (not really - but it helps the doc tool)
12094 * The defaults collection enables customizing the default properties of UpdateManager
12096 Roo.UpdateManager.defaults = {
12098 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12104 * True to process scripts by default (Defaults to false).
12107 loadScripts : false,
12110 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12113 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12115 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12118 disableCaching : false,
12120 * Whether to show indicatorText when loading (Defaults to true).
12123 showLoadIndicator : true,
12125 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12128 indicatorText : '<div class="loading-indicator">Loading...</div>'
12132 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12134 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12135 * @param {String/HTMLElement/Roo.Element} el The element to update
12136 * @param {String} url The url
12137 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12138 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12141 * @member Roo.UpdateManager
12143 Roo.UpdateManager.updateElement = function(el, url, params, options){
12144 var um = Roo.get(el, true).getUpdateManager();
12145 Roo.apply(um, options);
12146 um.update(url, params, options ? options.callback : null);
12148 // alias for backwards compat
12149 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12151 * @class Roo.UpdateManager.BasicRenderer
12152 * Default Content renderer. Updates the elements innerHTML with the responseText.
12154 Roo.UpdateManager.BasicRenderer = function(){};
12156 Roo.UpdateManager.BasicRenderer.prototype = {
12158 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12159 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12160 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12161 * @param {Roo.Element} el The element being rendered
12162 * @param {Object} response The YUI Connect response object
12163 * @param {UpdateManager} updateManager The calling update manager
12164 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12166 render : function(el, response, updateManager, callback){
12167 el.update(response.responseText, updateManager.loadScripts, callback);
12173 * (c)) Alan Knowles
12179 * @class Roo.DomTemplate
12180 * @extends Roo.Template
12181 * An effort at a dom based template engine..
12183 * Similar to XTemplate, except it uses dom parsing to create the template..
12185 * Supported features:
12190 {a_variable} - output encoded.
12191 {a_variable.format:("Y-m-d")} - call a method on the variable
12192 {a_variable:raw} - unencoded output
12193 {a_variable:toFixed(1,2)} - Roo.util.Format."toFixed"
12194 {a_variable:this.method_on_template(...)} - call a method on the template object.
12199 <div roo-for="a_variable or condition.."></div>
12200 <div roo-if="a_variable or condition"></div>
12201 <div roo-exec="some javascript"></div>
12202 <div roo-name="named_template"></div>
12207 Roo.DomTemplate = function()
12209 Roo.DomTemplate.superclass.constructor.apply(this, arguments);
12216 Roo.extend(Roo.DomTemplate, Roo.Template, {
12218 * id counter for sub templates.
12222 * flag to indicate if dom parser is inside a pre,
12223 * it will strip whitespace if not.
12228 * The various sub templates
12236 * basic tag replacing syntax
12239 * // you can fake an object call by doing this
12243 re : /(\{|\%7B)([\w-\.]+)(?:\:([\w\.]*)(?:\(([^)]*?)?\))?)?(\}|\%7D)/g,
12244 //re : /\{([\w-\.]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
12246 iterChild : function (node, method) {
12248 var oldPre = this.inPre;
12249 if (node.tagName == 'PRE') {
12252 for( var i = 0; i < node.childNodes.length; i++) {
12253 method.call(this, node.childNodes[i]);
12255 this.inPre = oldPre;
12261 * compile the template
12263 * This is not recursive, so I'm not sure how nested templates are really going to be handled..
12266 compile: function()
12270 // covert the html into DOM...
12274 doc = document.implementation.createHTMLDocument("");
12275 doc.documentElement.innerHTML = this.html ;
12276 div = doc.documentElement;
12278 // old IE... - nasty -- it causes all sorts of issues.. with
12279 // images getting pulled from server..
12280 div = document.createElement('div');
12281 div.innerHTML = this.html;
12283 //doc.documentElement.innerHTML = htmlBody
12289 this.iterChild(div, function(n) {_t.compileNode(n, true); });
12291 var tpls = this.tpls;
12293 // create a top level template from the snippet..
12295 //Roo.log(div.innerHTML);
12302 body : div.innerHTML,
12315 Roo.each(tpls, function(tp){
12316 this.compileTpl(tp);
12317 this.tpls[tp.id] = tp;
12320 this.master = tpls[0];
12326 compileNode : function(node, istop) {
12331 // skip anything not a tag..
12332 if (node.nodeType != 1) {
12333 if (node.nodeType == 3 && !this.inPre) {
12334 // reduce white space..
12335 node.nodeValue = node.nodeValue.replace(/\s+/g, ' ');
12358 case (node.hasAttribute('roo-for')): tpl.attr = 'for'; break;
12359 case (node.hasAttribute('roo-if')): tpl.attr = 'if'; break;
12360 case (node.hasAttribute('roo-name')): tpl.attr = 'name'; break;
12361 case (node.hasAttribute('roo-exec')): tpl.attr = 'exec'; break;
12367 // just itterate children..
12368 this.iterChild(node,this.compileNode);
12371 tpl.uid = this.id++;
12372 tpl.value = node.getAttribute('roo-' + tpl.attr);
12373 node.removeAttribute('roo-'+ tpl.attr);
12374 if (tpl.attr != 'name') {
12375 var placeholder = document.createTextNode('{domtpl' + tpl.uid + '}');
12376 node.parentNode.replaceChild(placeholder, node);
12379 var placeholder = document.createElement('span');
12380 placeholder.className = 'roo-tpl-' + tpl.value;
12381 node.parentNode.replaceChild(placeholder, node);
12384 // parent now sees '{domtplXXXX}
12385 this.iterChild(node,this.compileNode);
12387 // we should now have node body...
12388 var div = document.createElement('div');
12389 div.appendChild(node);
12391 // this has the unfortunate side effect of converting tagged attributes
12392 // eg. href="{...}" into %7C...%7D
12393 // this has been fixed by searching for those combo's although it's a bit hacky..
12396 tpl.body = div.innerHTML;
12403 switch (tpl.value) {
12404 case '.': tpl.forCall = new Function('values', 'parent', 'with(values){ return values; }'); break;
12405 case '..': tpl.forCall= new Function('values', 'parent', 'with(values){ return parent; }'); break;
12406 default: tpl.forCall= new Function('values', 'parent', 'with(values){ return '+tpl.value+'; }');
12411 tpl.execCall = new Function('values', 'parent', 'with(values){ '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12415 tpl.ifCall = new Function('values', 'parent', 'with(values){ return '+(Roo.util.Format.htmlDecode(tpl.value))+'; }');
12419 tpl.id = tpl.value; // replace non characters???
12425 this.tpls.push(tpl);
12435 * Compile a segment of the template into a 'sub-template'
12441 compileTpl : function(tpl)
12443 var fm = Roo.util.Format;
12444 var useF = this.disableFormats !== true;
12446 var sep = Roo.isGecko ? "+\n" : ",\n";
12448 var undef = function(str) {
12449 Roo.debug && Roo.log("Property not found :" + str);
12453 //Roo.log(tpl.body);
12457 var fn = function(m, lbrace, name, format, args)
12460 //Roo.log(arguments);
12461 args = args ? args.replace(/\\'/g,"'") : args;
12462 //["{TEST:(a,b,c)}", "TEST", "", "a,b,c", 0, "{TEST:(a,b,c)}"]
12463 if (typeof(format) == 'undefined') {
12464 format = 'htmlEncode';
12466 if (format == 'raw' ) {
12470 if(name.substr(0, 6) == 'domtpl'){
12471 return "'"+ sep +'this.applySubTemplate('+name.substr(6)+', values, parent)'+sep+"'";
12474 // build an array of options to determine if value is undefined..
12476 // basically get 'xxxx.yyyy' then do
12477 // (typeof(xxxx) == 'undefined' || typeof(xxx.yyyy) == 'undefined') ?
12478 // (function () { Roo.log("Property not found"); return ''; })() :
12483 Roo.each(name.split('.'), function(st) {
12484 lookfor += (lookfor.length ? '.': '') + st;
12485 udef_ar.push( "(typeof(" + lookfor + ") == 'undefined')" );
12488 var udef_st = '((' + udef_ar.join(" || ") +") ? undef('" + name + "') : "; // .. needs )
12491 if(format && useF){
12493 args = args ? ',' + args : "";
12495 if(format.substr(0, 5) != "this."){
12496 format = "fm." + format + '(';
12498 format = 'this.call("'+ format.substr(5) + '", ';
12502 return "'"+ sep + udef_st + format + name + args + "))"+sep+"'";
12505 if (args && args.length) {
12506 // called with xxyx.yuu:(test,test)
12508 return "'"+ sep + udef_st + name + '(' + args + "))"+sep+"'";
12510 // raw.. - :raw modifier..
12511 return "'"+ sep + udef_st + name + ")"+sep+"'";
12515 // branched to use + in gecko and [].join() in others
12517 body = "tpl.compiled = function(values, parent){ with(values) { return '" +
12518 tpl.body.replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
12521 body = ["tpl.compiled = function(values, parent){ with (values) { return ['"];
12522 body.push(tpl.body.replace(/(\r\n|\n)/g,
12523 '\\n').replace(/'/g, "\\'").replace(this.re, fn));
12524 body.push("'].join('');};};");
12525 body = body.join('');
12528 Roo.debug && Roo.log(body.replace(/\\n/,'\n'));
12530 /** eval:var:tpl eval:var:fm eval:var:useF eval:var:undef */
12537 * same as applyTemplate, except it's done to one of the subTemplates
12538 * when using named templates, you can do:
12540 * var str = pl.applySubTemplate('your-name', values);
12543 * @param {Number} id of the template
12544 * @param {Object} values to apply to template
12545 * @param {Object} parent (normaly the instance of this object)
12547 applySubTemplate : function(id, values, parent)
12551 var t = this.tpls[id];
12555 if(t.ifCall && !t.ifCall.call(this, values, parent)){
12556 Roo.debug && Roo.log('if call on ' + t.value + ' return false');
12560 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-if="' + t.value + '" - ' + e.toString());
12567 if(t.execCall && t.execCall.call(this, values, parent)){
12571 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12577 var vs = t.forCall ? t.forCall.call(this, values, parent) : values;
12578 parent = t.target ? values : parent;
12579 if(t.forCall && vs instanceof Array){
12581 for(var i = 0, len = vs.length; i < len; i++){
12583 buf[buf.length] = t.compiled.call(this, vs[i], parent);
12585 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12587 //Roo.log(t.compiled);
12591 return buf.join('');
12594 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on roo-for="' + t.value + '" - ' + e.toString());
12599 return t.compiled.call(this, vs, parent);
12601 Roo.log('Xtemplate.applySubTemplate('+ id+ '): Exception thrown on body="' + t.value + '" - ' + e.toString());
12603 //Roo.log(t.compiled);
12611 applyTemplate : function(values){
12612 return this.master.compiled.call(this, values, {});
12613 //var s = this.subs;
12616 apply : function(){
12617 return this.applyTemplate.apply(this, arguments);
12622 Roo.DomTemplate.from = function(el){
12623 el = Roo.getDom(el);
12624 return new Roo.Domtemplate(el.value || el.innerHTML);
12627 * Ext JS Library 1.1.1
12628 * Copyright(c) 2006-2007, Ext JS, LLC.
12630 * Originally Released Under LGPL - original licence link has changed is not relivant.
12633 * <script type="text/javascript">
12637 * @class Roo.util.DelayedTask
12638 * Provides a convenient method of performing setTimeout where a new
12639 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12640 * You can use this class to buffer
12641 * the keypress events for a certain number of milliseconds, and perform only if they stop
12642 * for that amount of time.
12643 * @constructor The parameters to this constructor serve as defaults and are not required.
12644 * @param {Function} fn (optional) The default function to timeout
12645 * @param {Object} scope (optional) The default scope of that timeout
12646 * @param {Array} args (optional) The default Array of arguments
12648 Roo.util.DelayedTask = function(fn, scope, args){
12649 var id = null, d, t;
12651 var call = function(){
12652 var now = new Date().getTime();
12656 fn.apply(scope, args || []);
12660 * Cancels any pending timeout and queues a new one
12661 * @param {Number} delay The milliseconds to delay
12662 * @param {Function} newFn (optional) Overrides function passed to constructor
12663 * @param {Object} newScope (optional) Overrides scope passed to constructor
12664 * @param {Array} newArgs (optional) Overrides args passed to constructor
12666 this.delay = function(delay, newFn, newScope, newArgs){
12667 if(id && delay != d){
12671 t = new Date().getTime();
12673 scope = newScope || scope;
12674 args = newArgs || args;
12676 id = setInterval(call, d);
12681 * Cancel the last queued timeout
12683 this.cancel = function(){
12691 * Ext JS Library 1.1.1
12692 * Copyright(c) 2006-2007, Ext JS, LLC.
12694 * Originally Released Under LGPL - original licence link has changed is not relivant.
12697 * <script type="text/javascript">
12701 Roo.util.TaskRunner = function(interval){
12702 interval = interval || 10;
12703 var tasks = [], removeQueue = [];
12705 var running = false;
12707 var stopThread = function(){
12713 var startThread = function(){
12716 id = setInterval(runTasks, interval);
12720 var removeTask = function(task){
12721 removeQueue.push(task);
12727 var runTasks = function(){
12728 if(removeQueue.length > 0){
12729 for(var i = 0, len = removeQueue.length; i < len; i++){
12730 tasks.remove(removeQueue[i]);
12733 if(tasks.length < 1){
12738 var now = new Date().getTime();
12739 for(var i = 0, len = tasks.length; i < len; ++i){
12741 var itime = now - t.taskRunTime;
12742 if(t.interval <= itime){
12743 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12744 t.taskRunTime = now;
12745 if(rt === false || t.taskRunCount === t.repeat){
12750 if(t.duration && t.duration <= (now - t.taskStartTime)){
12757 * Queues a new task.
12758 * @param {Object} task
12760 this.start = function(task){
12762 task.taskStartTime = new Date().getTime();
12763 task.taskRunTime = 0;
12764 task.taskRunCount = 0;
12769 this.stop = function(task){
12774 this.stopAll = function(){
12776 for(var i = 0, len = tasks.length; i < len; i++){
12777 if(tasks[i].onStop){
12786 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12788 * Ext JS Library 1.1.1
12789 * Copyright(c) 2006-2007, Ext JS, LLC.
12791 * Originally Released Under LGPL - original licence link has changed is not relivant.
12794 * <script type="text/javascript">
12799 * @class Roo.util.MixedCollection
12800 * @extends Roo.util.Observable
12801 * A Collection class that maintains both numeric indexes and keys and exposes events.
12803 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12804 * collection (defaults to false)
12805 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12806 * and return the key value for that item. This is used when available to look up the key on items that
12807 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12808 * equivalent to providing an implementation for the {@link #getKey} method.
12810 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12818 * Fires when the collection is cleared.
12823 * Fires when an item is added to the collection.
12824 * @param {Number} index The index at which the item was added.
12825 * @param {Object} o The item added.
12826 * @param {String} key The key associated with the added item.
12831 * Fires when an item is replaced in the collection.
12832 * @param {String} key he key associated with the new added.
12833 * @param {Object} old The item being replaced.
12834 * @param {Object} new The new item.
12839 * Fires when an item is removed from the collection.
12840 * @param {Object} o The item being removed.
12841 * @param {String} key (optional) The key associated with the removed item.
12846 this.allowFunctions = allowFunctions === true;
12848 this.getKey = keyFn;
12850 Roo.util.MixedCollection.superclass.constructor.call(this);
12853 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12854 allowFunctions : false,
12857 * Adds an item to the collection.
12858 * @param {String} key The key to associate with the item
12859 * @param {Object} o The item to add.
12860 * @return {Object} The item added.
12862 add : function(key, o){
12863 if(arguments.length == 1){
12865 key = this.getKey(o);
12867 if(typeof key == "undefined" || key === null){
12869 this.items.push(o);
12870 this.keys.push(null);
12872 var old = this.map[key];
12874 return this.replace(key, o);
12877 this.items.push(o);
12879 this.keys.push(key);
12881 this.fireEvent("add", this.length-1, o, key);
12886 * MixedCollection has a generic way to fetch keys if you implement getKey.
12889 var mc = new Roo.util.MixedCollection();
12890 mc.add(someEl.dom.id, someEl);
12891 mc.add(otherEl.dom.id, otherEl);
12895 var mc = new Roo.util.MixedCollection();
12896 mc.getKey = function(el){
12902 // or via the constructor
12903 var mc = new Roo.util.MixedCollection(false, function(el){
12909 * @param o {Object} The item for which to find the key.
12910 * @return {Object} The key for the passed item.
12912 getKey : function(o){
12917 * Replaces an item in the collection.
12918 * @param {String} key The key associated with the item to replace, or the item to replace.
12919 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12920 * @return {Object} The new item.
12922 replace : function(key, o){
12923 if(arguments.length == 1){
12925 key = this.getKey(o);
12927 var old = this.item(key);
12928 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12929 return this.add(key, o);
12931 var index = this.indexOfKey(key);
12932 this.items[index] = o;
12934 this.fireEvent("replace", key, old, o);
12939 * Adds all elements of an Array or an Object to the collection.
12940 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12941 * an Array of values, each of which are added to the collection.
12943 addAll : function(objs){
12944 if(arguments.length > 1 || objs instanceof Array){
12945 var args = arguments.length > 1 ? arguments : objs;
12946 for(var i = 0, len = args.length; i < len; i++){
12950 for(var key in objs){
12951 if(this.allowFunctions || typeof objs[key] != "function"){
12952 this.add(key, objs[key]);
12959 * Executes the specified function once for every item in the collection, passing each
12960 * item as the first and only parameter. returning false from the function will stop the iteration.
12961 * @param {Function} fn The function to execute for each item.
12962 * @param {Object} scope (optional) The scope in which to execute the function.
12964 each : function(fn, scope){
12965 var items = [].concat(this.items); // each safe for removal
12966 for(var i = 0, len = items.length; i < len; i++){
12967 if(fn.call(scope || items[i], items[i], i, len) === false){
12974 * Executes the specified function once for every key in the collection, passing each
12975 * key, and its associated item as the first two parameters.
12976 * @param {Function} fn The function to execute for each item.
12977 * @param {Object} scope (optional) The scope in which to execute the function.
12979 eachKey : function(fn, scope){
12980 for(var i = 0, len = this.keys.length; i < len; i++){
12981 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12986 * Returns the first item in the collection which elicits a true return value from the
12987 * passed selection function.
12988 * @param {Function} fn The selection function to execute for each item.
12989 * @param {Object} scope (optional) The scope in which to execute the function.
12990 * @return {Object} The first item in the collection which returned true from the selection function.
12992 find : function(fn, scope){
12993 for(var i = 0, len = this.items.length; i < len; i++){
12994 if(fn.call(scope || window, this.items[i], this.keys[i])){
12995 return this.items[i];
13002 * Inserts an item at the specified index in the collection.
13003 * @param {Number} index The index to insert the item at.
13004 * @param {String} key The key to associate with the new item, or the item itself.
13005 * @param {Object} o (optional) If the second parameter was a key, the new item.
13006 * @return {Object} The item inserted.
13008 insert : function(index, key, o){
13009 if(arguments.length == 2){
13011 key = this.getKey(o);
13013 if(index >= this.length){
13014 return this.add(key, o);
13017 this.items.splice(index, 0, o);
13018 if(typeof key != "undefined" && key != null){
13021 this.keys.splice(index, 0, key);
13022 this.fireEvent("add", index, o, key);
13027 * Removed an item from the collection.
13028 * @param {Object} o The item to remove.
13029 * @return {Object} The item removed.
13031 remove : function(o){
13032 return this.removeAt(this.indexOf(o));
13036 * Remove an item from a specified index in the collection.
13037 * @param {Number} index The index within the collection of the item to remove.
13039 removeAt : function(index){
13040 if(index < this.length && index >= 0){
13042 var o = this.items[index];
13043 this.items.splice(index, 1);
13044 var key = this.keys[index];
13045 if(typeof key != "undefined"){
13046 delete this.map[key];
13048 this.keys.splice(index, 1);
13049 this.fireEvent("remove", o, key);
13054 * Removed an item associated with the passed key fom the collection.
13055 * @param {String} key The key of the item to remove.
13057 removeKey : function(key){
13058 return this.removeAt(this.indexOfKey(key));
13062 * Returns the number of items in the collection.
13063 * @return {Number} the number of items in the collection.
13065 getCount : function(){
13066 return this.length;
13070 * Returns index within the collection of the passed Object.
13071 * @param {Object} o The item to find the index of.
13072 * @return {Number} index of the item.
13074 indexOf : function(o){
13075 if(!this.items.indexOf){
13076 for(var i = 0, len = this.items.length; i < len; i++){
13077 if(this.items[i] == o) return i;
13081 return this.items.indexOf(o);
13086 * Returns index within the collection of the passed key.
13087 * @param {String} key The key to find the index of.
13088 * @return {Number} index of the key.
13090 indexOfKey : function(key){
13091 if(!this.keys.indexOf){
13092 for(var i = 0, len = this.keys.length; i < len; i++){
13093 if(this.keys[i] == key) return i;
13097 return this.keys.indexOf(key);
13102 * Returns the item associated with the passed key OR index. Key has priority over index.
13103 * @param {String/Number} key The key or index of the item.
13104 * @return {Object} The item associated with the passed key.
13106 item : function(key){
13107 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
13108 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
13112 * Returns the item at the specified index.
13113 * @param {Number} index The index of the item.
13116 itemAt : function(index){
13117 return this.items[index];
13121 * Returns the item associated with the passed key.
13122 * @param {String/Number} key The key of the item.
13123 * @return {Object} The item associated with the passed key.
13125 key : function(key){
13126 return this.map[key];
13130 * Returns true if the collection contains the passed Object as an item.
13131 * @param {Object} o The Object to look for in the collection.
13132 * @return {Boolean} True if the collection contains the Object as an item.
13134 contains : function(o){
13135 return this.indexOf(o) != -1;
13139 * Returns true if the collection contains the passed Object as a key.
13140 * @param {String} key The key to look for in the collection.
13141 * @return {Boolean} True if the collection contains the Object as a key.
13143 containsKey : function(key){
13144 return typeof this.map[key] != "undefined";
13148 * Removes all items from the collection.
13150 clear : function(){
13155 this.fireEvent("clear");
13159 * Returns the first item in the collection.
13160 * @return {Object} the first item in the collection..
13162 first : function(){
13163 return this.items[0];
13167 * Returns the last item in the collection.
13168 * @return {Object} the last item in the collection..
13171 return this.items[this.length-1];
13174 _sort : function(property, dir, fn){
13175 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
13176 fn = fn || function(a, b){
13179 var c = [], k = this.keys, items = this.items;
13180 for(var i = 0, len = items.length; i < len; i++){
13181 c[c.length] = {key: k[i], value: items[i], index: i};
13183 c.sort(function(a, b){
13184 var v = fn(a[property], b[property]) * dsc;
13186 v = (a.index < b.index ? -1 : 1);
13190 for(var i = 0, len = c.length; i < len; i++){
13191 items[i] = c[i].value;
13194 this.fireEvent("sort", this);
13198 * Sorts this collection with the passed comparison function
13199 * @param {String} direction (optional) "ASC" or "DESC"
13200 * @param {Function} fn (optional) comparison function
13202 sort : function(dir, fn){
13203 this._sort("value", dir, fn);
13207 * Sorts this collection by keys
13208 * @param {String} direction (optional) "ASC" or "DESC"
13209 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
13211 keySort : function(dir, fn){
13212 this._sort("key", dir, fn || function(a, b){
13213 return String(a).toUpperCase()-String(b).toUpperCase();
13218 * Returns a range of items in this collection
13219 * @param {Number} startIndex (optional) defaults to 0
13220 * @param {Number} endIndex (optional) default to the last item
13221 * @return {Array} An array of items
13223 getRange : function(start, end){
13224 var items = this.items;
13225 if(items.length < 1){
13228 start = start || 0;
13229 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
13232 for(var i = start; i <= end; i++) {
13233 r[r.length] = items[i];
13236 for(var i = start; i >= end; i--) {
13237 r[r.length] = items[i];
13244 * Filter the <i>objects</i> in this collection by a specific property.
13245 * Returns a new collection that has been filtered.
13246 * @param {String} property A property on your objects
13247 * @param {String/RegExp} value Either string that the property values
13248 * should start with or a RegExp to test against the property
13249 * @return {MixedCollection} The new filtered collection
13251 filter : function(property, value){
13252 if(!value.exec){ // not a regex
13253 value = String(value);
13254 if(value.length == 0){
13255 return this.clone();
13257 value = new RegExp("^" + Roo.escapeRe(value), "i");
13259 return this.filterBy(function(o){
13260 return o && value.test(o[property]);
13265 * Filter by a function. * Returns a new collection that has been filtered.
13266 * The passed function will be called with each
13267 * object in the collection. If the function returns true, the value is included
13268 * otherwise it is filtered.
13269 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
13270 * @param {Object} scope (optional) The scope of the function (defaults to this)
13271 * @return {MixedCollection} The new filtered collection
13273 filterBy : function(fn, scope){
13274 var r = new Roo.util.MixedCollection();
13275 r.getKey = this.getKey;
13276 var k = this.keys, it = this.items;
13277 for(var i = 0, len = it.length; i < len; i++){
13278 if(fn.call(scope||this, it[i], k[i])){
13279 r.add(k[i], it[i]);
13286 * Creates a duplicate of this collection
13287 * @return {MixedCollection}
13289 clone : function(){
13290 var r = new Roo.util.MixedCollection();
13291 var k = this.keys, it = this.items;
13292 for(var i = 0, len = it.length; i < len; i++){
13293 r.add(k[i], it[i]);
13295 r.getKey = this.getKey;
13300 * Returns the item associated with the passed key or index.
13302 * @param {String/Number} key The key or index of the item.
13303 * @return {Object} The item associated with the passed key.
13305 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
13307 * Ext JS Library 1.1.1
13308 * Copyright(c) 2006-2007, Ext JS, LLC.
13310 * Originally Released Under LGPL - original licence link has changed is not relivant.
13313 * <script type="text/javascript">
13316 * @class Roo.util.JSON
13317 * Modified version of Douglas Crockford"s json.js that doesn"t
13318 * mess with the Object prototype
13319 * http://www.json.org/js.html
13322 Roo.util.JSON = new (function(){
13323 var useHasOwn = {}.hasOwnProperty ? true : false;
13325 // crashes Safari in some instances
13326 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
13328 var pad = function(n) {
13329 return n < 10 ? "0" + n : n;
13342 var encodeString = function(s){
13343 if (/["\\\x00-\x1f]/.test(s)) {
13344 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
13349 c = b.charCodeAt();
13351 Math.floor(c / 16).toString(16) +
13352 (c % 16).toString(16);
13355 return '"' + s + '"';
13358 var encodeArray = function(o){
13359 var a = ["["], b, i, l = o.length, v;
13360 for (i = 0; i < l; i += 1) {
13362 switch (typeof v) {
13371 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
13379 var encodeDate = function(o){
13380 return '"' + o.getFullYear() + "-" +
13381 pad(o.getMonth() + 1) + "-" +
13382 pad(o.getDate()) + "T" +
13383 pad(o.getHours()) + ":" +
13384 pad(o.getMinutes()) + ":" +
13385 pad(o.getSeconds()) + '"';
13389 * Encodes an Object, Array or other value
13390 * @param {Mixed} o The variable to encode
13391 * @return {String} The JSON string
13393 this.encode = function(o)
13395 // should this be extended to fully wrap stringify..
13397 if(typeof o == "undefined" || o === null){
13399 }else if(o instanceof Array){
13400 return encodeArray(o);
13401 }else if(o instanceof Date){
13402 return encodeDate(o);
13403 }else if(typeof o == "string"){
13404 return encodeString(o);
13405 }else if(typeof o == "number"){
13406 return isFinite(o) ? String(o) : "null";
13407 }else if(typeof o == "boolean"){
13410 var a = ["{"], b, i, v;
13412 if(!useHasOwn || o.hasOwnProperty(i)) {
13414 switch (typeof v) {
13423 a.push(this.encode(i), ":",
13424 v === null ? "null" : this.encode(v));
13435 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
13436 * @param {String} json The JSON string
13437 * @return {Object} The resulting object
13439 this.decode = function(json){
13441 return /** eval:var:json */ eval("(" + json + ')');
13445 * Shorthand for {@link Roo.util.JSON#encode}
13446 * @member Roo encode
13448 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
13450 * Shorthand for {@link Roo.util.JSON#decode}
13451 * @member Roo decode
13453 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
13456 * Ext JS Library 1.1.1
13457 * Copyright(c) 2006-2007, Ext JS, LLC.
13459 * Originally Released Under LGPL - original licence link has changed is not relivant.
13462 * <script type="text/javascript">
13466 * @class Roo.util.Format
13467 * Reusable data formatting functions
13470 Roo.util.Format = function(){
13471 var trimRe = /^\s+|\s+$/g;
13474 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
13475 * @param {String} value The string to truncate
13476 * @param {Number} length The maximum length to allow before truncating
13477 * @return {String} The converted text
13479 ellipsis : function(value, len){
13480 if(value && value.length > len){
13481 return value.substr(0, len-3)+"...";
13487 * Checks a reference and converts it to empty string if it is undefined
13488 * @param {Mixed} value Reference to check
13489 * @return {Mixed} Empty string if converted, otherwise the original value
13491 undef : function(value){
13492 return typeof value != "undefined" ? value : "";
13496 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
13497 * @param {String} value The string to encode
13498 * @return {String} The encoded text
13500 htmlEncode : function(value){
13501 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
13505 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
13506 * @param {String} value The string to decode
13507 * @return {String} The decoded text
13509 htmlDecode : function(value){
13510 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
13514 * Trims any whitespace from either side of a string
13515 * @param {String} value The text to trim
13516 * @return {String} The trimmed text
13518 trim : function(value){
13519 return String(value).replace(trimRe, "");
13523 * Returns a substring from within an original string
13524 * @param {String} value The original text
13525 * @param {Number} start The start index of the substring
13526 * @param {Number} length The length of the substring
13527 * @return {String} The substring
13529 substr : function(value, start, length){
13530 return String(value).substr(start, length);
13534 * Converts a string to all lower case letters
13535 * @param {String} value The text to convert
13536 * @return {String} The converted text
13538 lowercase : function(value){
13539 return String(value).toLowerCase();
13543 * Converts a string to all upper case letters
13544 * @param {String} value The text to convert
13545 * @return {String} The converted text
13547 uppercase : function(value){
13548 return String(value).toUpperCase();
13552 * Converts the first character only of a string to upper case
13553 * @param {String} value The text to convert
13554 * @return {String} The converted text
13556 capitalize : function(value){
13557 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13561 call : function(value, fn){
13562 if(arguments.length > 2){
13563 var args = Array.prototype.slice.call(arguments, 2);
13564 args.unshift(value);
13566 return /** eval:var:value */ eval(fn).apply(window, args);
13568 /** eval:var:value */
13569 return /** eval:var:value */ eval(fn).call(window, value);
13575 * safer version of Math.toFixed..??/
13576 * @param {Number/String} value The numeric value to format
13577 * @param {Number/String} value Decimal places
13578 * @return {String} The formatted currency string
13580 toFixed : function(v, n)
13582 // why not use to fixed - precision is buggered???
13584 return Math.round(v-0);
13586 var fact = Math.pow(10,n+1);
13587 v = (Math.round((v-0)*fact))/fact;
13588 var z = (''+fact).substring(2);
13589 if (v == Math.floor(v)) {
13590 return Math.floor(v) + '.' + z;
13593 // now just padd decimals..
13594 var ps = String(v).split('.');
13595 var fd = (ps[1] + z);
13596 var r = fd.substring(0,n);
13597 var rm = fd.substring(n);
13599 return ps[0] + '.' + r;
13601 r*=1; // turn it into a number;
13603 if (String(r).length != n) {
13606 r = String(r).substring(1); // chop the end off.
13609 return ps[0] + '.' + r;
13614 * Format a number as US currency
13615 * @param {Number/String} value The numeric value to format
13616 * @return {String} The formatted currency string
13618 usMoney : function(v){
13619 return '$' + Roo.util.Format.number(v);
13624 * eventually this should probably emulate php's number_format
13625 * @param {Number/String} value The numeric value to format
13626 * @param {Number} decimals number of decimal places
13627 * @return {String} The formatted currency string
13629 number : function(v,decimals)
13631 // multiply and round.
13632 decimals = typeof(decimals) == 'undefined' ? 2 : decimals;
13633 var mul = Math.pow(10, decimals);
13634 var zero = String(mul).substring(1);
13635 v = (Math.round((v-0)*mul))/mul;
13637 // if it's '0' number.. then
13639 //v = (v == Math.floor(v)) ? v + "." + zero : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13641 var ps = v.split('.');
13645 var r = /(\d+)(\d{3})/;
13647 while (r.test(whole)) {
13648 whole = whole.replace(r, '$1' + ',' + '$2');
13654 (decimals ? ('.'+ ps[1] + zero.substring(ps[1].length)) : '') :
13655 // does not have decimals
13656 (decimals ? ('.' + zero) : '');
13659 return whole + sub ;
13663 * Parse a value into a formatted date using the specified format pattern.
13664 * @param {Mixed} value The value to format
13665 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13666 * @return {String} The formatted date string
13668 date : function(v, format){
13672 if(!(v instanceof Date)){
13673 v = new Date(Date.parse(v));
13675 return v.dateFormat(format || Roo.util.Format.defaults.date);
13679 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13680 * @param {String} format Any valid date format string
13681 * @return {Function} The date formatting function
13683 dateRenderer : function(format){
13684 return function(v){
13685 return Roo.util.Format.date(v, format);
13690 stripTagsRE : /<\/?[^>]+>/gi,
13693 * Strips all HTML tags
13694 * @param {Mixed} value The text from which to strip tags
13695 * @return {String} The stripped text
13697 stripTags : function(v){
13698 return !v ? v : String(v).replace(this.stripTagsRE, "");
13702 Roo.util.Format.defaults = {
13706 * Ext JS Library 1.1.1
13707 * Copyright(c) 2006-2007, Ext JS, LLC.
13709 * Originally Released Under LGPL - original licence link has changed is not relivant.
13712 * <script type="text/javascript">
13719 * @class Roo.MasterTemplate
13720 * @extends Roo.Template
13721 * Provides a template that can have child templates. The syntax is:
13723 var t = new Roo.MasterTemplate(
13724 '<select name="{name}">',
13725 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13728 t.add('options', {value: 'foo', text: 'bar'});
13729 // or you can add multiple child elements in one shot
13730 t.addAll('options', [
13731 {value: 'foo', text: 'bar'},
13732 {value: 'foo2', text: 'bar2'},
13733 {value: 'foo3', text: 'bar3'}
13735 // then append, applying the master template values
13736 t.append('my-form', {name: 'my-select'});
13738 * A name attribute for the child template is not required if you have only one child
13739 * template or you want to refer to them by index.
13741 Roo.MasterTemplate = function(){
13742 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13743 this.originalHtml = this.html;
13745 var m, re = this.subTemplateRe;
13748 while(m = re.exec(this.html)){
13749 var name = m[1], content = m[2];
13754 tpl : new Roo.Template(content)
13757 st[name] = st[subIndex];
13759 st[subIndex].tpl.compile();
13760 st[subIndex].tpl.call = this.call.createDelegate(this);
13763 this.subCount = subIndex;
13766 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13768 * The regular expression used to match sub templates
13772 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13775 * Applies the passed values to a child template.
13776 * @param {String/Number} name (optional) The name or index of the child template
13777 * @param {Array/Object} values The values to be applied to the template
13778 * @return {MasterTemplate} this
13780 add : function(name, values){
13781 if(arguments.length == 1){
13782 values = arguments[0];
13785 var s = this.subs[name];
13786 s.buffer[s.buffer.length] = s.tpl.apply(values);
13791 * Applies all the passed values to a child template.
13792 * @param {String/Number} name (optional) The name or index of the child template
13793 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13794 * @param {Boolean} reset (optional) True to reset the template first
13795 * @return {MasterTemplate} this
13797 fill : function(name, values, reset){
13799 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13807 for(var i = 0, len = values.length; i < len; i++){
13808 this.add(name, values[i]);
13814 * Resets the template for reuse
13815 * @return {MasterTemplate} this
13817 reset : function(){
13819 for(var i = 0; i < this.subCount; i++){
13825 applyTemplate : function(values){
13827 var replaceIndex = -1;
13828 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13829 return s[++replaceIndex].buffer.join("");
13831 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13834 apply : function(){
13835 return this.applyTemplate.apply(this, arguments);
13838 compile : function(){return this;}
13842 * Alias for fill().
13845 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13847 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13848 * var tpl = Roo.MasterTemplate.from('element-id');
13849 * @param {String/HTMLElement} el
13850 * @param {Object} config
13853 Roo.MasterTemplate.from = function(el, config){
13854 el = Roo.getDom(el);
13855 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13858 * Ext JS Library 1.1.1
13859 * Copyright(c) 2006-2007, Ext JS, LLC.
13861 * Originally Released Under LGPL - original licence link has changed is not relivant.
13864 * <script type="text/javascript">
13869 * @class Roo.util.CSS
13870 * Utility class for manipulating CSS rules
13873 Roo.util.CSS = function(){
13875 var doc = document;
13877 var camelRe = /(-[a-z])/gi;
13878 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13882 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13883 * tag and appended to the HEAD of the document.
13884 * @param {String|Object} cssText The text containing the css rules
13885 * @param {String} id An id to add to the stylesheet for later removal
13886 * @return {StyleSheet}
13888 createStyleSheet : function(cssText, id){
13890 var head = doc.getElementsByTagName("head")[0];
13891 var nrules = doc.createElement("style");
13892 nrules.setAttribute("type", "text/css");
13894 nrules.setAttribute("id", id);
13896 if (typeof(cssText) != 'string') {
13897 // support object maps..
13898 // not sure if this a good idea..
13899 // perhaps it should be merged with the general css handling
13900 // and handle js style props.
13901 var cssTextNew = [];
13902 for(var n in cssText) {
13904 for(var k in cssText[n]) {
13905 citems.push( k + ' : ' +cssText[n][k] + ';' );
13907 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13910 cssText = cssTextNew.join("\n");
13916 head.appendChild(nrules);
13917 ss = nrules.styleSheet;
13918 ss.cssText = cssText;
13921 nrules.appendChild(doc.createTextNode(cssText));
13923 nrules.cssText = cssText;
13925 head.appendChild(nrules);
13926 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13928 this.cacheStyleSheet(ss);
13933 * Removes a style or link tag by id
13934 * @param {String} id The id of the tag
13936 removeStyleSheet : function(id){
13937 var existing = doc.getElementById(id);
13939 existing.parentNode.removeChild(existing);
13944 * Dynamically swaps an existing stylesheet reference for a new one
13945 * @param {String} id The id of an existing link tag to remove
13946 * @param {String} url The href of the new stylesheet to include
13948 swapStyleSheet : function(id, url){
13949 this.removeStyleSheet(id);
13950 var ss = doc.createElement("link");
13951 ss.setAttribute("rel", "stylesheet");
13952 ss.setAttribute("type", "text/css");
13953 ss.setAttribute("id", id);
13954 ss.setAttribute("href", url);
13955 doc.getElementsByTagName("head")[0].appendChild(ss);
13959 * Refresh the rule cache if you have dynamically added stylesheets
13960 * @return {Object} An object (hash) of rules indexed by selector
13962 refreshCache : function(){
13963 return this.getRules(true);
13967 cacheStyleSheet : function(stylesheet){
13971 try{// try catch for cross domain access issue
13972 var ssRules = stylesheet.cssRules || stylesheet.rules;
13973 for(var j = ssRules.length-1; j >= 0; --j){
13974 rules[ssRules[j].selectorText] = ssRules[j];
13980 * Gets all css rules for the document
13981 * @param {Boolean} refreshCache true to refresh the internal cache
13982 * @return {Object} An object (hash) of rules indexed by selector
13984 getRules : function(refreshCache){
13985 if(rules == null || refreshCache){
13987 var ds = doc.styleSheets;
13988 for(var i =0, len = ds.length; i < len; i++){
13990 this.cacheStyleSheet(ds[i]);
13998 * Gets an an individual CSS rule by selector(s)
13999 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
14000 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
14001 * @return {CSSRule} The CSS rule or null if one is not found
14003 getRule : function(selector, refreshCache){
14004 var rs = this.getRules(refreshCache);
14005 if(!(selector instanceof Array)){
14006 return rs[selector];
14008 for(var i = 0; i < selector.length; i++){
14009 if(rs[selector[i]]){
14010 return rs[selector[i]];
14018 * Updates a rule property
14019 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
14020 * @param {String} property The css property
14021 * @param {String} value The new value for the property
14022 * @return {Boolean} true If a rule was found and updated
14024 updateRule : function(selector, property, value){
14025 if(!(selector instanceof Array)){
14026 var rule = this.getRule(selector);
14028 rule.style[property.replace(camelRe, camelFn)] = value;
14032 for(var i = 0; i < selector.length; i++){
14033 if(this.updateRule(selector[i], property, value)){
14043 * Ext JS Library 1.1.1
14044 * Copyright(c) 2006-2007, Ext JS, LLC.
14046 * Originally Released Under LGPL - original licence link has changed is not relivant.
14049 * <script type="text/javascript">
14055 * @class Roo.util.ClickRepeater
14056 * @extends Roo.util.Observable
14058 * A wrapper class which can be applied to any element. Fires a "click" event while the
14059 * mouse is pressed. The interval between firings may be specified in the config but
14060 * defaults to 10 milliseconds.
14062 * Optionally, a CSS class may be applied to the element during the time it is pressed.
14064 * @cfg {String/HTMLElement/Element} el The element to act as a button.
14065 * @cfg {Number} delay The initial delay before the repeating event begins firing.
14066 * Similar to an autorepeat key delay.
14067 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
14068 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
14069 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
14070 * "interval" and "delay" are ignored. "immediate" is honored.
14071 * @cfg {Boolean} preventDefault True to prevent the default click event
14072 * @cfg {Boolean} stopDefault True to stop the default click event
14075 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
14076 * 2007-02-02 jvs Renamed to ClickRepeater
14077 * 2007-02-03 jvs Modifications for FF Mac and Safari
14080 * @param {String/HTMLElement/Element} el The element to listen on
14081 * @param {Object} config
14083 Roo.util.ClickRepeater = function(el, config)
14085 this.el = Roo.get(el);
14086 this.el.unselectable();
14088 Roo.apply(this, config);
14093 * Fires when the mouse button is depressed.
14094 * @param {Roo.util.ClickRepeater} this
14096 "mousedown" : true,
14099 * Fires on a specified interval during the time the element is pressed.
14100 * @param {Roo.util.ClickRepeater} this
14105 * Fires when the mouse key is released.
14106 * @param {Roo.util.ClickRepeater} this
14111 this.el.on("mousedown", this.handleMouseDown, this);
14112 if(this.preventDefault || this.stopDefault){
14113 this.el.on("click", function(e){
14114 if(this.preventDefault){
14115 e.preventDefault();
14117 if(this.stopDefault){
14123 // allow inline handler
14125 this.on("click", this.handler, this.scope || this);
14128 Roo.util.ClickRepeater.superclass.constructor.call(this);
14131 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
14134 preventDefault : true,
14135 stopDefault : false,
14139 handleMouseDown : function(){
14140 clearTimeout(this.timer);
14142 if(this.pressClass){
14143 this.el.addClass(this.pressClass);
14145 this.mousedownTime = new Date();
14147 Roo.get(document).on("mouseup", this.handleMouseUp, this);
14148 this.el.on("mouseout", this.handleMouseOut, this);
14150 this.fireEvent("mousedown", this);
14151 this.fireEvent("click", this);
14153 this.timer = this.click.defer(this.delay || this.interval, this);
14157 click : function(){
14158 this.fireEvent("click", this);
14159 this.timer = this.click.defer(this.getInterval(), this);
14163 getInterval: function(){
14164 if(!this.accelerate){
14165 return this.interval;
14167 var pressTime = this.mousedownTime.getElapsed();
14168 if(pressTime < 500){
14170 }else if(pressTime < 1700){
14172 }else if(pressTime < 2600){
14174 }else if(pressTime < 3500){
14176 }else if(pressTime < 4400){
14178 }else if(pressTime < 5300){
14180 }else if(pressTime < 6200){
14188 handleMouseOut : function(){
14189 clearTimeout(this.timer);
14190 if(this.pressClass){
14191 this.el.removeClass(this.pressClass);
14193 this.el.on("mouseover", this.handleMouseReturn, this);
14197 handleMouseReturn : function(){
14198 this.el.un("mouseover", this.handleMouseReturn);
14199 if(this.pressClass){
14200 this.el.addClass(this.pressClass);
14206 handleMouseUp : function(){
14207 clearTimeout(this.timer);
14208 this.el.un("mouseover", this.handleMouseReturn);
14209 this.el.un("mouseout", this.handleMouseOut);
14210 Roo.get(document).un("mouseup", this.handleMouseUp);
14211 this.el.removeClass(this.pressClass);
14212 this.fireEvent("mouseup", this);
14216 * Ext JS Library 1.1.1
14217 * Copyright(c) 2006-2007, Ext JS, LLC.
14219 * Originally Released Under LGPL - original licence link has changed is not relivant.
14222 * <script type="text/javascript">
14227 * @class Roo.KeyNav
14228 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
14229 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
14230 * way to implement custom navigation schemes for any UI component.</p>
14231 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
14232 * pageUp, pageDown, del, home, end. Usage:</p>
14234 var nav = new Roo.KeyNav("my-element", {
14235 "left" : function(e){
14236 this.moveLeft(e.ctrlKey);
14238 "right" : function(e){
14239 this.moveRight(e.ctrlKey);
14241 "enter" : function(e){
14248 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14249 * @param {Object} config The config
14251 Roo.KeyNav = function(el, config){
14252 this.el = Roo.get(el);
14253 Roo.apply(this, config);
14254 if(!this.disabled){
14255 this.disabled = true;
14260 Roo.KeyNav.prototype = {
14262 * @cfg {Boolean} disabled
14263 * True to disable this KeyNav instance (defaults to false)
14267 * @cfg {String} defaultEventAction
14268 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
14269 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
14270 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
14272 defaultEventAction: "stopEvent",
14274 * @cfg {Boolean} forceKeyDown
14275 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
14276 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
14277 * handle keydown instead of keypress.
14279 forceKeyDown : false,
14282 prepareEvent : function(e){
14283 var k = e.getKey();
14284 var h = this.keyToHandler[k];
14285 //if(h && this[h]){
14286 // e.stopPropagation();
14288 if(Roo.isSafari && h && k >= 37 && k <= 40){
14294 relay : function(e){
14295 var k = e.getKey();
14296 var h = this.keyToHandler[k];
14298 if(this.doRelay(e, this[h], h) !== true){
14299 e[this.defaultEventAction]();
14305 doRelay : function(e, h, hname){
14306 return h.call(this.scope || this, e);
14309 // possible handlers
14323 // quick lookup hash
14340 * Enable this KeyNav
14342 enable: function(){
14344 // ie won't do special keys on keypress, no one else will repeat keys with keydown
14345 // the EventObject will normalize Safari automatically
14346 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14347 this.el.on("keydown", this.relay, this);
14349 this.el.on("keydown", this.prepareEvent, this);
14350 this.el.on("keypress", this.relay, this);
14352 this.disabled = false;
14357 * Disable this KeyNav
14359 disable: function(){
14360 if(!this.disabled){
14361 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
14362 this.el.un("keydown", this.relay);
14364 this.el.un("keydown", this.prepareEvent);
14365 this.el.un("keypress", this.relay);
14367 this.disabled = true;
14372 * Ext JS Library 1.1.1
14373 * Copyright(c) 2006-2007, Ext JS, LLC.
14375 * Originally Released Under LGPL - original licence link has changed is not relivant.
14378 * <script type="text/javascript">
14383 * @class Roo.KeyMap
14384 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
14385 * The constructor accepts the same config object as defined by {@link #addBinding}.
14386 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
14387 * combination it will call the function with this signature (if the match is a multi-key
14388 * combination the callback will still be called only once): (String key, Roo.EventObject e)
14389 * A KeyMap can also handle a string representation of keys.<br />
14392 // map one key by key code
14393 var map = new Roo.KeyMap("my-element", {
14394 key: 13, // or Roo.EventObject.ENTER
14399 // map multiple keys to one action by string
14400 var map = new Roo.KeyMap("my-element", {
14406 // map multiple keys to multiple actions by strings and array of codes
14407 var map = new Roo.KeyMap("my-element", [
14410 fn: function(){ alert("Return was pressed"); }
14413 fn: function(){ alert('a, b or c was pressed'); }
14418 fn: function(){ alert('Control + shift + tab was pressed.'); }
14422 * <b>Note: A KeyMap starts enabled</b>
14424 * @param {String/HTMLElement/Roo.Element} el The element to bind to
14425 * @param {Object} config The config (see {@link #addBinding})
14426 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
14428 Roo.KeyMap = function(el, config, eventName){
14429 this.el = Roo.get(el);
14430 this.eventName = eventName || "keydown";
14431 this.bindings = [];
14433 this.addBinding(config);
14438 Roo.KeyMap.prototype = {
14440 * True to stop the event from bubbling and prevent the default browser action if the
14441 * key was handled by the KeyMap (defaults to false)
14447 * Add a new binding to this KeyMap. The following config object properties are supported:
14449 Property Type Description
14450 ---------- --------------- ----------------------------------------------------------------------
14451 key String/Array A single keycode or an array of keycodes to handle
14452 shift Boolean True to handle key only when shift is pressed (defaults to false)
14453 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
14454 alt Boolean True to handle key only when alt is pressed (defaults to false)
14455 fn Function The function to call when KeyMap finds the expected key combination
14456 scope Object The scope of the callback function
14462 var map = new Roo.KeyMap(document, {
14463 key: Roo.EventObject.ENTER,
14468 //Add a new binding to the existing KeyMap later
14476 * @param {Object/Array} config A single KeyMap config or an array of configs
14478 addBinding : function(config){
14479 if(config instanceof Array){
14480 for(var i = 0, len = config.length; i < len; i++){
14481 this.addBinding(config[i]);
14485 var keyCode = config.key,
14486 shift = config.shift,
14487 ctrl = config.ctrl,
14490 scope = config.scope;
14491 if(typeof keyCode == "string"){
14493 var keyString = keyCode.toUpperCase();
14494 for(var j = 0, len = keyString.length; j < len; j++){
14495 ks.push(keyString.charCodeAt(j));
14499 var keyArray = keyCode instanceof Array;
14500 var handler = function(e){
14501 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
14502 var k = e.getKey();
14504 for(var i = 0, len = keyCode.length; i < len; i++){
14505 if(keyCode[i] == k){
14506 if(this.stopEvent){
14509 fn.call(scope || window, k, e);
14515 if(this.stopEvent){
14518 fn.call(scope || window, k, e);
14523 this.bindings.push(handler);
14527 * Shorthand for adding a single key listener
14528 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
14529 * following options:
14530 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
14531 * @param {Function} fn The function to call
14532 * @param {Object} scope (optional) The scope of the function
14534 on : function(key, fn, scope){
14535 var keyCode, shift, ctrl, alt;
14536 if(typeof key == "object" && !(key instanceof Array)){
14555 handleKeyDown : function(e){
14556 if(this.enabled){ //just in case
14557 var b = this.bindings;
14558 for(var i = 0, len = b.length; i < len; i++){
14559 b[i].call(this, e);
14565 * Returns true if this KeyMap is enabled
14566 * @return {Boolean}
14568 isEnabled : function(){
14569 return this.enabled;
14573 * Enables this KeyMap
14575 enable: function(){
14577 this.el.on(this.eventName, this.handleKeyDown, this);
14578 this.enabled = true;
14583 * Disable this KeyMap
14585 disable: function(){
14587 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14588 this.enabled = false;
14593 * Ext JS Library 1.1.1
14594 * Copyright(c) 2006-2007, Ext JS, LLC.
14596 * Originally Released Under LGPL - original licence link has changed is not relivant.
14599 * <script type="text/javascript">
14604 * @class Roo.util.TextMetrics
14605 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14606 * wide, in pixels, a given block of text will be.
14609 Roo.util.TextMetrics = function(){
14613 * Measures the size of the specified text
14614 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14615 * that can affect the size of the rendered text
14616 * @param {String} text The text to measure
14617 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14618 * in order to accurately measure the text height
14619 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14621 measure : function(el, text, fixedWidth){
14623 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14626 shared.setFixedWidth(fixedWidth || 'auto');
14627 return shared.getSize(text);
14631 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14632 * the overhead of multiple calls to initialize the style properties on each measurement.
14633 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14634 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14635 * in order to accurately measure the text height
14636 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14638 createInstance : function(el, fixedWidth){
14639 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14646 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14647 var ml = new Roo.Element(document.createElement('div'));
14648 document.body.appendChild(ml.dom);
14649 ml.position('absolute');
14650 ml.setLeftTop(-1000, -1000);
14654 ml.setWidth(fixedWidth);
14659 * Returns the size of the specified text based on the internal element's style and width properties
14660 * @memberOf Roo.util.TextMetrics.Instance#
14661 * @param {String} text The text to measure
14662 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14664 getSize : function(text){
14666 var s = ml.getSize();
14672 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14673 * that can affect the size of the rendered text
14674 * @memberOf Roo.util.TextMetrics.Instance#
14675 * @param {String/HTMLElement} el The element, dom node or id
14677 bind : function(el){
14679 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14684 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14685 * to set a fixed width in order to accurately measure the text height.
14686 * @memberOf Roo.util.TextMetrics.Instance#
14687 * @param {Number} width The width to set on the element
14689 setFixedWidth : function(width){
14690 ml.setWidth(width);
14694 * Returns the measured width of the specified text
14695 * @memberOf Roo.util.TextMetrics.Instance#
14696 * @param {String} text The text to measure
14697 * @return {Number} width The width in pixels
14699 getWidth : function(text){
14700 ml.dom.style.width = 'auto';
14701 return this.getSize(text).width;
14705 * Returns the measured height of the specified text. For multiline text, be sure to call
14706 * {@link #setFixedWidth} if necessary.
14707 * @memberOf Roo.util.TextMetrics.Instance#
14708 * @param {String} text The text to measure
14709 * @return {Number} height The height in pixels
14711 getHeight : function(text){
14712 return this.getSize(text).height;
14716 instance.bind(bindTo);
14721 // backwards compat
14722 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14724 * Ext JS Library 1.1.1
14725 * Copyright(c) 2006-2007, Ext JS, LLC.
14727 * Originally Released Under LGPL - original licence link has changed is not relivant.
14730 * <script type="text/javascript">
14734 * @class Roo.state.Provider
14735 * Abstract base class for state provider implementations. This class provides methods
14736 * for encoding and decoding <b>typed</b> variables including dates and defines the
14737 * Provider interface.
14739 Roo.state.Provider = function(){
14741 * @event statechange
14742 * Fires when a state change occurs.
14743 * @param {Provider} this This state provider
14744 * @param {String} key The state key which was changed
14745 * @param {String} value The encoded value for the state
14748 "statechange": true
14751 Roo.state.Provider.superclass.constructor.call(this);
14753 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14755 * Returns the current value for a key
14756 * @param {String} name The key name
14757 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14758 * @return {Mixed} The state data
14760 get : function(name, defaultValue){
14761 return typeof this.state[name] == "undefined" ?
14762 defaultValue : this.state[name];
14766 * Clears a value from the state
14767 * @param {String} name The key name
14769 clear : function(name){
14770 delete this.state[name];
14771 this.fireEvent("statechange", this, name, null);
14775 * Sets the value for a key
14776 * @param {String} name The key name
14777 * @param {Mixed} value The value to set
14779 set : function(name, value){
14780 this.state[name] = value;
14781 this.fireEvent("statechange", this, name, value);
14785 * Decodes a string previously encoded with {@link #encodeValue}.
14786 * @param {String} value The value to decode
14787 * @return {Mixed} The decoded value
14789 decodeValue : function(cookie){
14790 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14791 var matches = re.exec(unescape(cookie));
14792 if(!matches || !matches[1]) return; // non state cookie
14793 var type = matches[1];
14794 var v = matches[2];
14797 return parseFloat(v);
14799 return new Date(Date.parse(v));
14804 var values = v.split("^");
14805 for(var i = 0, len = values.length; i < len; i++){
14806 all.push(this.decodeValue(values[i]));
14811 var values = v.split("^");
14812 for(var i = 0, len = values.length; i < len; i++){
14813 var kv = values[i].split("=");
14814 all[kv[0]] = this.decodeValue(kv[1]);
14823 * Encodes a value including type information. Decode with {@link #decodeValue}.
14824 * @param {Mixed} value The value to encode
14825 * @return {String} The encoded value
14827 encodeValue : function(v){
14829 if(typeof v == "number"){
14831 }else if(typeof v == "boolean"){
14832 enc = "b:" + (v ? "1" : "0");
14833 }else if(v instanceof Date){
14834 enc = "d:" + v.toGMTString();
14835 }else if(v instanceof Array){
14837 for(var i = 0, len = v.length; i < len; i++){
14838 flat += this.encodeValue(v[i]);
14839 if(i != len-1) flat += "^";
14842 }else if(typeof v == "object"){
14845 if(typeof v[key] != "function"){
14846 flat += key + "=" + this.encodeValue(v[key]) + "^";
14849 enc = "o:" + flat.substring(0, flat.length-1);
14853 return escape(enc);
14859 * Ext JS Library 1.1.1
14860 * Copyright(c) 2006-2007, Ext JS, LLC.
14862 * Originally Released Under LGPL - original licence link has changed is not relivant.
14865 * <script type="text/javascript">
14868 * @class Roo.state.Manager
14869 * This is the global state manager. By default all components that are "state aware" check this class
14870 * for state information if you don't pass them a custom state provider. In order for this class
14871 * to be useful, it must be initialized with a provider when your application initializes.
14873 // in your initialization function
14875 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14877 // supposed you have a {@link Roo.BorderLayout}
14878 var layout = new Roo.BorderLayout(...);
14879 layout.restoreState();
14880 // or a {Roo.BasicDialog}
14881 var dialog = new Roo.BasicDialog(...);
14882 dialog.restoreState();
14886 Roo.state.Manager = function(){
14887 var provider = new Roo.state.Provider();
14891 * Configures the default state provider for your application
14892 * @param {Provider} stateProvider The state provider to set
14894 setProvider : function(stateProvider){
14895 provider = stateProvider;
14899 * Returns the current value for a key
14900 * @param {String} name The key name
14901 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14902 * @return {Mixed} The state data
14904 get : function(key, defaultValue){
14905 return provider.get(key, defaultValue);
14909 * Sets the value for a key
14910 * @param {String} name The key name
14911 * @param {Mixed} value The state data
14913 set : function(key, value){
14914 provider.set(key, value);
14918 * Clears a value from the state
14919 * @param {String} name The key name
14921 clear : function(key){
14922 provider.clear(key);
14926 * Gets the currently configured state provider
14927 * @return {Provider} The state provider
14929 getProvider : function(){
14936 * Ext JS Library 1.1.1
14937 * Copyright(c) 2006-2007, Ext JS, LLC.
14939 * Originally Released Under LGPL - original licence link has changed is not relivant.
14942 * <script type="text/javascript">
14945 * @class Roo.state.CookieProvider
14946 * @extends Roo.state.Provider
14947 * The default Provider implementation which saves state via cookies.
14950 var cp = new Roo.state.CookieProvider({
14952 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14953 domain: "roojs.com"
14955 Roo.state.Manager.setProvider(cp);
14957 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14958 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14959 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14960 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14961 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14962 * domain the page is running on including the 'www' like 'www.roojs.com')
14963 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14965 * Create a new CookieProvider
14966 * @param {Object} config The configuration object
14968 Roo.state.CookieProvider = function(config){
14969 Roo.state.CookieProvider.superclass.constructor.call(this);
14971 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14972 this.domain = null;
14973 this.secure = false;
14974 Roo.apply(this, config);
14975 this.state = this.readCookies();
14978 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14980 set : function(name, value){
14981 if(typeof value == "undefined" || value === null){
14985 this.setCookie(name, value);
14986 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14990 clear : function(name){
14991 this.clearCookie(name);
14992 Roo.state.CookieProvider.superclass.clear.call(this, name);
14996 readCookies : function(){
14998 var c = document.cookie + ";";
14999 var re = /\s?(.*?)=(.*?);/g;
15001 while((matches = re.exec(c)) != null){
15002 var name = matches[1];
15003 var value = matches[2];
15004 if(name && name.substring(0,3) == "ys-"){
15005 cookies[name.substr(3)] = this.decodeValue(value);
15012 setCookie : function(name, value){
15013 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
15014 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
15015 ((this.path == null) ? "" : ("; path=" + this.path)) +
15016 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15017 ((this.secure == true) ? "; secure" : "");
15021 clearCookie : function(name){
15022 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
15023 ((this.path == null) ? "" : ("; path=" + this.path)) +
15024 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
15025 ((this.secure == true) ? "; secure" : "");
15029 * Ext JS Library 1.1.1
15030 * Copyright(c) 2006-2007, Ext JS, LLC.
15032 * Originally Released Under LGPL - original licence link has changed is not relivant.
15035 * <script type="text/javascript">
15040 * @class Roo.ComponentMgr
15041 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
15044 Roo.ComponentMgr = function(){
15045 var all = new Roo.util.MixedCollection();
15049 * Registers a component.
15050 * @param {Roo.Component} c The component
15052 register : function(c){
15057 * Unregisters a component.
15058 * @param {Roo.Component} c The component
15060 unregister : function(c){
15065 * Returns a component by id
15066 * @param {String} id The component id
15068 get : function(id){
15069 return all.get(id);
15073 * Registers a function that will be called when a specified component is added to ComponentMgr
15074 * @param {String} id The component id
15075 * @param {Funtction} fn The callback function
15076 * @param {Object} scope The scope of the callback
15078 onAvailable : function(id, fn, scope){
15079 all.on("add", function(index, o){
15081 fn.call(scope || o, o);
15082 all.un("add", fn, scope);
15089 * Ext JS Library 1.1.1
15090 * Copyright(c) 2006-2007, Ext JS, LLC.
15092 * Originally Released Under LGPL - original licence link has changed is not relivant.
15095 * <script type="text/javascript">
15099 * @class Roo.Component
15100 * @extends Roo.util.Observable
15101 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
15102 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
15103 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
15104 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
15105 * All visual components (widgets) that require rendering into a layout should subclass Component.
15107 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
15108 * 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
15109 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
15111 Roo.Component = function(config){
15112 config = config || {};
15113 if(config.tagName || config.dom || typeof config == "string"){ // element object
15114 config = {el: config, id: config.id || config};
15116 this.initialConfig = config;
15118 Roo.apply(this, config);
15122 * Fires after the component is disabled.
15123 * @param {Roo.Component} this
15128 * Fires after the component is enabled.
15129 * @param {Roo.Component} this
15133 * @event beforeshow
15134 * Fires before the component is shown. Return false to stop the show.
15135 * @param {Roo.Component} this
15140 * Fires after the component is shown.
15141 * @param {Roo.Component} this
15145 * @event beforehide
15146 * Fires before the component is hidden. Return false to stop the hide.
15147 * @param {Roo.Component} this
15152 * Fires after the component is hidden.
15153 * @param {Roo.Component} this
15157 * @event beforerender
15158 * Fires before the component is rendered. Return false to stop the render.
15159 * @param {Roo.Component} this
15161 beforerender : true,
15164 * Fires after the component is rendered.
15165 * @param {Roo.Component} this
15169 * @event beforedestroy
15170 * Fires before the component is destroyed. Return false to stop the destroy.
15171 * @param {Roo.Component} this
15173 beforedestroy : true,
15176 * Fires after the component is destroyed.
15177 * @param {Roo.Component} this
15182 this.id = "roo-comp-" + (++Roo.Component.AUTO_ID);
15184 Roo.ComponentMgr.register(this);
15185 Roo.Component.superclass.constructor.call(this);
15186 this.initComponent();
15187 if(this.renderTo){ // not supported by all components yet. use at your own risk!
15188 this.render(this.renderTo);
15189 delete this.renderTo;
15194 Roo.Component.AUTO_ID = 1000;
15196 Roo.extend(Roo.Component, Roo.util.Observable, {
15198 * @scope Roo.Component.prototype
15200 * true if this component is hidden. Read-only.
15205 * true if this component is disabled. Read-only.
15210 * true if this component has been rendered. Read-only.
15214 /** @cfg {String} disableClass
15215 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
15217 disabledClass : "x-item-disabled",
15218 /** @cfg {Boolean} allowDomMove
15219 * Whether the component can move the Dom node when rendering (defaults to true).
15221 allowDomMove : true,
15222 /** @cfg {String} hideMode (display|visibility)
15223 * How this component should hidden. Supported values are
15224 * "visibility" (css visibility), "offsets" (negative offset position) and
15225 * "display" (css display) - defaults to "display".
15227 hideMode: 'display',
15230 ctype : "Roo.Component",
15233 * @cfg {String} actionMode
15234 * which property holds the element that used for hide() / show() / disable() / enable()
15240 getActionEl : function(){
15241 return this[this.actionMode];
15244 initComponent : Roo.emptyFn,
15246 * If this is a lazy rendering component, render it to its container element.
15247 * @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.
15249 render : function(container, position){
15250 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
15251 if(!container && this.el){
15252 this.el = Roo.get(this.el);
15253 container = this.el.dom.parentNode;
15254 this.allowDomMove = false;
15256 this.container = Roo.get(container);
15257 this.rendered = true;
15258 if(position !== undefined){
15259 if(typeof position == 'number'){
15260 position = this.container.dom.childNodes[position];
15262 position = Roo.getDom(position);
15265 this.onRender(this.container, position || null);
15267 this.el.addClass(this.cls);
15271 this.el.applyStyles(this.style);
15274 this.fireEvent("render", this);
15275 this.afterRender(this.container);
15287 // default function is not really useful
15288 onRender : function(ct, position){
15290 this.el = Roo.get(this.el);
15291 if(this.allowDomMove !== false){
15292 ct.dom.insertBefore(this.el.dom, position);
15298 getAutoCreate : function(){
15299 var cfg = typeof this.autoCreate == "object" ?
15300 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
15301 if(this.id && !cfg.id){
15308 afterRender : Roo.emptyFn,
15311 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
15312 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
15314 destroy : function(){
15315 if(this.fireEvent("beforedestroy", this) !== false){
15316 this.purgeListeners();
15317 this.beforeDestroy();
15319 this.el.removeAllListeners();
15321 if(this.actionMode == "container"){
15322 this.container.remove();
15326 Roo.ComponentMgr.unregister(this);
15327 this.fireEvent("destroy", this);
15332 beforeDestroy : function(){
15337 onDestroy : function(){
15342 * Returns the underlying {@link Roo.Element}.
15343 * @return {Roo.Element} The element
15345 getEl : function(){
15350 * Returns the id of this component.
15353 getId : function(){
15358 * Try to focus this component.
15359 * @param {Boolean} selectText True to also select the text in this component (if applicable)
15360 * @return {Roo.Component} this
15362 focus : function(selectText){
15365 if(selectText === true){
15366 this.el.dom.select();
15381 * Disable this component.
15382 * @return {Roo.Component} this
15384 disable : function(){
15388 this.disabled = true;
15389 this.fireEvent("disable", this);
15394 onDisable : function(){
15395 this.getActionEl().addClass(this.disabledClass);
15396 this.el.dom.disabled = true;
15400 * Enable this component.
15401 * @return {Roo.Component} this
15403 enable : function(){
15407 this.disabled = false;
15408 this.fireEvent("enable", this);
15413 onEnable : function(){
15414 this.getActionEl().removeClass(this.disabledClass);
15415 this.el.dom.disabled = false;
15419 * Convenience function for setting disabled/enabled by boolean.
15420 * @param {Boolean} disabled
15422 setDisabled : function(disabled){
15423 this[disabled ? "disable" : "enable"]();
15427 * Show this component.
15428 * @return {Roo.Component} this
15431 if(this.fireEvent("beforeshow", this) !== false){
15432 this.hidden = false;
15436 this.fireEvent("show", this);
15442 onShow : function(){
15443 var ae = this.getActionEl();
15444 if(this.hideMode == 'visibility'){
15445 ae.dom.style.visibility = "visible";
15446 }else if(this.hideMode == 'offsets'){
15447 ae.removeClass('x-hidden');
15449 ae.dom.style.display = "";
15454 * Hide this component.
15455 * @return {Roo.Component} this
15458 if(this.fireEvent("beforehide", this) !== false){
15459 this.hidden = true;
15463 this.fireEvent("hide", this);
15469 onHide : function(){
15470 var ae = this.getActionEl();
15471 if(this.hideMode == 'visibility'){
15472 ae.dom.style.visibility = "hidden";
15473 }else if(this.hideMode == 'offsets'){
15474 ae.addClass('x-hidden');
15476 ae.dom.style.display = "none";
15481 * Convenience function to hide or show this component by boolean.
15482 * @param {Boolean} visible True to show, false to hide
15483 * @return {Roo.Component} this
15485 setVisible: function(visible){
15495 * Returns true if this component is visible.
15497 isVisible : function(){
15498 return this.getActionEl().isVisible();
15501 cloneConfig : function(overrides){
15502 overrides = overrides || {};
15503 var id = overrides.id || Roo.id();
15504 var cfg = Roo.applyIf(overrides, this.initialConfig);
15505 cfg.id = id; // prevent dup id
15506 return new this.constructor(cfg);
15510 * Ext JS Library 1.1.1
15511 * Copyright(c) 2006-2007, Ext JS, LLC.
15513 * Originally Released Under LGPL - original licence link has changed is not relivant.
15516 * <script type="text/javascript">
15520 * @class Roo.BoxComponent
15521 * @extends Roo.Component
15522 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
15523 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
15524 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
15525 * layout containers.
15527 * @param {Roo.Element/String/Object} config The configuration options.
15529 Roo.BoxComponent = function(config){
15530 Roo.Component.call(this, config);
15534 * Fires after the component is resized.
15535 * @param {Roo.Component} this
15536 * @param {Number} adjWidth The box-adjusted width that was set
15537 * @param {Number} adjHeight The box-adjusted height that was set
15538 * @param {Number} rawWidth The width that was originally specified
15539 * @param {Number} rawHeight The height that was originally specified
15544 * Fires after the component is moved.
15545 * @param {Roo.Component} this
15546 * @param {Number} x The new x position
15547 * @param {Number} y The new y position
15553 Roo.extend(Roo.BoxComponent, Roo.Component, {
15554 // private, set in afterRender to signify that the component has been rendered
15556 // private, used to defer height settings to subclasses
15557 deferHeight: false,
15558 /** @cfg {Number} width
15559 * width (optional) size of component
15561 /** @cfg {Number} height
15562 * height (optional) size of component
15566 * Sets the width and height of the component. This method fires the resize event. This method can accept
15567 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
15568 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
15569 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
15570 * @return {Roo.BoxComponent} this
15572 setSize : function(w, h){
15573 // support for standard size objects
15574 if(typeof w == 'object'){
15579 if(!this.boxReady){
15585 // prevent recalcs when not needed
15586 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
15589 this.lastSize = {width: w, height: h};
15591 var adj = this.adjustSize(w, h);
15592 var aw = adj.width, ah = adj.height;
15593 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
15594 var rz = this.getResizeEl();
15595 if(!this.deferHeight && aw !== undefined && ah !== undefined){
15596 rz.setSize(aw, ah);
15597 }else if(!this.deferHeight && ah !== undefined){
15599 }else if(aw !== undefined){
15602 this.onResize(aw, ah, w, h);
15603 this.fireEvent('resize', this, aw, ah, w, h);
15609 * Gets the current size of the component's underlying element.
15610 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
15612 getSize : function(){
15613 return this.el.getSize();
15617 * Gets the current XY position of the component's underlying element.
15618 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15619 * @return {Array} The XY position of the element (e.g., [100, 200])
15621 getPosition : function(local){
15622 if(local === true){
15623 return [this.el.getLeft(true), this.el.getTop(true)];
15625 return this.xy || this.el.getXY();
15629 * Gets the current box measurements of the component's underlying element.
15630 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
15631 * @returns {Object} box An object in the format {x, y, width, height}
15633 getBox : function(local){
15634 var s = this.el.getSize();
15636 s.x = this.el.getLeft(true);
15637 s.y = this.el.getTop(true);
15639 var xy = this.xy || this.el.getXY();
15647 * Sets the current box measurements of the component's underlying element.
15648 * @param {Object} box An object in the format {x, y, width, height}
15649 * @returns {Roo.BoxComponent} this
15651 updateBox : function(box){
15652 this.setSize(box.width, box.height);
15653 this.setPagePosition(box.x, box.y);
15658 getResizeEl : function(){
15659 return this.resizeEl || this.el;
15663 getPositionEl : function(){
15664 return this.positionEl || this.el;
15668 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
15669 * This method fires the move event.
15670 * @param {Number} left The new left
15671 * @param {Number} top The new top
15672 * @returns {Roo.BoxComponent} this
15674 setPosition : function(x, y){
15677 if(!this.boxReady){
15680 var adj = this.adjustPosition(x, y);
15681 var ax = adj.x, ay = adj.y;
15683 var el = this.getPositionEl();
15684 if(ax !== undefined || ay !== undefined){
15685 if(ax !== undefined && ay !== undefined){
15686 el.setLeftTop(ax, ay);
15687 }else if(ax !== undefined){
15689 }else if(ay !== undefined){
15692 this.onPosition(ax, ay);
15693 this.fireEvent('move', this, ax, ay);
15699 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
15700 * This method fires the move event.
15701 * @param {Number} x The new x position
15702 * @param {Number} y The new y position
15703 * @returns {Roo.BoxComponent} this
15705 setPagePosition : function(x, y){
15708 if(!this.boxReady){
15711 if(x === undefined || y === undefined){ // cannot translate undefined points
15714 var p = this.el.translatePoints(x, y);
15715 this.setPosition(p.left, p.top);
15720 onRender : function(ct, position){
15721 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
15723 this.resizeEl = Roo.get(this.resizeEl);
15725 if(this.positionEl){
15726 this.positionEl = Roo.get(this.positionEl);
15731 afterRender : function(){
15732 Roo.BoxComponent.superclass.afterRender.call(this);
15733 this.boxReady = true;
15734 this.setSize(this.width, this.height);
15735 if(this.x || this.y){
15736 this.setPosition(this.x, this.y);
15738 if(this.pageX || this.pageY){
15739 this.setPagePosition(this.pageX, this.pageY);
15744 * Force the component's size to recalculate based on the underlying element's current height and width.
15745 * @returns {Roo.BoxComponent} this
15747 syncSize : function(){
15748 delete this.lastSize;
15749 this.setSize(this.el.getWidth(), this.el.getHeight());
15754 * Called after the component is resized, this method is empty by default but can be implemented by any
15755 * subclass that needs to perform custom logic after a resize occurs.
15756 * @param {Number} adjWidth The box-adjusted width that was set
15757 * @param {Number} adjHeight The box-adjusted height that was set
15758 * @param {Number} rawWidth The width that was originally specified
15759 * @param {Number} rawHeight The height that was originally specified
15761 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
15766 * Called after the component is moved, this method is empty by default but can be implemented by any
15767 * subclass that needs to perform custom logic after a move occurs.
15768 * @param {Number} x The new x position
15769 * @param {Number} y The new y position
15771 onPosition : function(x, y){
15776 adjustSize : function(w, h){
15777 if(this.autoWidth){
15780 if(this.autoHeight){
15783 return {width : w, height: h};
15787 adjustPosition : function(x, y){
15788 return {x : x, y: y};
15791 * Original code for Roojs - LGPL
15792 * <script type="text/javascript">
15796 * @class Roo.XComponent
15797 * A delayed Element creator...
15798 * Or a way to group chunks of interface together.
15799 * technically this is a wrapper around a tree of Roo elements (which defines a 'module'),
15800 * used in conjunction with XComponent.build() it will create an instance of each element,
15801 * then call addxtype() to build the User interface.
15803 * Mypart.xyx = new Roo.XComponent({
15805 parent : 'Mypart.xyz', // empty == document.element.!!
15809 disabled : function() {}
15811 tree : function() { // return an tree of xtype declared components
15815 xtype : 'NestedLayoutPanel',
15822 * It can be used to build a big heiracy, with parent etc.
15823 * or you can just use this to render a single compoent to a dom element
15824 * MYPART.render(Roo.Element | String(id) | dom_element )
15831 * Roo is designed primarily as a single page application, so the UI build for a standard interface will
15832 * expect a single 'TOP' level module normally indicated by the 'parent' of the XComponent definition being defined as false.
15834 * Each sub module is expected to have a parent pointing to the class name of it's parent module.
15836 * When the top level is false, a 'Roo.BorderLayout' is created and the element is flagged as 'topModule'
15837 * - if mulitple topModules exist, the last one is defined as the top module.
15841 * When the top level or multiple modules are to embedded into a existing HTML page,
15842 * the parent element can container '#id' of the element where the module will be drawn.
15846 * Unlike classic Roo, the bootstrap tends not to be used as a single page.
15847 * it relies more on a include mechanism, where sub modules are included into an outer page.
15848 * This is normally managed by the builder tools using Roo.apply( options, Included.Sub.Module )
15850 * Bootstrap Roo Included elements
15852 * Our builder application needs the ability to preview these sub compoennts. They will normally have parent=false set,
15853 * hence confusing the component builder as it thinks there are multiple top level elements.
15857 * @extends Roo.util.Observable
15859 * @param cfg {Object} configuration of component
15862 Roo.XComponent = function(cfg) {
15863 Roo.apply(this, cfg);
15867 * Fires when this the componnt is built
15868 * @param {Roo.XComponent} c the component
15873 this.region = this.region || 'center'; // default..
15874 Roo.XComponent.register(this);
15875 this.modules = false;
15876 this.el = false; // where the layout goes..
15880 Roo.extend(Roo.XComponent, Roo.util.Observable, {
15883 * The created element (with Roo.factory())
15884 * @type {Roo.Layout}
15890 * for BC - use el in new code
15891 * @type {Roo.Layout}
15897 * for BC - use el in new code
15898 * @type {Roo.Layout}
15903 * @cfg {Function|boolean} disabled
15904 * If this module is disabled by some rule, return true from the funtion
15909 * @cfg {String} parent
15910 * Name of parent element which it get xtype added to..
15915 * @cfg {String} order
15916 * Used to set the order in which elements are created (usefull for multiple tabs)
15921 * @cfg {String} name
15922 * String to display while loading.
15926 * @cfg {String} region
15927 * Region to render component to (defaults to center)
15932 * @cfg {Array} items
15933 * A single item array - the first element is the root of the tree..
15934 * It's done this way to stay compatible with the Xtype system...
15940 * The method that retuns the tree of parts that make up this compoennt
15947 * render element to dom or tree
15948 * @param {Roo.Element|String|DomElement} optional render to if parent is not set.
15951 render : function(el)
15955 var hp = this.parent ? 1 : 0;
15956 Roo.debug && Roo.log(this);
15958 if (!el && typeof(this.parent) == 'string' && this.parent.substring(0,1) == '#') {
15959 // if parent is a '#.....' string, then let's use that..
15960 var ename = this.parent.substr(1);
15961 this.parent = false;
15962 Roo.debug && Roo.log(ename);
15964 case 'bootstrap-body' :
15965 if (typeof(Roo.bootstrap.Body) != 'undefined') {
15966 this.parent = { el : new Roo.bootstrap.Body() };
15967 Roo.debug && Roo.log("setting el to doc body");
15970 throw "Container is bootstrap body, but Roo.bootstrap.Body is not defined";
15974 this.parent = { el : true};
15977 el = Roo.get(ename);
15982 if (!el && !this.parent) {
15983 Roo.debug && Roo.log("Warning - element can not be found :#" + ename );
15987 Roo.debug && Roo.log("EL:");
15988 Roo.debug && Roo.log(el);
15989 Roo.debug && Roo.log("this.parent.el:");
15990 Roo.debug && Roo.log(this.parent.el);
15992 var tree = this._tree ? this._tree() : this.tree();
15994 // altertive root elements ??? - we need a better way to indicate these.
15995 var is_alt = (typeof(Roo.bootstrap) != 'undefined' && tree.xns == Roo.bootstrap) ||
15996 (typeof(Roo.mailer) != 'undefined' && tree.xns == Roo.mailer) ;
15998 if (!this.parent && is_alt) {
15999 //el = Roo.get(document.body);
16000 this.parent = { el : true };
16005 if (!this.parent) {
16007 Roo.debug && Roo.log("no parent - creating one");
16009 el = el ? Roo.get(el) : false;
16011 // it's a top level one..
16013 el : new Roo.BorderLayout(el || document.body, {
16019 tabPosition: 'top',
16020 //resizeTabs: true,
16021 alwaysShowTabs: el && hp? false : true,
16022 hideTabs: el || !hp ? true : false,
16029 if (!this.parent.el) {
16030 // probably an old style ctor, which has been disabled.
16034 // The 'tree' method is '_tree now'
16036 tree.region = tree.region || this.region;
16038 if (this.parent.el === true) {
16039 // bootstrap... - body..
16040 this.parent.el = Roo.factory(tree);
16043 this.el = this.parent.el.addxtype(tree);
16044 this.fireEvent('built', this);
16046 this.panel = this.el;
16047 this.layout = this.panel.layout;
16048 this.parentLayout = this.parent.layout || false;
16054 Roo.apply(Roo.XComponent, {
16056 * @property hideProgress
16057 * true to disable the building progress bar.. usefull on single page renders.
16060 hideProgress : false,
16062 * @property buildCompleted
16063 * True when the builder has completed building the interface.
16066 buildCompleted : false,
16069 * @property topModule
16070 * the upper most module - uses document.element as it's constructor.
16077 * @property modules
16078 * array of modules to be created by registration system.
16079 * @type {Array} of Roo.XComponent
16084 * @property elmodules
16085 * array of modules to be created by which use #ID
16086 * @type {Array} of Roo.XComponent
16092 * @property build_from_html
16093 * Build elements from html - used by bootstrap HTML stuff
16094 * - this is cleared after build is completed
16095 * @type {boolean} true (default false)
16098 build_from_html : false,
16101 * Register components to be built later.
16103 * This solves the following issues
16104 * - Building is not done on page load, but after an authentication process has occured.
16105 * - Interface elements are registered on page load
16106 * - Parent Interface elements may not be loaded before child, so this handles that..
16113 module : 'Pman.Tab.projectMgr',
16115 parent : 'Pman.layout',
16116 disabled : false, // or use a function..
16119 * * @param {Object} details about module
16121 register : function(obj) {
16123 Roo.XComponent.event.fireEvent('register', obj);
16124 switch(typeof(obj.disabled) ) {
16130 if ( obj.disabled() ) {
16136 if (obj.disabled) {
16142 this.modules.push(obj);
16146 * convert a string to an object..
16147 * eg. 'AAA.BBB' -> finds AAA.BBB
16151 toObject : function(str)
16153 if (!str || typeof(str) == 'object') {
16156 if (str.substring(0,1) == '#') {
16160 var ar = str.split('.');
16165 eval('if (typeof ' + rt + ' == "undefined"){ o = false;} o = ' + rt + ';');
16167 throw "Module not found : " + str;
16171 throw "Module not found : " + str;
16173 Roo.each(ar, function(e) {
16174 if (typeof(o[e]) == 'undefined') {
16175 throw "Module not found : " + str;
16186 * move modules into their correct place in the tree..
16189 preBuild : function ()
16192 Roo.each(this.modules , function (obj)
16194 Roo.XComponent.event.fireEvent('beforebuild', obj);
16196 var opar = obj.parent;
16198 obj.parent = this.toObject(opar);
16200 Roo.debug && Roo.log("parent:toObject failed: " + e.toString());
16205 Roo.debug && Roo.log("GOT top level module");
16206 Roo.debug && Roo.log(obj);
16207 obj.modules = new Roo.util.MixedCollection(false,
16208 function(o) { return o.order + '' }
16210 this.topModule = obj;
16213 // parent is a string (usually a dom element name..)
16214 if (typeof(obj.parent) == 'string') {
16215 this.elmodules.push(obj);
16218 if (obj.parent.constructor != Roo.XComponent) {
16219 Roo.debug && Roo.log("Warning : Object Parent is not instance of XComponent:" + obj.name)
16221 if (!obj.parent.modules) {
16222 obj.parent.modules = new Roo.util.MixedCollection(false,
16223 function(o) { return o.order + '' }
16226 if (obj.parent.disabled) {
16227 obj.disabled = true;
16229 obj.parent.modules.add(obj);
16234 * make a list of modules to build.
16235 * @return {Array} list of modules.
16238 buildOrder : function()
16241 var cmp = function(a,b) {
16242 return String(a).toUpperCase() > String(b).toUpperCase() ? 1 : -1;
16244 if ((!this.topModule || !this.topModule.modules) && !this.elmodules.length) {
16245 throw "No top level modules to build";
16248 // make a flat list in order of modules to build.
16249 var mods = this.topModule ? [ this.topModule ] : [];
16252 // elmodules (is a list of DOM based modules )
16253 Roo.each(this.elmodules, function(e) {
16255 if (!this.topModule &&
16256 typeof(e.parent) == 'string' &&
16257 e.parent.substring(0,1) == '#' &&
16258 Roo.get(e.parent.substr(1))
16261 _this.topModule = e;
16267 // add modules to their parents..
16268 var addMod = function(m) {
16269 Roo.debug && Roo.log("build Order: add: " + m.name);
16272 if (m.modules && !m.disabled) {
16273 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules");
16274 m.modules.keySort('ASC', cmp );
16275 Roo.debug && Roo.log("build Order: " + m.modules.length + " child modules (after sort)");
16277 m.modules.each(addMod);
16279 Roo.debug && Roo.log("build Order: no child modules");
16281 // not sure if this is used any more..
16283 m.finalize.name = m.name + " (clean up) ";
16284 mods.push(m.finalize);
16288 if (this.topModule && this.topModule.modules) {
16289 this.topModule.modules.keySort('ASC', cmp );
16290 this.topModule.modules.each(addMod);
16296 * Build the registered modules.
16297 * @param {Object} parent element.
16298 * @param {Function} optional method to call after module has been added.
16302 build : function(opts)
16305 if (typeof(opts) != 'undefined') {
16306 Roo.apply(this,opts);
16310 var mods = this.buildOrder();
16312 //this.allmods = mods;
16313 //Roo.debug && Roo.log(mods);
16315 if (!mods.length) { // should not happen
16316 throw "NO modules!!!";
16320 var msg = "Building Interface...";
16321 // flash it up as modal - so we store the mask!?
16322 if (!this.hideProgress && Roo.MessageBox) {
16323 Roo.MessageBox.show({ title: 'loading' });
16324 Roo.MessageBox.show({
16325 title: "Please wait...",
16334 var total = mods.length;
16337 var progressRun = function() {
16338 if (!mods.length) {
16339 Roo.debug && Roo.log('hide?');
16340 if (!this.hideProgress && Roo.MessageBox) {
16341 Roo.MessageBox.hide();
16343 Roo.XComponent.build_from_html = false; // reset, so dialogs will be build from javascript
16345 Roo.XComponent.event.fireEvent('buildcomplete', _this.topModule);
16351 var m = mods.shift();
16354 Roo.debug && Roo.log(m);
16355 // not sure if this is supported any more.. - modules that are are just function
16356 if (typeof(m) == 'function') {
16358 return progressRun.defer(10, _this);
16362 msg = "Building Interface " + (total - mods.length) +
16364 (m.name ? (' - ' + m.name) : '');
16365 Roo.debug && Roo.log(msg);
16366 if (!this.hideProgress && Roo.MessageBox) {
16367 Roo.MessageBox.updateProgress( (total - mods.length)/total, msg );
16371 // is the module disabled?
16372 var disabled = (typeof(m.disabled) == 'function') ?
16373 m.disabled.call(m.module.disabled) : m.disabled;
16377 return progressRun(); // we do not update the display!
16385 // it's 10 on top level, and 1 on others??? why...
16386 return progressRun.defer(10, _this);
16389 progressRun.defer(1, _this);
16403 * wrapper for event.on - aliased later..
16404 * Typically use to register a event handler for register:
16406 * eg. Roo.XComponent.on('register', function(comp) { comp.disable = true } );
16415 Roo.XComponent.event = new Roo.util.Observable({
16419 * Fires when an Component is registered,
16420 * set the disable property on the Component to stop registration.
16421 * @param {Roo.XComponent} c the component being registerd.
16426 * @event beforebuild
16427 * Fires before each Component is built
16428 * can be used to apply permissions.
16429 * @param {Roo.XComponent} c the component being registerd.
16432 'beforebuild' : true,
16434 * @event buildcomplete
16435 * Fires on the top level element when all elements have been built
16436 * @param {Roo.XComponent} the top level component.
16438 'buildcomplete' : true
16443 Roo.XComponent.on = Roo.XComponent.event.on.createDelegate(Roo.XComponent.event);