4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
89 * Turn on debugging output (currently only the factory uses this)
96 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
99 enableGarbageCollector : true,
102 * True to automatically purge event listeners after uncaching an element (defaults to false).
103 * Note: this only happens if enableGarbageCollector is true.
106 enableListenerCollection:false,
109 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
110 * the IE insecure content warning (defaults to javascript:false).
113 SSL_SECURE_URL : "javascript:false",
116 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
117 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
120 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
122 emptyFn : function(){},
125 * Copies all the properties of config to obj if they don't already exist.
126 * @param {Object} obj The receiver of the properties
127 * @param {Object} config The source of the properties
128 * @return {Object} returns obj
130 applyIf : function(o, c){
133 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
140 * Applies event listeners to elements by selectors when the document is ready.
141 * The event name is specified with an @ suffix.
144 // add a listener for click on all anchors in element with id foo
145 '#foo a@click' : function(e, t){
149 // add the same listener to multiple selectors (separated by comma BEFORE the @)
150 '#foo a, #bar span.some-class@mouseover' : function(){
155 * @param {Object} obj The list of behaviors to apply
157 addBehaviors : function(o){
159 Roo.onReady(function(){
164 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
166 var parts = b.split('@');
167 if(parts[1]){ // for Object prototype breakers
170 cache[s] = Roo.select(s);
172 cache[s].on(parts[1], o[b]);
179 * Generates unique ids. If the element already has an id, it is unchanged
180 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
181 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
182 * @return {String} The generated Id.
184 id : function(el, prefix){
185 prefix = prefix || "roo-gen";
187 var id = prefix + (++idSeed);
188 return el ? (el.id ? el.id : (el.id = id)) : id;
193 * Extends one class with another class and optionally overrides members with the passed literal. This class
194 * also adds the function "override()" to the class that can be used to override
195 * members on an instance.
196 * @param {Object} subclass The class inheriting the functionality
197 * @param {Object} superclass The class being extended
198 * @param {Object} overrides (optional) A literal with members
203 var io = function(o){
208 return function(sb, sp, overrides){
209 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
212 sb = function(){sp.apply(this, arguments);};
214 var F = function(){}, sbp, spp = sp.prototype;
216 sbp = sb.prototype = new F();
220 if(spp.constructor == Object.prototype.constructor){
225 sb.override = function(o){
229 Roo.override(sb, overrides);
235 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
237 Roo.override(MyClass, {
238 newMethod1: function(){
241 newMethod2: function(foo){
246 * @param {Object} origclass The class to override
247 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
248 * containing one or more methods.
251 override : function(origclass, overrides){
253 var p = origclass.prototype;
254 for(var method in overrides){
255 p[method] = overrides[method];
260 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
262 Roo.namespace('Company', 'Company.data');
263 Company.Widget = function() { ... }
264 Company.data.CustomStore = function(config) { ... }
266 * @param {String} namespace1
267 * @param {String} namespace2
268 * @param {String} etc
271 namespace : function(){
272 var a=arguments, o=null, i, j, d, rt;
273 for (i=0; i<a.length; ++i) {
277 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
278 for (j=1; j<d.length; ++j) {
279 o[d[j]]=o[d[j]] || {};
285 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
287 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
288 Roo.factory(conf, Roo.data);
290 * @param {String} classname
291 * @param {String} namespace (optional)
295 factory : function(c, ns)
297 // no xtype, no ns or c.xns - or forced off by c.xns
298 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
301 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
302 if (c.constructor == ns[c.xtype]) {// already created...
306 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
307 var ret = new ns[c.xtype](c);
311 c.xns = false; // prevent recursion..
315 * Logs to console if it can.
317 * @param {String|Object} string
322 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
329 * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2". Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
333 urlEncode : function(o){
339 var ov = o[key], k = Roo.encodeURIComponent(key);
340 var type = typeof ov;
341 if(type == 'undefined'){
343 }else if(type != "function" && type != "object"){
344 buf.push(k, "=", Roo.encodeURIComponent(ov), "&");
345 }else if(ov instanceof Array){
347 for(var i = 0, len = ov.length; i < len; i++) {
348 buf.push(k, "=", Roo.encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
359 * Safe version of encodeURIComponent
360 * @param {String} data
364 encodeURIComponent : function (data)
367 return encodeURIComponent(data);
368 } catch(e) {} // should be an uri encode error.
370 if (data == '' || data == null){
373 // http://stackoverflow.com/questions/2596483/unicode-and-uri-encoding-decoding-and-escaping-in-javascript
374 function nibble_to_hex(nibble){
375 var chars = '0123456789ABCDEF';
376 return chars.charAt(nibble);
378 data = data.toString();
380 for(var i=0; i<data.length; i++){
381 var c = data.charCodeAt(i);
382 var bs = new Array();
385 bs[0] = 0xF0 | ((c & 0x1C0000) >>> 18);
386 bs[1] = 0x80 | ((c & 0x3F000) >>> 12);
387 bs[2] = 0x80 | ((c & 0xFC0) >>> 6);
388 bs[3] = 0x80 | (c & 0x3F);
389 }else if (c > 0x800){
391 bs[0] = 0xE0 | ((c & 0xF000) >>> 12);
392 bs[1] = 0x80 | ((c & 0xFC0) >>> 6);
393 bs[2] = 0x80 | (c & 0x3F);
396 bs[0] = 0xC0 | ((c & 0x7C0) >>> 6);
397 bs[1] = 0x80 | (c & 0x3F);
402 for(var j=0; j<bs.length; j++){
404 var hex = nibble_to_hex((b & 0xF0) >>> 4)
405 + nibble_to_hex(b &0x0F);
414 * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
415 * @param {String} string
416 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
417 * @return {Object} A literal with members
419 urlDecode : function(string, overwrite){
420 if(!string || !string.length){
424 var pairs = string.split('&');
425 var pair, name, value;
426 for(var i = 0, len = pairs.length; i < len; i++){
427 pair = pairs[i].split('=');
428 name = decodeURIComponent(pair[0]);
429 value = decodeURIComponent(pair[1]);
430 if(overwrite !== true){
431 if(typeof obj[name] == "undefined"){
433 }else if(typeof obj[name] == "string"){
434 obj[name] = [obj[name]];
435 obj[name].push(value);
437 obj[name].push(value);
447 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
448 * passed array is not really an array, your function is called once with it.
449 * The supplied function is called with (Object item, Number index, Array allItems).
450 * @param {Array/NodeList/Mixed} array
451 * @param {Function} fn
452 * @param {Object} scope
454 each : function(array, fn, scope){
455 if(typeof array.length == "undefined" || typeof array == "string"){
458 for(var i = 0, len = array.length; i < len; i++){
459 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
464 combine : function(){
465 var as = arguments, l = as.length, r = [];
466 for(var i = 0; i < l; i++){
468 if(a instanceof Array){
470 }else if(a.length !== undefined && !a.substr){
471 r = r.concat(Array.prototype.slice.call(a, 0));
480 * Escapes the passed string for use in a regular expression
481 * @param {String} str
484 escapeRe : function(s) {
485 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
489 callback : function(cb, scope, args, delay){
490 if(typeof cb == "function"){
492 cb.defer(delay, scope, args || []);
494 cb.apply(scope, args || []);
500 * Return the dom node for the passed string (id), dom node, or Roo.Element
501 * @param {String/HTMLElement/Roo.Element} el
502 * @return HTMLElement
504 getDom : function(el){
508 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
512 * Shorthand for {@link Roo.ComponentMgr#get}
514 * @return Roo.Component
516 getCmp : function(id){
517 return Roo.ComponentMgr.get(id);
520 num : function(v, defaultValue){
521 if(typeof v != 'number'){
527 destroy : function(){
528 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
532 as.removeAllListeners();
536 if(typeof as.purgeListeners == 'function'){
539 if(typeof as.destroy == 'function'){
546 // inpired by a similar function in mootools library
548 * Returns the type of object that is passed in. If the object passed in is null or undefined it
549 * return false otherwise it returns one of the following values:<ul>
550 * <li><b>string</b>: If the object passed is a string</li>
551 * <li><b>number</b>: If the object passed is a number</li>
552 * <li><b>boolean</b>: If the object passed is a boolean value</li>
553 * <li><b>function</b>: If the object passed is a function reference</li>
554 * <li><b>object</b>: If the object passed is an object</li>
555 * <li><b>array</b>: If the object passed is an array</li>
556 * <li><b>regexp</b>: If the object passed is a regular expression</li>
557 * <li><b>element</b>: If the object passed is a DOM Element</li>
558 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
559 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
560 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
561 * @param {Mixed} object
565 if(o === undefined || o === null){
572 if(t == 'object' && o.nodeName) {
574 case 1: return 'element';
575 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
578 if(t == 'object' || t == 'function') {
579 switch(o.constructor) {
580 case Array: return 'array';
581 case RegExp: return 'regexp';
583 if(typeof o.length == 'number' && typeof o.item == 'function') {
591 * Returns true if the passed value is null, undefined or an empty string (optional).
592 * @param {Mixed} value The value to test
593 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
596 isEmpty : function(v, allowBlank){
597 return v === null || v === undefined || (!allowBlank ? v === '' : false);
611 isBorderBox : isBorderBox,
613 isWindows : isWindows,
620 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
621 * you may want to set this to true.
624 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
629 * Selects a single element as a Roo Element
630 * This is about as close as you can get to jQuery's $('do crazy stuff')
631 * @param {String} selector The selector/xpath query
632 * @param {Node} root (optional) The start of the query (defaults to document).
633 * @return {Roo.Element}
635 selectNode : function(selector, root)
637 var node = Roo.DomQuery.selectNode(selector,root);
638 return node ? Roo.get(node) : new Roo.Element(false);
646 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
647 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
650 * Ext JS Library 1.1.1
651 * Copyright(c) 2006-2007, Ext JS, LLC.
653 * Originally Released Under LGPL - original licence link has changed is not relivant.
656 * <script type="text/javascript">
660 // wrappedn so fnCleanup is not in global scope...
662 function fnCleanUp() {
663 var p = Function.prototype;
664 delete p.createSequence;
666 delete p.createDelegate;
667 delete p.createCallback;
668 delete p.createInterceptor;
670 window.detachEvent("onunload", fnCleanUp);
672 window.attachEvent("onunload", fnCleanUp);
679 * These functions are available on every Function object (any JavaScript function).
681 Roo.apply(Function.prototype, {
683 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
684 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
685 * Will create a function that is bound to those 2 args.
686 * @return {Function} The new function
688 createCallback : function(/*args...*/){
689 // make args available, in function below
690 var args = arguments;
693 return method.apply(window, args);
698 * Creates a delegate (callback) that sets the scope to obj.
699 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
700 * Will create a function that is automatically scoped to this.
701 * @param {Object} obj (optional) The object for which the scope is set
702 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
703 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
704 * if a number the args are inserted at the specified position
705 * @return {Function} The new function
707 createDelegate : function(obj, args, appendArgs){
710 var callArgs = args || arguments;
711 if(appendArgs === true){
712 callArgs = Array.prototype.slice.call(arguments, 0);
713 callArgs = callArgs.concat(args);
714 }else if(typeof appendArgs == "number"){
715 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
716 var applyArgs = [appendArgs, 0].concat(args); // create method call params
717 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
719 return method.apply(obj || window, callArgs);
724 * Calls this function after the number of millseconds specified.
725 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
726 * @param {Object} obj (optional) The object for which the scope is set
727 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
728 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
729 * if a number the args are inserted at the specified position
730 * @return {Number} The timeout id that can be used with clearTimeout
732 defer : function(millis, obj, args, appendArgs){
733 var fn = this.createDelegate(obj, args, appendArgs);
735 return setTimeout(fn, millis);
741 * Create a combined function call sequence of the original function + the passed function.
742 * The resulting function returns the results of the original function.
743 * The passed fcn is called with the parameters of the original function
744 * @param {Function} fcn The function to sequence
745 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
746 * @return {Function} The new function
748 createSequence : function(fcn, scope){
749 if(typeof fcn != "function"){
754 var retval = method.apply(this || window, arguments);
755 fcn.apply(scope || this || window, arguments);
761 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
762 * The resulting function returns the results of the original function.
763 * The passed fcn is called with the parameters of the original function.
765 * @param {Function} fcn The function to call before the original
766 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
767 * @return {Function} The new function
769 createInterceptor : function(fcn, scope){
770 if(typeof fcn != "function"){
777 if(fcn.apply(scope || this || window, arguments) === false){
780 return method.apply(this || window, arguments);
786 * Ext JS Library 1.1.1
787 * Copyright(c) 2006-2007, Ext JS, LLC.
789 * Originally Released Under LGPL - original licence link has changed is not relivant.
792 * <script type="text/javascript">
795 Roo.applyIf(String, {
800 * Escapes the passed string for ' and \
801 * @param {String} string The string to escape
802 * @return {String} The escaped string
805 escape : function(string) {
806 return string.replace(/('|\\)/g, "\\$1");
810 * Pads the left side of a string with a specified character. This is especially useful
811 * for normalizing number and date strings. Example usage:
813 var s = String.leftPad('123', 5, '0');
814 // s now contains the string: '00123'
816 * @param {String} string The original string
817 * @param {Number} size The total length of the output string
818 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
819 * @return {String} The padded string
822 leftPad : function (val, size, ch) {
823 var result = new String(val);
824 if(ch === null || ch === undefined || ch === '') {
827 while (result.length < size) {
828 result = ch + result;
834 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
835 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
837 var cls = 'my-class', text = 'Some text';
838 var s = String.format('<div class="{0}">{1}</div>', cls, text);
839 // s now contains the string: '<div class="my-class">Some text</div>'
841 * @param {String} string The tokenized string to be formatted
842 * @param {String} value1 The value to replace token {0}
843 * @param {String} value2 Etc...
844 * @return {String} The formatted string
847 format : function(format){
848 var args = Array.prototype.slice.call(arguments, 1);
849 return format.replace(/\{(\d+)\}/g, function(m, i){
850 return Roo.util.Format.htmlEncode(args[i]);
856 * Utility function that allows you to easily switch a string between two alternating values. The passed value
857 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
858 * they are already different, the first value passed in is returned. Note that this method returns the new value
859 * but does not change the current string.
861 // alternate sort directions
862 sort = sort.toggle('ASC', 'DESC');
864 // instead of conditional logic:
865 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
867 * @param {String} value The value to compare to the current string
868 * @param {String} other The new value to use if the string already equals the first value passed in
869 * @return {String} The new value
872 String.prototype.toggle = function(value, other){
873 return this == value ? other : value;
876 * Ext JS Library 1.1.1
877 * Copyright(c) 2006-2007, Ext JS, LLC.
879 * Originally Released Under LGPL - original licence link has changed is not relivant.
882 * <script type="text/javascript">
888 Roo.applyIf(Number.prototype, {
890 * Checks whether or not the current number is within a desired range. If the number is already within the
891 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
892 * exceeded. Note that this method returns the constrained value but does not change the current number.
893 * @param {Number} min The minimum number in the range
894 * @param {Number} max The maximum number in the range
895 * @return {Number} The constrained value if outside the range, otherwise the current value
897 constrain : function(min, max){
898 return Math.min(Math.max(this, min), max);
902 * Ext JS Library 1.1.1
903 * Copyright(c) 2006-2007, Ext JS, LLC.
905 * Originally Released Under LGPL - original licence link has changed is not relivant.
908 * <script type="text/javascript">
913 Roo.applyIf(Array.prototype, {
915 * Checks whether or not the specified object exists in the array.
916 * @param {Object} o The object to check for
917 * @return {Number} The index of o in the array (or -1 if it is not found)
919 indexOf : function(o){
920 for (var i = 0, len = this.length; i < len; i++){
921 if(this[i] == o) return i;
927 * Removes the specified object from the array. If the object is not found nothing happens.
928 * @param {Object} o The object to remove
930 remove : function(o){
931 var index = this.indexOf(o);
933 this.splice(index, 1);
937 * Map (JS 1.6 compatibility)
938 * @param {Function} function to call
942 var len = this.length >>> 0;
943 if (typeof fun != "function")
944 throw new TypeError();
946 var res = new Array(len);
947 var thisp = arguments[1];
948 for (var i = 0; i < len; i++)
951 res[i] = fun.call(thisp, this[i], i, this);
962 * Ext JS Library 1.1.1
963 * Copyright(c) 2006-2007, Ext JS, LLC.
965 * Originally Released Under LGPL - original licence link has changed is not relivant.
968 * <script type="text/javascript">
974 * The date parsing and format syntax is a subset of
975 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
976 * supported will provide results equivalent to their PHP versions.
978 * Following is the list of all currently supported formats:
981 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
983 Format Output Description
984 ------ ---------- --------------------------------------------------------------
985 d 10 Day of the month, 2 digits with leading zeros
986 D Wed A textual representation of a day, three letters
987 j 10 Day of the month without leading zeros
988 l Wednesday A full textual representation of the day of the week
989 S th English ordinal day of month suffix, 2 chars (use with j)
990 w 3 Numeric representation of the day of the week
991 z 9 The julian date, or day of the year (0-365)
992 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
993 F January A full textual representation of the month
994 m 01 Numeric representation of a month, with leading zeros
995 M Jan Month name abbreviation, three letters
996 n 1 Numeric representation of a month, without leading zeros
997 t 31 Number of days in the given month
998 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
999 Y 2007 A full numeric representation of a year, 4 digits
1000 y 07 A two digit representation of a year
1001 a pm Lowercase Ante meridiem and Post meridiem
1002 A PM Uppercase Ante meridiem and Post meridiem
1003 g 3 12-hour format of an hour without leading zeros
1004 G 15 24-hour format of an hour without leading zeros
1005 h 03 12-hour format of an hour with leading zeros
1006 H 15 24-hour format of an hour with leading zeros
1007 i 05 Minutes with leading zeros
1008 s 01 Seconds, with leading zeros
1009 O -0600 Difference to Greenwich time (GMT) in hours
1010 T CST Timezone setting of the machine running the code
1011 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
1014 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
1016 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
1017 document.write(dt.format('Y-m-d')); //2007-01-10
1018 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
1019 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
1022 * Here are some standard date/time patterns that you might find helpful. They
1023 * are not part of the source of Date.js, but to use them you can simply copy this
1024 * block of code into any script that is included after Date.js and they will also become
1025 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
1028 ISO8601Long:"Y-m-d H:i:s",
1029 ISO8601Short:"Y-m-d",
1031 LongDate: "l, F d, Y",
1032 FullDateTime: "l, F d, Y g:i:s A",
1035 LongTime: "g:i:s A",
1036 SortableDateTime: "Y-m-d\\TH:i:s",
1037 UniversalSortableDateTime: "Y-m-d H:i:sO",
1044 var dt = new Date();
1045 document.write(dt.format(Date.patterns.ShortDate));
1050 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
1051 * They generate precompiled functions from date formats instead of parsing and
1052 * processing the pattern every time you format a date. These functions are available
1053 * on every Date object (any javascript function).
1055 * The original article and download are here:
1056 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1063 Returns the number of milliseconds between this date and date
1064 @param {Date} date (optional) Defaults to now
1065 @return {Number} The diff in milliseconds
1066 @member Date getElapsed
1068 Date.prototype.getElapsed = function(date) {
1069 return Math.abs((date || new Date()).getTime()-this.getTime());
1071 // was in date file..
1075 Date.parseFunctions = {count:0};
1077 Date.parseRegexes = [];
1079 Date.formatFunctions = {count:0};
1082 Date.prototype.dateFormat = function(format) {
1083 if (Date.formatFunctions[format] == null) {
1084 Date.createNewFormat(format);
1086 var func = Date.formatFunctions[format];
1087 return this[func]();
1092 * Formats a date given the supplied format string
1093 * @param {String} format The format string
1094 * @return {String} The formatted date
1097 Date.prototype.format = Date.prototype.dateFormat;
1100 Date.createNewFormat = function(format) {
1101 var funcName = "format" + Date.formatFunctions.count++;
1102 Date.formatFunctions[format] = funcName;
1103 var code = "Date.prototype." + funcName + " = function(){return ";
1104 var special = false;
1106 for (var i = 0; i < format.length; ++i) {
1107 ch = format.charAt(i);
1108 if (!special && ch == "\\") {
1113 code += "'" + String.escape(ch) + "' + ";
1116 code += Date.getFormatCode(ch);
1119 /** eval:var:zzzzzzzzzzzzz */
1120 eval(code.substring(0, code.length - 3) + ";}");
1124 Date.getFormatCode = function(character) {
1125 switch (character) {
1127 return "String.leftPad(this.getDate(), 2, '0') + ";
1129 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1131 return "this.getDate() + ";
1133 return "Date.dayNames[this.getDay()] + ";
1135 return "this.getSuffix() + ";
1137 return "this.getDay() + ";
1139 return "this.getDayOfYear() + ";
1141 return "this.getWeekOfYear() + ";
1143 return "Date.monthNames[this.getMonth()] + ";
1145 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1147 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1149 return "(this.getMonth() + 1) + ";
1151 return "this.getDaysInMonth() + ";
1153 return "(this.isLeapYear() ? 1 : 0) + ";
1155 return "this.getFullYear() + ";
1157 return "('' + this.getFullYear()).substring(2, 4) + ";
1159 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1161 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1163 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1165 return "this.getHours() + ";
1167 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1169 return "String.leftPad(this.getHours(), 2, '0') + ";
1171 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1173 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1175 return "this.getGMTOffset() + ";
1177 return "this.getTimezone() + ";
1179 return "(this.getTimezoneOffset() * -60) + ";
1181 return "'" + String.escape(character) + "' + ";
1186 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1187 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1188 * the date format that is not specified will default to the current date value for that part. Time parts can also
1189 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1190 * string or the parse operation will fail.
1193 //dt = Fri May 25 2007 (current date)
1194 var dt = new Date();
1196 //dt = Thu May 25 2006 (today's month/day in 2006)
1197 dt = Date.parseDate("2006", "Y");
1199 //dt = Sun Jan 15 2006 (all date parts specified)
1200 dt = Date.parseDate("2006-1-15", "Y-m-d");
1202 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1203 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1205 * @param {String} input The unparsed date as a string
1206 * @param {String} format The format the date is in
1207 * @return {Date} The parsed date
1210 Date.parseDate = function(input, format) {
1211 if (Date.parseFunctions[format] == null) {
1212 Date.createParser(format);
1214 var func = Date.parseFunctions[format];
1215 return Date[func](input);
1220 Date.createParser = function(format) {
1221 var funcName = "parse" + Date.parseFunctions.count++;
1222 var regexNum = Date.parseRegexes.length;
1223 var currentGroup = 1;
1224 Date.parseFunctions[format] = funcName;
1226 var code = "Date." + funcName + " = function(input){\n"
1227 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1228 + "var d = new Date();\n"
1229 + "y = d.getFullYear();\n"
1230 + "m = d.getMonth();\n"
1231 + "d = d.getDate();\n"
1232 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1233 + "if (results && results.length > 0) {";
1236 var special = false;
1238 for (var i = 0; i < format.length; ++i) {
1239 ch = format.charAt(i);
1240 if (!special && ch == "\\") {
1245 regex += String.escape(ch);
1248 var obj = Date.formatCodeToRegex(ch, currentGroup);
1249 currentGroup += obj.g;
1251 if (obj.g && obj.c) {
1257 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1258 + "{v = new Date(y, m, d, h, i, s);}\n"
1259 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1260 + "{v = new Date(y, m, d, h, i);}\n"
1261 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1262 + "{v = new Date(y, m, d, h);}\n"
1263 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1264 + "{v = new Date(y, m, d);}\n"
1265 + "else if (y >= 0 && m >= 0)\n"
1266 + "{v = new Date(y, m);}\n"
1267 + "else if (y >= 0)\n"
1268 + "{v = new Date(y);}\n"
1269 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1270 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1271 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1274 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1275 /** eval:var:zzzzzzzzzzzzz */
1280 Date.formatCodeToRegex = function(character, currentGroup) {
1281 switch (character) {
1285 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1288 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1289 s:"(\\d{1,2})"}; // day of month without leading zeroes
1292 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1293 s:"(\\d{2})"}; // day of month with leading zeroes
1297 s:"(?:" + Date.dayNames.join("|") + ")"};
1301 s:"(?:st|nd|rd|th)"};
1316 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1317 s:"(" + Date.monthNames.join("|") + ")"};
1320 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1321 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1324 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1325 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1328 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1329 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1340 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1344 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1345 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1349 c:"if (results[" + currentGroup + "] == 'am') {\n"
1350 + "if (h == 12) { h = 0; }\n"
1351 + "} else { if (h < 12) { h += 12; }}",
1355 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1356 + "if (h == 12) { h = 0; }\n"
1357 + "} else { if (h < 12) { h += 12; }}",
1362 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1363 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1367 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1368 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1371 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1375 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1380 "o = results[", currentGroup, "];\n",
1381 "var sn = o.substring(0,1);\n", // get + / - sign
1382 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1383 "var mn = o.substring(3,5) % 60;\n", // get minutes
1384 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1385 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1391 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1394 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1395 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1396 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1400 s:String.escape(character)};
1405 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1406 * @return {String} The abbreviated timezone name (e.g. 'CST')
1408 Date.prototype.getTimezone = function() {
1409 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1413 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1414 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1416 Date.prototype.getGMTOffset = function() {
1417 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1418 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1419 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1423 * Get the numeric day number of the year, adjusted for leap year.
1424 * @return {Number} 0 through 364 (365 in leap years)
1426 Date.prototype.getDayOfYear = function() {
1428 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1429 for (var i = 0; i < this.getMonth(); ++i) {
1430 num += Date.daysInMonth[i];
1432 return num + this.getDate() - 1;
1436 * Get the string representation of the numeric week number of the year
1437 * (equivalent to the format specifier 'W').
1438 * @return {String} '00' through '52'
1440 Date.prototype.getWeekOfYear = function() {
1441 // Skip to Thursday of this week
1442 var now = this.getDayOfYear() + (4 - this.getDay());
1443 // Find the first Thursday of the year
1444 var jan1 = new Date(this.getFullYear(), 0, 1);
1445 var then = (7 - jan1.getDay() + 4);
1446 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1450 * Whether or not the current date is in a leap year.
1451 * @return {Boolean} True if the current date is in a leap year, else false
1453 Date.prototype.isLeapYear = function() {
1454 var year = this.getFullYear();
1455 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1459 * Get the first day of the current month, adjusted for leap year. The returned value
1460 * is the numeric day index within the week (0-6) which can be used in conjunction with
1461 * the {@link #monthNames} array to retrieve the textual day name.
1464 var dt = new Date('1/10/2007');
1465 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1467 * @return {Number} The day number (0-6)
1469 Date.prototype.getFirstDayOfMonth = function() {
1470 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1471 return (day < 0) ? (day + 7) : day;
1475 * Get the last day of the current month, adjusted for leap year. The returned value
1476 * is the numeric day index within the week (0-6) which can be used in conjunction with
1477 * the {@link #monthNames} array to retrieve the textual day name.
1480 var dt = new Date('1/10/2007');
1481 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1483 * @return {Number} The day number (0-6)
1485 Date.prototype.getLastDayOfMonth = function() {
1486 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1487 return (day < 0) ? (day + 7) : day;
1492 * Get the first date of this date's month
1495 Date.prototype.getFirstDateOfMonth = function() {
1496 return new Date(this.getFullYear(), this.getMonth(), 1);
1500 * Get the last date of this date's month
1503 Date.prototype.getLastDateOfMonth = function() {
1504 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1507 * Get the number of days in the current month, adjusted for leap year.
1508 * @return {Number} The number of days in the month
1510 Date.prototype.getDaysInMonth = function() {
1511 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1512 return Date.daysInMonth[this.getMonth()];
1516 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1517 * @return {String} 'st, 'nd', 'rd' or 'th'
1519 Date.prototype.getSuffix = function() {
1520 switch (this.getDate()) {
1537 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1540 * An array of textual month names.
1541 * Override these values for international dates, for example...
1542 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1561 * An array of textual day names.
1562 * Override these values for international dates, for example...
1563 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1579 Date.monthNumbers = {
1594 * Creates and returns a new Date instance with the exact same date value as the called instance.
1595 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1596 * variable will also be changed. When the intention is to create a new variable that will not
1597 * modify the original instance, you should create a clone.
1599 * Example of correctly cloning a date:
1602 var orig = new Date('10/1/2006');
1605 document.write(orig); //returns 'Thu Oct 05 2006'!
1608 var orig = new Date('10/1/2006');
1609 var copy = orig.clone();
1611 document.write(orig); //returns 'Thu Oct 01 2006'
1613 * @return {Date} The new Date instance
1615 Date.prototype.clone = function() {
1616 return new Date(this.getTime());
1620 * Clears any time information from this date
1621 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1622 @return {Date} this or the clone
1624 Date.prototype.clearTime = function(clone){
1626 return this.clone().clearTime();
1631 this.setMilliseconds(0);
1636 // safari setMonth is broken
1638 Date.brokenSetMonth = Date.prototype.setMonth;
1639 Date.prototype.setMonth = function(num){
1641 var n = Math.ceil(-num);
1642 var back_year = Math.ceil(n/12);
1643 var month = (n % 12) ? 12 - n % 12 : 0 ;
1644 this.setFullYear(this.getFullYear() - back_year);
1645 return Date.brokenSetMonth.call(this, month);
1647 return Date.brokenSetMonth.apply(this, arguments);
1652 /** Date interval constant
1656 /** Date interval constant
1660 /** Date interval constant
1664 /** Date interval constant
1668 /** Date interval constant
1672 /** Date interval constant
1676 /** Date interval constant
1682 * Provides a convenient method of performing basic date arithmetic. This method
1683 * does not modify the Date instance being called - it creates and returns
1684 * a new Date instance containing the resulting date value.
1689 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1690 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1692 //Negative values will subtract correctly:
1693 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1694 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1696 //You can even chain several calls together in one line!
1697 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1698 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1701 * @param {String} interval A valid date interval enum value
1702 * @param {Number} value The amount to add to the current date
1703 * @return {Date} The new Date instance
1705 Date.prototype.add = function(interval, value){
1706 var d = this.clone();
1707 if (!interval || value === 0) return d;
1708 switch(interval.toLowerCase()){
1710 d.setMilliseconds(this.getMilliseconds() + value);
1713 d.setSeconds(this.getSeconds() + value);
1716 d.setMinutes(this.getMinutes() + value);
1719 d.setHours(this.getHours() + value);
1722 d.setDate(this.getDate() + value);
1725 var day = this.getDate();
1727 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1730 d.setMonth(this.getMonth() + value);
1733 d.setFullYear(this.getFullYear() + value);
1739 * Ext JS Library 1.1.1
1740 * Copyright(c) 2006-2007, Ext JS, LLC.
1742 * Originally Released Under LGPL - original licence link has changed is not relivant.
1745 * <script type="text/javascript">
1749 getViewWidth : function(full) {
1750 return full ? this.getDocumentWidth() : this.getViewportWidth();
1753 getViewHeight : function(full) {
1754 return full ? this.getDocumentHeight() : this.getViewportHeight();
1757 getDocumentHeight: function() {
1758 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1759 return Math.max(scrollHeight, this.getViewportHeight());
1762 getDocumentWidth: function() {
1763 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1764 return Math.max(scrollWidth, this.getViewportWidth());
1767 getViewportHeight: function() {
1768 var height = self.innerHeight;
1769 var mode = document.compatMode;
1771 if ((mode || Roo.isIE) && !Roo.isOpera) {
1772 height = (mode == "CSS1Compat") ?
1773 document.documentElement.clientHeight :
1774 document.body.clientHeight;
1780 getViewportWidth: function() {
1781 var width = self.innerWidth;
1782 var mode = document.compatMode;
1784 if (mode || Roo.isIE) {
1785 width = (mode == "CSS1Compat") ?
1786 document.documentElement.clientWidth :
1787 document.body.clientWidth;
1792 isAncestor : function(p, c) {
1799 if (p.contains && !Roo.isSafari) {
1800 return p.contains(c);
1801 } else if (p.compareDocumentPosition) {
1802 return !!(p.compareDocumentPosition(c) & 16);
1804 var parent = c.parentNode;
1809 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1812 parent = parent.parentNode;
1818 getRegion : function(el) {
1819 return Roo.lib.Region.getRegion(el);
1822 getY : function(el) {
1823 return this.getXY(el)[1];
1826 getX : function(el) {
1827 return this.getXY(el)[0];
1830 getXY : function(el) {
1831 var p, pe, b, scroll, bd = document.body;
1832 el = Roo.getDom(el);
1833 var fly = Roo.lib.AnimBase.fly;
1834 if (el.getBoundingClientRect) {
1835 b = el.getBoundingClientRect();
1836 scroll = fly(document).getScroll();
1837 return [b.left + scroll.left, b.top + scroll.top];
1843 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1850 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1857 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1858 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1865 if (p != el && pe.getStyle('overflow') != 'visible') {
1873 if (Roo.isSafari && hasAbsolute) {
1878 if (Roo.isGecko && !hasAbsolute) {
1880 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1881 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1885 while (p && p != bd) {
1886 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1898 setXY : function(el, xy) {
1899 el = Roo.fly(el, '_setXY');
1901 var pts = el.translatePoints(xy);
1902 if (xy[0] !== false) {
1903 el.dom.style.left = pts.left + "px";
1905 if (xy[1] !== false) {
1906 el.dom.style.top = pts.top + "px";
1910 setX : function(el, x) {
1911 this.setXY(el, [x, false]);
1914 setY : function(el, y) {
1915 this.setXY(el, [false, y]);
1919 * Portions of this file are based on pieces of Yahoo User Interface Library
1920 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1921 * YUI licensed under the BSD License:
1922 * http://developer.yahoo.net/yui/license.txt
1923 * <script type="text/javascript">
1927 Roo.lib.Event = function() {
1928 var loadComplete = false;
1930 var unloadListeners = [];
1932 var onAvailStack = [];
1934 var lastError = null;
1947 startInterval: function() {
1948 if (!this._interval) {
1950 var callback = function() {
1951 self._tryPreloadAttach();
1953 this._interval = setInterval(callback, this.POLL_INTERVAL);
1958 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1959 onAvailStack.push({ id: p_id,
1962 override: p_override,
1963 checkReady: false });
1965 retryCount = this.POLL_RETRYS;
1966 this.startInterval();
1970 addListener: function(el, eventName, fn) {
1971 el = Roo.getDom(el);
1976 if ("unload" == eventName) {
1977 unloadListeners[unloadListeners.length] =
1978 [el, eventName, fn];
1982 var wrappedFn = function(e) {
1983 return fn(Roo.lib.Event.getEvent(e));
1986 var li = [el, eventName, fn, wrappedFn];
1988 var index = listeners.length;
1989 listeners[index] = li;
1991 this.doAdd(el, eventName, wrappedFn, false);
1997 removeListener: function(el, eventName, fn) {
2000 el = Roo.getDom(el);
2003 return this.purgeElement(el, false, eventName);
2007 if ("unload" == eventName) {
2009 for (i = 0,len = unloadListeners.length; i < len; i++) {
2010 var li = unloadListeners[i];
2013 li[1] == eventName &&
2015 unloadListeners.splice(i, 1);
2023 var cacheItem = null;
2026 var index = arguments[3];
2028 if ("undefined" == typeof index) {
2029 index = this._getCacheIndex(el, eventName, fn);
2033 cacheItem = listeners[index];
2036 if (!el || !cacheItem) {
2040 this.doRemove(el, eventName, cacheItem[this.WFN], false);
2042 delete listeners[index][this.WFN];
2043 delete listeners[index][this.FN];
2044 listeners.splice(index, 1);
2051 getTarget: function(ev, resolveTextNode) {
2052 ev = ev.browserEvent || ev;
2053 var t = ev.target || ev.srcElement;
2054 return this.resolveTextNode(t);
2058 resolveTextNode: function(node) {
2059 if (Roo.isSafari && node && 3 == node.nodeType) {
2060 return node.parentNode;
2067 getPageX: function(ev) {
2068 ev = ev.browserEvent || ev;
2070 if (!x && 0 !== x) {
2071 x = ev.clientX || 0;
2074 x += this.getScroll()[1];
2082 getPageY: function(ev) {
2083 ev = ev.browserEvent || ev;
2085 if (!y && 0 !== y) {
2086 y = ev.clientY || 0;
2089 y += this.getScroll()[0];
2098 getXY: function(ev) {
2099 ev = ev.browserEvent || ev;
2100 return [this.getPageX(ev), this.getPageY(ev)];
2104 getRelatedTarget: function(ev) {
2105 ev = ev.browserEvent || ev;
2106 var t = ev.relatedTarget;
2108 if (ev.type == "mouseout") {
2110 } else if (ev.type == "mouseover") {
2115 return this.resolveTextNode(t);
2119 getTime: function(ev) {
2120 ev = ev.browserEvent || ev;
2122 var t = new Date().getTime();
2126 this.lastError = ex;
2135 stopEvent: function(ev) {
2136 this.stopPropagation(ev);
2137 this.preventDefault(ev);
2141 stopPropagation: function(ev) {
2142 ev = ev.browserEvent || ev;
2143 if (ev.stopPropagation) {
2144 ev.stopPropagation();
2146 ev.cancelBubble = true;
2151 preventDefault: function(ev) {
2152 ev = ev.browserEvent || ev;
2153 if(ev.preventDefault) {
2154 ev.preventDefault();
2156 ev.returnValue = false;
2161 getEvent: function(e) {
2162 var ev = e || window.event;
2164 var c = this.getEvent.caller;
2166 ev = c.arguments[0];
2167 if (ev && Event == ev.constructor) {
2177 getCharCode: function(ev) {
2178 ev = ev.browserEvent || ev;
2179 return ev.charCode || ev.keyCode || 0;
2183 _getCacheIndex: function(el, eventName, fn) {
2184 for (var i = 0,len = listeners.length; i < len; ++i) {
2185 var li = listeners[i];
2187 li[this.FN] == fn &&
2188 li[this.EL] == el &&
2189 li[this.TYPE] == eventName) {
2201 getEl: function(id) {
2202 return document.getElementById(id);
2206 clearCache: function() {
2210 _load: function(e) {
2211 loadComplete = true;
2212 var EU = Roo.lib.Event;
2216 EU.doRemove(window, "load", EU._load);
2221 _tryPreloadAttach: function() {
2230 var tryAgain = !loadComplete;
2232 tryAgain = (retryCount > 0);
2237 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2238 var item = onAvailStack[i];
2240 var el = this.getEl(item.id);
2243 if (!item.checkReady ||
2246 (document && document.body)) {
2249 if (item.override) {
2250 if (item.override === true) {
2253 scope = item.override;
2256 item.fn.call(scope, item.obj);
2257 onAvailStack[i] = null;
2260 notAvail.push(item);
2265 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2269 this.startInterval();
2271 clearInterval(this._interval);
2272 this._interval = null;
2275 this.locked = false;
2282 purgeElement: function(el, recurse, eventName) {
2283 var elListeners = this.getListeners(el, eventName);
2285 for (var i = 0,len = elListeners.length; i < len; ++i) {
2286 var l = elListeners[i];
2287 this.removeListener(el, l.type, l.fn);
2291 if (recurse && el && el.childNodes) {
2292 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2293 this.purgeElement(el.childNodes[i], recurse, eventName);
2299 getListeners: function(el, eventName) {
2300 var results = [], searchLists;
2302 searchLists = [listeners, unloadListeners];
2303 } else if (eventName == "unload") {
2304 searchLists = [unloadListeners];
2306 searchLists = [listeners];
2309 for (var j = 0; j < searchLists.length; ++j) {
2310 var searchList = searchLists[j];
2311 if (searchList && searchList.length > 0) {
2312 for (var i = 0,len = searchList.length; i < len; ++i) {
2313 var l = searchList[i];
2314 if (l && l[this.EL] === el &&
2315 (!eventName || eventName === l[this.TYPE])) {
2320 adjust: l[this.ADJ_SCOPE],
2328 return (results.length) ? results : null;
2332 _unload: function(e) {
2334 var EU = Roo.lib.Event, i, j, l, len, index;
2336 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2337 l = unloadListeners[i];
2340 if (l[EU.ADJ_SCOPE]) {
2341 if (l[EU.ADJ_SCOPE] === true) {
2344 scope = l[EU.ADJ_SCOPE];
2347 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2348 unloadListeners[i] = null;
2354 unloadListeners = null;
2356 if (listeners && listeners.length > 0) {
2357 j = listeners.length;
2360 l = listeners[index];
2362 EU.removeListener(l[EU.EL], l[EU.TYPE],
2372 EU.doRemove(window, "unload", EU._unload);
2377 getScroll: function() {
2378 var dd = document.documentElement, db = document.body;
2379 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2380 return [dd.scrollTop, dd.scrollLeft];
2382 return [db.scrollTop, db.scrollLeft];
2389 doAdd: function () {
2390 if (window.addEventListener) {
2391 return function(el, eventName, fn, capture) {
2392 el.addEventListener(eventName, fn, (capture));
2394 } else if (window.attachEvent) {
2395 return function(el, eventName, fn, capture) {
2396 el.attachEvent("on" + eventName, fn);
2405 doRemove: function() {
2406 if (window.removeEventListener) {
2407 return function (el, eventName, fn, capture) {
2408 el.removeEventListener(eventName, fn, (capture));
2410 } else if (window.detachEvent) {
2411 return function (el, eventName, fn) {
2412 el.detachEvent("on" + eventName, fn);
2424 var E = Roo.lib.Event;
2425 E.on = E.addListener;
2426 E.un = E.removeListener;
2428 if (document && document.body) {
2431 E.doAdd(window, "load", E._load);
2433 E.doAdd(window, "unload", E._unload);
2434 E._tryPreloadAttach();
2438 * Portions of this file are based on pieces of Yahoo User Interface Library
2439 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2440 * YUI licensed under the BSD License:
2441 * http://developer.yahoo.net/yui/license.txt
2442 * <script type="text/javascript">
2449 request : function(method, uri, cb, data, options) {
2451 var hs = options.headers;
2454 if(hs.hasOwnProperty(h)){
2455 this.initHeader(h, hs[h], false);
2459 if(options.xmlData){
2460 this.initHeader('Content-Type', 'text/xml', false);
2462 data = options.xmlData;
2466 return this.asyncRequest(method, uri, cb, data);
2469 serializeForm : function(form) {
2470 if(typeof form == 'string') {
2471 form = (document.getElementById(form) || document.forms[form]);
2474 var el, name, val, disabled, data = '', hasSubmit = false;
2475 for (var i = 0; i < form.elements.length; i++) {
2476 el = form.elements[i];
2477 disabled = form.elements[i].disabled;
2478 name = form.elements[i].name;
2479 val = form.elements[i].value;
2481 if (!disabled && name){
2485 case 'select-multiple':
2486 for (var j = 0; j < el.options.length; j++) {
2487 if (el.options[j].selected) {
2489 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2492 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2500 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2513 if(hasSubmit == false) {
2514 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2519 data += Roo.encodeURIComponent(name) + '=' + Roo.encodeURIComponent(val) + '&';
2524 data = data.substr(0, data.length - 1);
2532 useDefaultHeader:true,
2534 defaultPostHeader:'application/x-www-form-urlencoded',
2536 useDefaultXhrHeader:true,
2538 defaultXhrHeader:'XMLHttpRequest',
2540 hasDefaultHeaders:true,
2552 setProgId:function(id)
2554 this.activeX.unshift(id);
2557 setDefaultPostHeader:function(b)
2559 this.useDefaultHeader = b;
2562 setDefaultXhrHeader:function(b)
2564 this.useDefaultXhrHeader = b;
2567 setPollingInterval:function(i)
2569 if (typeof i == 'number' && isFinite(i)) {
2570 this.pollInterval = i;
2574 createXhrObject:function(transactionId)
2580 http = new XMLHttpRequest();
2582 obj = { conn:http, tId:transactionId };
2586 for (var i = 0; i < this.activeX.length; ++i) {
2590 http = new ActiveXObject(this.activeX[i]);
2592 obj = { conn:http, tId:transactionId };
2605 getConnectionObject:function()
2608 var tId = this.transactionId;
2612 o = this.createXhrObject(tId);
2614 this.transactionId++;
2625 asyncRequest:function(method, uri, callback, postData)
2627 var o = this.getConnectionObject();
2633 o.conn.open(method, uri, true);
2635 if (this.useDefaultXhrHeader) {
2636 if (!this.defaultHeaders['X-Requested-With']) {
2637 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2641 if(postData && this.useDefaultHeader){
2642 this.initHeader('Content-Type', this.defaultPostHeader);
2645 if (this.hasDefaultHeaders || this.hasHeaders) {
2649 this.handleReadyState(o, callback);
2650 o.conn.send(postData || null);
2656 handleReadyState:function(o, callback)
2660 if (callback && callback.timeout) {
2661 this.timeout[o.tId] = window.setTimeout(function() {
2662 oConn.abort(o, callback, true);
2663 }, callback.timeout);
2666 this.poll[o.tId] = window.setInterval(
2668 if (o.conn && o.conn.readyState == 4) {
2669 window.clearInterval(oConn.poll[o.tId]);
2670 delete oConn.poll[o.tId];
2672 if(callback && callback.timeout) {
2673 window.clearTimeout(oConn.timeout[o.tId]);
2674 delete oConn.timeout[o.tId];
2677 oConn.handleTransactionResponse(o, callback);
2680 , this.pollInterval);
2683 handleTransactionResponse:function(o, callback, isAbort)
2687 this.releaseObject(o);
2691 var httpStatus, responseObject;
2695 if (o.conn.status !== undefined && o.conn.status != 0) {
2696 httpStatus = o.conn.status;
2708 if (httpStatus >= 200 && httpStatus < 300) {
2709 responseObject = this.createResponseObject(o, callback.argument);
2710 if (callback.success) {
2711 if (!callback.scope) {
2712 callback.success(responseObject);
2717 callback.success.apply(callback.scope, [responseObject]);
2722 switch (httpStatus) {
2730 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2731 if (callback.failure) {
2732 if (!callback.scope) {
2733 callback.failure(responseObject);
2736 callback.failure.apply(callback.scope, [responseObject]);
2741 responseObject = this.createResponseObject(o, callback.argument);
2742 if (callback.failure) {
2743 if (!callback.scope) {
2744 callback.failure(responseObject);
2747 callback.failure.apply(callback.scope, [responseObject]);
2753 this.releaseObject(o);
2754 responseObject = null;
2757 createResponseObject:function(o, callbackArg)
2764 var headerStr = o.conn.getAllResponseHeaders();
2765 var header = headerStr.split('\n');
2766 for (var i = 0; i < header.length; i++) {
2767 var delimitPos = header[i].indexOf(':');
2768 if (delimitPos != -1) {
2769 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2777 obj.status = o.conn.status;
2778 obj.statusText = o.conn.statusText;
2779 obj.getResponseHeader = headerObj;
2780 obj.getAllResponseHeaders = headerStr;
2781 obj.responseText = o.conn.responseText;
2782 obj.responseXML = o.conn.responseXML;
2784 if (typeof callbackArg !== undefined) {
2785 obj.argument = callbackArg;
2791 createExceptionObject:function(tId, callbackArg, isAbort)
2794 var COMM_ERROR = 'communication failure';
2795 var ABORT_CODE = -1;
2796 var ABORT_ERROR = 'transaction aborted';
2802 obj.status = ABORT_CODE;
2803 obj.statusText = ABORT_ERROR;
2806 obj.status = COMM_CODE;
2807 obj.statusText = COMM_ERROR;
2811 obj.argument = callbackArg;
2817 initHeader:function(label, value, isDefault)
2819 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2821 if (headerObj[label] === undefined) {
2822 headerObj[label] = value;
2827 headerObj[label] = value + "," + headerObj[label];
2831 this.hasDefaultHeaders = true;
2834 this.hasHeaders = true;
2839 setHeader:function(o)
2841 if (this.hasDefaultHeaders) {
2842 for (var prop in this.defaultHeaders) {
2843 if (this.defaultHeaders.hasOwnProperty(prop)) {
2844 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2849 if (this.hasHeaders) {
2850 for (var prop in this.headers) {
2851 if (this.headers.hasOwnProperty(prop)) {
2852 o.conn.setRequestHeader(prop, this.headers[prop]);
2856 this.hasHeaders = false;
2860 resetDefaultHeaders:function() {
2861 delete this.defaultHeaders;
2862 this.defaultHeaders = {};
2863 this.hasDefaultHeaders = false;
2866 abort:function(o, callback, isTimeout)
2868 if(this.isCallInProgress(o)) {
2870 window.clearInterval(this.poll[o.tId]);
2871 delete this.poll[o.tId];
2873 delete this.timeout[o.tId];
2876 this.handleTransactionResponse(o, callback, true);
2886 isCallInProgress:function(o)
2889 return o.conn.readyState != 4 && o.conn.readyState != 0;
2898 releaseObject:function(o)
2907 'MSXML2.XMLHTTP.3.0',
2915 * Portions of this file are based on pieces of Yahoo User Interface Library
2916 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2917 * YUI licensed under the BSD License:
2918 * http://developer.yahoo.net/yui/license.txt
2919 * <script type="text/javascript">
2923 Roo.lib.Region = function(t, r, b, l) {
2933 Roo.lib.Region.prototype = {
2934 contains : function(region) {
2935 return ( region.left >= this.left &&
2936 region.right <= this.right &&
2937 region.top >= this.top &&
2938 region.bottom <= this.bottom );
2942 getArea : function() {
2943 return ( (this.bottom - this.top) * (this.right - this.left) );
2946 intersect : function(region) {
2947 var t = Math.max(this.top, region.top);
2948 var r = Math.min(this.right, region.right);
2949 var b = Math.min(this.bottom, region.bottom);
2950 var l = Math.max(this.left, region.left);
2952 if (b >= t && r >= l) {
2953 return new Roo.lib.Region(t, r, b, l);
2958 union : function(region) {
2959 var t = Math.min(this.top, region.top);
2960 var r = Math.max(this.right, region.right);
2961 var b = Math.max(this.bottom, region.bottom);
2962 var l = Math.min(this.left, region.left);
2964 return new Roo.lib.Region(t, r, b, l);
2967 adjust : function(t, l, b, r) {
2976 Roo.lib.Region.getRegion = function(el) {
2977 var p = Roo.lib.Dom.getXY(el);
2980 var r = p[0] + el.offsetWidth;
2981 var b = p[1] + el.offsetHeight;
2984 return new Roo.lib.Region(t, r, b, l);
2987 * Portions of this file are based on pieces of Yahoo User Interface Library
2988 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2989 * YUI licensed under the BSD License:
2990 * http://developer.yahoo.net/yui/license.txt
2991 * <script type="text/javascript">
2994 //@@dep Roo.lib.Region
2997 Roo.lib.Point = function(x, y) {
2998 if (x instanceof Array) {
3002 this.x = this.right = this.left = this[0] = x;
3003 this.y = this.top = this.bottom = this[1] = y;
3006 Roo.lib.Point.prototype = new Roo.lib.Region();
3008 * Portions of this file are based on pieces of Yahoo User Interface Library
3009 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3010 * YUI licensed under the BSD License:
3011 * http://developer.yahoo.net/yui/license.txt
3012 * <script type="text/javascript">
3019 scroll : function(el, args, duration, easing, cb, scope) {
3020 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
3023 motion : function(el, args, duration, easing, cb, scope) {
3024 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
3027 color : function(el, args, duration, easing, cb, scope) {
3028 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
3031 run : function(el, args, duration, easing, cb, scope, type) {
3032 type = type || Roo.lib.AnimBase;
3033 if (typeof easing == "string") {
3034 easing = Roo.lib.Easing[easing];
3036 var anim = new type(el, args, duration, easing);
3037 anim.animateX(function() {
3038 Roo.callback(cb, scope);
3044 * Portions of this file are based on pieces of Yahoo User Interface Library
3045 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3046 * YUI licensed under the BSD License:
3047 * http://developer.yahoo.net/yui/license.txt
3048 * <script type="text/javascript">
3056 if (!libFlyweight) {
3057 libFlyweight = new Roo.Element.Flyweight();
3059 libFlyweight.dom = el;
3060 return libFlyweight;
3063 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3067 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3069 this.init(el, attributes, duration, method);
3073 Roo.lib.AnimBase.fly = fly;
3077 Roo.lib.AnimBase.prototype = {
3079 toString: function() {
3080 var el = this.getEl();
3081 var id = el.id || el.tagName;
3082 return ("Anim " + id);
3086 noNegatives: /width|height|opacity|padding/i,
3087 offsetAttribute: /^((width|height)|(top|left))$/,
3088 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3089 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3093 doMethod: function(attr, start, end) {
3094 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3098 setAttribute: function(attr, val, unit) {
3099 if (this.patterns.noNegatives.test(attr)) {
3100 val = (val > 0) ? val : 0;
3103 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3107 getAttribute: function(attr) {
3108 var el = this.getEl();
3109 var val = fly(el).getStyle(attr);
3111 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3112 return parseFloat(val);
3115 var a = this.patterns.offsetAttribute.exec(attr) || [];
3116 var pos = !!( a[3] );
3117 var box = !!( a[2] );
3120 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3121 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3130 getDefaultUnit: function(attr) {
3131 if (this.patterns.defaultUnit.test(attr)) {
3138 animateX : function(callback, scope) {
3139 var f = function() {
3140 this.onComplete.removeListener(f);
3141 if (typeof callback == "function") {
3142 callback.call(scope || this, this);
3145 this.onComplete.addListener(f, this);
3150 setRuntimeAttribute: function(attr) {
3153 var attributes = this.attributes;
3155 this.runtimeAttributes[attr] = {};
3157 var isset = function(prop) {
3158 return (typeof prop !== 'undefined');
3161 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3165 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3168 if (isset(attributes[attr]['to'])) {
3169 end = attributes[attr]['to'];
3170 } else if (isset(attributes[attr]['by'])) {
3171 if (start.constructor == Array) {
3173 for (var i = 0, len = start.length; i < len; ++i) {
3174 end[i] = start[i] + attributes[attr]['by'][i];
3177 end = start + attributes[attr]['by'];
3181 this.runtimeAttributes[attr].start = start;
3182 this.runtimeAttributes[attr].end = end;
3185 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3189 init: function(el, attributes, duration, method) {
3191 var isAnimated = false;
3194 var startTime = null;
3197 var actualFrames = 0;
3200 el = Roo.getDom(el);
3203 this.attributes = attributes || {};
3206 this.duration = duration || 1;
3209 this.method = method || Roo.lib.Easing.easeNone;
3212 this.useSeconds = true;
3215 this.currentFrame = 0;
3218 this.totalFrames = Roo.lib.AnimMgr.fps;
3221 this.getEl = function() {
3226 this.isAnimated = function() {
3231 this.getStartTime = function() {
3235 this.runtimeAttributes = {};
3238 this.animate = function() {
3239 if (this.isAnimated()) {
3243 this.currentFrame = 0;
3245 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3247 Roo.lib.AnimMgr.registerElement(this);
3251 this.stop = function(finish) {
3253 this.currentFrame = this.totalFrames;
3254 this._onTween.fire();
3256 Roo.lib.AnimMgr.stop(this);
3259 var onStart = function() {
3260 this.onStart.fire();
3262 this.runtimeAttributes = {};
3263 for (var attr in this.attributes) {
3264 this.setRuntimeAttribute(attr);
3269 startTime = new Date();
3273 var onTween = function() {
3275 duration: new Date() - this.getStartTime(),
3276 currentFrame: this.currentFrame
3279 data.toString = function() {
3281 'duration: ' + data.duration +
3282 ', currentFrame: ' + data.currentFrame
3286 this.onTween.fire(data);
3288 var runtimeAttributes = this.runtimeAttributes;
3290 for (var attr in runtimeAttributes) {
3291 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3297 var onComplete = function() {
3298 var actual_duration = (new Date() - startTime) / 1000 ;
3301 duration: actual_duration,
3302 frames: actualFrames,
3303 fps: actualFrames / actual_duration
3306 data.toString = function() {
3308 'duration: ' + data.duration +
3309 ', frames: ' + data.frames +
3310 ', fps: ' + data.fps
3316 this.onComplete.fire(data);
3320 this._onStart = new Roo.util.Event(this);
3321 this.onStart = new Roo.util.Event(this);
3322 this.onTween = new Roo.util.Event(this);
3323 this._onTween = new Roo.util.Event(this);
3324 this.onComplete = new Roo.util.Event(this);
3325 this._onComplete = new Roo.util.Event(this);
3326 this._onStart.addListener(onStart);
3327 this._onTween.addListener(onTween);
3328 this._onComplete.addListener(onComplete);
3333 * Portions of this file are based on pieces of Yahoo User Interface Library
3334 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3335 * YUI licensed under the BSD License:
3336 * http://developer.yahoo.net/yui/license.txt
3337 * <script type="text/javascript">
3341 Roo.lib.AnimMgr = new function() {
3358 this.registerElement = function(tween) {
3359 queue[queue.length] = tween;
3361 tween._onStart.fire();
3366 this.unRegister = function(tween, index) {
3367 tween._onComplete.fire();
3368 index = index || getIndex(tween);
3370 queue.splice(index, 1);
3374 if (tweenCount <= 0) {
3380 this.start = function() {
3381 if (thread === null) {
3382 thread = setInterval(this.run, this.delay);
3387 this.stop = function(tween) {
3389 clearInterval(thread);
3391 for (var i = 0, len = queue.length; i < len; ++i) {
3392 if (queue[0].isAnimated()) {
3393 this.unRegister(queue[0], 0);
3402 this.unRegister(tween);
3407 this.run = function() {
3408 for (var i = 0, len = queue.length; i < len; ++i) {
3409 var tween = queue[i];
3410 if (!tween || !tween.isAnimated()) {
3414 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3416 tween.currentFrame += 1;
3418 if (tween.useSeconds) {
3419 correctFrame(tween);
3421 tween._onTween.fire();
3424 Roo.lib.AnimMgr.stop(tween, i);
3429 var getIndex = function(anim) {
3430 for (var i = 0, len = queue.length; i < len; ++i) {
3431 if (queue[i] == anim) {
3439 var correctFrame = function(tween) {
3440 var frames = tween.totalFrames;
3441 var frame = tween.currentFrame;
3442 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3443 var elapsed = (new Date() - tween.getStartTime());
3446 if (elapsed < tween.duration * 1000) {
3447 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3449 tweak = frames - (frame + 1);
3451 if (tweak > 0 && isFinite(tweak)) {
3452 if (tween.currentFrame + tweak >= frames) {
3453 tweak = frames - (frame + 1);
3456 tween.currentFrame += tweak;
3460 * Portions of this file are based on pieces of Yahoo User Interface Library
3461 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3462 * YUI licensed under the BSD License:
3463 * http://developer.yahoo.net/yui/license.txt
3464 * <script type="text/javascript">
3467 Roo.lib.Bezier = new function() {
3469 this.getPosition = function(points, t) {
3470 var n = points.length;
3473 for (var i = 0; i < n; ++i) {
3474 tmp[i] = [points[i][0], points[i][1]];
3477 for (var j = 1; j < n; ++j) {
3478 for (i = 0; i < n - j; ++i) {
3479 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3480 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3484 return [ tmp[0][0], tmp[0][1] ];
3488 * Portions of this file are based on pieces of Yahoo User Interface Library
3489 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3490 * YUI licensed under the BSD License:
3491 * http://developer.yahoo.net/yui/license.txt
3492 * <script type="text/javascript">
3497 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3498 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3501 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3503 var fly = Roo.lib.AnimBase.fly;
3505 var superclass = Y.ColorAnim.superclass;
3506 var proto = Y.ColorAnim.prototype;
3508 proto.toString = function() {
3509 var el = this.getEl();
3510 var id = el.id || el.tagName;
3511 return ("ColorAnim " + id);
3514 proto.patterns.color = /color$/i;
3515 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3516 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3517 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3518 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3521 proto.parseColor = function(s) {
3522 if (s.length == 3) {
3526 var c = this.patterns.hex.exec(s);
3527 if (c && c.length == 4) {
3528 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3531 c = this.patterns.rgb.exec(s);
3532 if (c && c.length == 4) {
3533 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3536 c = this.patterns.hex3.exec(s);
3537 if (c && c.length == 4) {
3538 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3543 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3544 proto.getAttribute = function(attr) {
3545 var el = this.getEl();
3546 if (this.patterns.color.test(attr)) {
3547 var val = fly(el).getStyle(attr);
3549 if (this.patterns.transparent.test(val)) {
3550 var parent = el.parentNode;
3551 val = fly(parent).getStyle(attr);
3553 while (parent && this.patterns.transparent.test(val)) {
3554 parent = parent.parentNode;
3555 val = fly(parent).getStyle(attr);
3556 if (parent.tagName.toUpperCase() == 'HTML') {
3562 val = superclass.getAttribute.call(this, attr);
3567 proto.getAttribute = function(attr) {
3568 var el = this.getEl();
3569 if (this.patterns.color.test(attr)) {
3570 var val = fly(el).getStyle(attr);
3572 if (this.patterns.transparent.test(val)) {
3573 var parent = el.parentNode;
3574 val = fly(parent).getStyle(attr);
3576 while (parent && this.patterns.transparent.test(val)) {
3577 parent = parent.parentNode;
3578 val = fly(parent).getStyle(attr);
3579 if (parent.tagName.toUpperCase() == 'HTML') {
3585 val = superclass.getAttribute.call(this, attr);
3591 proto.doMethod = function(attr, start, end) {
3594 if (this.patterns.color.test(attr)) {
3596 for (var i = 0, len = start.length; i < len; ++i) {
3597 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3600 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3603 val = superclass.doMethod.call(this, attr, start, end);
3609 proto.setRuntimeAttribute = function(attr) {
3610 superclass.setRuntimeAttribute.call(this, attr);
3612 if (this.patterns.color.test(attr)) {
3613 var attributes = this.attributes;
3614 var start = this.parseColor(this.runtimeAttributes[attr].start);
3615 var end = this.parseColor(this.runtimeAttributes[attr].end);
3617 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3618 end = this.parseColor(attributes[attr].by);
3620 for (var i = 0, len = start.length; i < len; ++i) {
3621 end[i] = start[i] + end[i];
3625 this.runtimeAttributes[attr].start = start;
3626 this.runtimeAttributes[attr].end = end;
3632 * Portions of this file are based on pieces of Yahoo User Interface Library
3633 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3634 * YUI licensed under the BSD License:
3635 * http://developer.yahoo.net/yui/license.txt
3636 * <script type="text/javascript">
3642 easeNone: function (t, b, c, d) {
3643 return c * t / d + b;
3647 easeIn: function (t, b, c, d) {
3648 return c * (t /= d) * t + b;
3652 easeOut: function (t, b, c, d) {
3653 return -c * (t /= d) * (t - 2) + b;
3657 easeBoth: function (t, b, c, d) {
3658 if ((t /= d / 2) < 1) {
3659 return c / 2 * t * t + b;
3662 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3666 easeInStrong: function (t, b, c, d) {
3667 return c * (t /= d) * t * t * t + b;
3671 easeOutStrong: function (t, b, c, d) {
3672 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3676 easeBothStrong: function (t, b, c, d) {
3677 if ((t /= d / 2) < 1) {
3678 return c / 2 * t * t * t * t + b;
3681 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3686 elasticIn: function (t, b, c, d, a, p) {
3690 if ((t /= d) == 1) {
3697 if (!a || a < Math.abs(c)) {
3702 var s = p / (2 * Math.PI) * Math.asin(c / a);
3705 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3709 elasticOut: function (t, b, c, d, a, p) {
3713 if ((t /= d) == 1) {
3720 if (!a || a < Math.abs(c)) {
3725 var s = p / (2 * Math.PI) * Math.asin(c / a);
3728 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3732 elasticBoth: function (t, b, c, d, a, p) {
3737 if ((t /= d / 2) == 2) {
3745 if (!a || a < Math.abs(c)) {
3750 var s = p / (2 * Math.PI) * Math.asin(c / a);
3754 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3755 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3757 return a * Math.pow(2, -10 * (t -= 1)) *
3758 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3763 backIn: function (t, b, c, d, s) {
3764 if (typeof s == 'undefined') {
3767 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3771 backOut: function (t, b, c, d, s) {
3772 if (typeof s == 'undefined') {
3775 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3779 backBoth: function (t, b, c, d, s) {
3780 if (typeof s == 'undefined') {
3784 if ((t /= d / 2 ) < 1) {
3785 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3787 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3791 bounceIn: function (t, b, c, d) {
3792 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3796 bounceOut: function (t, b, c, d) {
3797 if ((t /= d) < (1 / 2.75)) {
3798 return c * (7.5625 * t * t) + b;
3799 } else if (t < (2 / 2.75)) {
3800 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3801 } else if (t < (2.5 / 2.75)) {
3802 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3804 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3808 bounceBoth: function (t, b, c, d) {
3810 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3812 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3815 * Portions of this file are based on pieces of Yahoo User Interface Library
3816 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3817 * YUI licensed under the BSD License:
3818 * http://developer.yahoo.net/yui/license.txt
3819 * <script type="text/javascript">
3823 Roo.lib.Motion = function(el, attributes, duration, method) {
3825 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3829 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3833 var superclass = Y.Motion.superclass;
3834 var proto = Y.Motion.prototype;
3836 proto.toString = function() {
3837 var el = this.getEl();
3838 var id = el.id || el.tagName;
3839 return ("Motion " + id);
3842 proto.patterns.points = /^points$/i;
3844 proto.setAttribute = function(attr, val, unit) {
3845 if (this.patterns.points.test(attr)) {
3846 unit = unit || 'px';
3847 superclass.setAttribute.call(this, 'left', val[0], unit);
3848 superclass.setAttribute.call(this, 'top', val[1], unit);
3850 superclass.setAttribute.call(this, attr, val, unit);
3854 proto.getAttribute = function(attr) {
3855 if (this.patterns.points.test(attr)) {
3857 superclass.getAttribute.call(this, 'left'),
3858 superclass.getAttribute.call(this, 'top')
3861 val = superclass.getAttribute.call(this, attr);
3867 proto.doMethod = function(attr, start, end) {
3870 if (this.patterns.points.test(attr)) {
3871 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3872 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3874 val = superclass.doMethod.call(this, attr, start, end);
3879 proto.setRuntimeAttribute = function(attr) {
3880 if (this.patterns.points.test(attr)) {
3881 var el = this.getEl();
3882 var attributes = this.attributes;
3884 var control = attributes['points']['control'] || [];
3888 if (control.length > 0 && !(control[0] instanceof Array)) {
3889 control = [control];
3892 for (i = 0,len = control.length; i < len; ++i) {
3893 tmp[i] = control[i];
3898 Roo.fly(el).position();
3900 if (isset(attributes['points']['from'])) {
3901 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3904 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3907 start = this.getAttribute('points');
3910 if (isset(attributes['points']['to'])) {
3911 end = translateValues.call(this, attributes['points']['to'], start);
3913 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3914 for (i = 0,len = control.length; i < len; ++i) {
3915 control[i] = translateValues.call(this, control[i], start);
3919 } else if (isset(attributes['points']['by'])) {
3920 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3922 for (i = 0,len = control.length; i < len; ++i) {
3923 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3927 this.runtimeAttributes[attr] = [start];
3929 if (control.length > 0) {
3930 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3933 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3936 superclass.setRuntimeAttribute.call(this, attr);
3940 var translateValues = function(val, start) {
3941 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3942 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3947 var isset = function(prop) {
3948 return (typeof prop !== 'undefined');
3952 * Portions of this file are based on pieces of Yahoo User Interface Library
3953 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3954 * YUI licensed under the BSD License:
3955 * http://developer.yahoo.net/yui/license.txt
3956 * <script type="text/javascript">
3960 Roo.lib.Scroll = function(el, attributes, duration, method) {
3962 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3966 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3970 var superclass = Y.Scroll.superclass;
3971 var proto = Y.Scroll.prototype;
3973 proto.toString = function() {
3974 var el = this.getEl();
3975 var id = el.id || el.tagName;
3976 return ("Scroll " + id);
3979 proto.doMethod = function(attr, start, end) {
3982 if (attr == 'scroll') {
3984 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3985 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3989 val = superclass.doMethod.call(this, attr, start, end);
3994 proto.getAttribute = function(attr) {
3996 var el = this.getEl();
3998 if (attr == 'scroll') {
3999 val = [ el.scrollLeft, el.scrollTop ];
4001 val = superclass.getAttribute.call(this, attr);
4007 proto.setAttribute = function(attr, val, unit) {
4008 var el = this.getEl();
4010 if (attr == 'scroll') {
4011 el.scrollLeft = val[0];
4012 el.scrollTop = val[1];
4014 superclass.setAttribute.call(this, attr, val, unit);
4020 * Ext JS Library 1.1.1
4021 * Copyright(c) 2006-2007, Ext JS, LLC.
4023 * Originally Released Under LGPL - original licence link has changed is not relivant.
4026 * <script type="text/javascript">
4030 // nasty IE9 hack - what a pile of crap that is..
4032 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4033 Range.prototype.createContextualFragment = function (html) {
4034 var doc = window.document;
4035 var container = doc.createElement("div");
4036 container.innerHTML = html;
4037 var frag = doc.createDocumentFragment(), n;
4038 while ((n = container.firstChild)) {
4039 frag.appendChild(n);
4046 * @class Roo.DomHelper
4047 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4048 * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
4051 Roo.DomHelper = function(){
4052 var tempTableEl = null;
4053 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4054 var tableRe = /^table|tbody|tr|td$/i;
4056 // build as innerHTML where available
4058 var createHtml = function(o){
4059 if(typeof o == 'string'){
4068 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4069 if(attr == "style"){
4071 if(typeof s == "function"){
4074 if(typeof s == "string"){
4075 b += ' style="' + s + '"';
4076 }else if(typeof s == "object"){
4079 if(typeof s[key] != "function"){
4080 b += key + ":" + s[key] + ";";
4087 b += ' class="' + o["cls"] + '"';
4088 }else if(attr == "htmlFor"){
4089 b += ' for="' + o["htmlFor"] + '"';
4091 b += " " + attr + '="' + o[attr] + '"';
4095 if(emptyTags.test(o.tag)){
4099 var cn = o.children || o.cn;
4101 //http://bugs.kde.org/show_bug.cgi?id=71506
4102 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4103 for(var i = 0, len = cn.length; i < len; i++) {
4104 b += createHtml(cn[i], b);
4107 b += createHtml(cn, b);
4113 b += "</" + o.tag + ">";
4120 var createDom = function(o, parentNode){
4122 // defininition craeted..
4124 if (o.ns && o.ns != 'html') {
4126 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4127 xmlns[o.ns] = o.xmlns;
4130 if (typeof(xmlns[o.ns]) == 'undefined') {
4131 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4137 if (typeof(o) == 'string') {
4138 return parentNode.appendChild(document.createTextNode(o));
4140 o.tag = o.tag || div;
4141 if (o.ns && Roo.isIE) {
4143 o.tag = o.ns + ':' + o.tag;
4146 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4147 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4150 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4151 attr == "style" || typeof o[attr] == "function") continue;
4153 if(attr=="cls" && Roo.isIE){
4154 el.className = o["cls"];
4156 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4157 else el[attr] = o[attr];
4160 Roo.DomHelper.applyStyles(el, o.style);
4161 var cn = o.children || o.cn;
4163 //http://bugs.kde.org/show_bug.cgi?id=71506
4164 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4165 for(var i = 0, len = cn.length; i < len; i++) {
4166 createDom(cn[i], el);
4173 el.innerHTML = o.html;
4176 parentNode.appendChild(el);
4181 var ieTable = function(depth, s, h, e){
4182 tempTableEl.innerHTML = [s, h, e].join('');
4183 var i = -1, el = tempTableEl;
4190 // kill repeat to save bytes
4194 tbe = '</tbody>'+te,
4200 * Nasty code for IE's broken table implementation
4202 var insertIntoTable = function(tag, where, el, html){
4204 tempTableEl = document.createElement('div');
4209 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4212 if(where == 'beforebegin'){
4216 before = el.nextSibling;
4219 node = ieTable(4, trs, html, tre);
4221 else if(tag == 'tr'){
4222 if(where == 'beforebegin'){
4225 node = ieTable(3, tbs, html, tbe);
4226 } else if(where == 'afterend'){
4227 before = el.nextSibling;
4229 node = ieTable(3, tbs, html, tbe);
4230 } else{ // INTO a TR
4231 if(where == 'afterbegin'){
4232 before = el.firstChild;
4234 node = ieTable(4, trs, html, tre);
4236 } else if(tag == 'tbody'){
4237 if(where == 'beforebegin'){
4240 node = ieTable(2, ts, html, te);
4241 } else if(where == 'afterend'){
4242 before = el.nextSibling;
4244 node = ieTable(2, ts, html, te);
4246 if(where == 'afterbegin'){
4247 before = el.firstChild;
4249 node = ieTable(3, tbs, html, tbe);
4252 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4255 if(where == 'afterbegin'){
4256 before = el.firstChild;
4258 node = ieTable(2, ts, html, te);
4260 el.insertBefore(node, before);
4265 /** True to force the use of DOM instead of html fragments @type Boolean */
4269 * Returns the markup for the passed Element(s) config
4270 * @param {Object} o The Dom object spec (and children)
4273 markup : function(o){
4274 return createHtml(o);
4278 * Applies a style specification to an element
4279 * @param {String/HTMLElement} el The element to apply styles to
4280 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4281 * a function which returns such a specification.
4283 applyStyles : function(el, styles){
4286 if(typeof styles == "string"){
4287 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4289 while ((matches = re.exec(styles)) != null){
4290 el.setStyle(matches[1], matches[2]);
4292 }else if (typeof styles == "object"){
4293 for (var style in styles){
4294 el.setStyle(style, styles[style]);
4296 }else if (typeof styles == "function"){
4297 Roo.DomHelper.applyStyles(el, styles.call());
4303 * Inserts an HTML fragment into the Dom
4304 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4305 * @param {HTMLElement} el The context element
4306 * @param {String} html The HTML fragmenet
4307 * @return {HTMLElement} The new node
4309 insertHtml : function(where, el, html){
4310 where = where.toLowerCase();
4311 if(el.insertAdjacentHTML){
4312 if(tableRe.test(el.tagName)){
4314 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4320 el.insertAdjacentHTML('BeforeBegin', html);
4321 return el.previousSibling;
4323 el.insertAdjacentHTML('AfterBegin', html);
4324 return el.firstChild;
4326 el.insertAdjacentHTML('BeforeEnd', html);
4327 return el.lastChild;
4329 el.insertAdjacentHTML('AfterEnd', html);
4330 return el.nextSibling;
4332 throw 'Illegal insertion point -> "' + where + '"';
4334 var range = el.ownerDocument.createRange();
4338 range.setStartBefore(el);
4339 frag = range.createContextualFragment(html);
4340 el.parentNode.insertBefore(frag, el);
4341 return el.previousSibling;
4344 range.setStartBefore(el.firstChild);
4345 frag = range.createContextualFragment(html);
4346 el.insertBefore(frag, el.firstChild);
4347 return el.firstChild;
4349 el.innerHTML = html;
4350 return el.firstChild;
4354 range.setStartAfter(el.lastChild);
4355 frag = range.createContextualFragment(html);
4356 el.appendChild(frag);
4357 return el.lastChild;
4359 el.innerHTML = html;
4360 return el.lastChild;
4363 range.setStartAfter(el);
4364 frag = range.createContextualFragment(html);
4365 el.parentNode.insertBefore(frag, el.nextSibling);
4366 return el.nextSibling;
4368 throw 'Illegal insertion point -> "' + where + '"';
4372 * Creates new Dom element(s) and inserts them before el
4373 * @param {String/HTMLElement/Element} el The context element
4374 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4375 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4376 * @return {HTMLElement/Roo.Element} The new node
4378 insertBefore : function(el, o, returnElement){
4379 return this.doInsert(el, o, returnElement, "beforeBegin");
4383 * Creates new Dom element(s) and inserts them after el
4384 * @param {String/HTMLElement/Element} el The context element
4385 * @param {Object} o The Dom object spec (and children)
4386 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4387 * @return {HTMLElement/Roo.Element} The new node
4389 insertAfter : function(el, o, returnElement){
4390 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4394 * Creates new Dom element(s) and inserts them as the first child of el
4395 * @param {String/HTMLElement/Element} el The context element
4396 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4397 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4398 * @return {HTMLElement/Roo.Element} The new node
4400 insertFirst : function(el, o, returnElement){
4401 return this.doInsert(el, o, returnElement, "afterBegin");
4405 doInsert : function(el, o, returnElement, pos, sibling){
4406 el = Roo.getDom(el);
4408 if(this.useDom || o.ns){
4409 newNode = createDom(o, null);
4410 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4412 var html = createHtml(o);
4413 newNode = this.insertHtml(pos, el, html);
4415 return returnElement ? Roo.get(newNode, true) : newNode;
4419 * Creates new Dom element(s) and appends them to el
4420 * @param {String/HTMLElement/Element} el The context element
4421 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4422 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4423 * @return {HTMLElement/Roo.Element} The new node
4425 append : function(el, o, returnElement){
4426 el = Roo.getDom(el);
4428 if(this.useDom || o.ns){
4429 newNode = createDom(o, null);
4430 el.appendChild(newNode);
4432 var html = createHtml(o);
4433 newNode = this.insertHtml("beforeEnd", el, html);
4435 return returnElement ? Roo.get(newNode, true) : newNode;
4439 * Creates new Dom element(s) and overwrites the contents of el with them
4440 * @param {String/HTMLElement/Element} el The context element
4441 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4442 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4443 * @return {HTMLElement/Roo.Element} The new node
4445 overwrite : function(el, o, returnElement){
4446 el = Roo.getDom(el);
4449 while (el.childNodes.length) {
4450 el.removeChild(el.firstChild);
4454 el.innerHTML = createHtml(o);
4457 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4461 * Creates a new Roo.DomHelper.Template from the Dom object spec
4462 * @param {Object} o The Dom object spec (and children)
4463 * @return {Roo.DomHelper.Template} The new template
4465 createTemplate : function(o){
4466 var html = createHtml(o);
4467 return new Roo.Template(html);
4473 * Ext JS Library 1.1.1
4474 * Copyright(c) 2006-2007, Ext JS, LLC.
4476 * Originally Released Under LGPL - original licence link has changed is not relivant.
4479 * <script type="text/javascript">
4483 * @class Roo.Template
4484 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4485 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4488 var t = new Roo.Template({
4489 html : '<div name="{id}">' +
4490 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4492 myformat: function (value, allValues) {
4493 return 'XX' + value;
4496 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4498 * For more information see this blog post with examples: <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">DomHelper - Create Elements using DOM, HTML fragments and Templates</a>.
4500 * @param {Object} cfg - Configuration object.
4502 Roo.Template = function(cfg){
4504 if(cfg instanceof Array){
4506 }else if(arguments.length > 1){
4507 cfg = Array.prototype.join.call(arguments, "");
4511 if (typeof(cfg) == 'object') {
4520 Roo.Template.prototype = {
4523 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4527 * Returns an HTML fragment of this template with the specified values applied.
4528 * @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'})
4529 * @return {String} The HTML fragment
4531 applyTemplate : function(values){
4535 return this.compiled(values);
4537 var useF = this.disableFormats !== true;
4538 var fm = Roo.util.Format, tpl = this;
4539 var fn = function(m, name, format, args){
4541 if(format.substr(0, 5) == "this."){
4542 return tpl.call(format.substr(5), values[name], values);
4545 // quoted values are required for strings in compiled templates,
4546 // but for non compiled we need to strip them
4547 // quoted reversed for jsmin
4548 var re = /^\s*['"](.*)["']\s*$/;
4549 args = args.split(',');
4550 for(var i = 0, len = args.length; i < len; i++){
4551 args[i] = args[i].replace(re, "$1");
4553 args = [values[name]].concat(args);
4555 args = [values[name]];
4557 return fm[format].apply(fm, args);
4560 return values[name] !== undefined ? values[name] : "";
4563 return this.html.replace(this.re, fn);
4572 * Sets the HTML used as the template and optionally compiles it.
4573 * @param {String} html
4574 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4575 * @return {Roo.Template} this
4577 set : function(html, compile){
4579 this.compiled = null;
4587 * True to disable format functions (defaults to false)
4590 disableFormats : false,
4593 * The regular expression used to match template variables
4597 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4600 * Compiles the template into an internal function, eliminating the RegEx overhead.
4601 * @return {Roo.Template} this
4603 compile : function(){
4604 var fm = Roo.util.Format;
4605 var useF = this.disableFormats !== true;
4606 var sep = Roo.isGecko ? "+" : ",";
4607 var fn = function(m, name, format, args){
4609 args = args ? ',' + args : "";
4610 if(format.substr(0, 5) != "this."){
4611 format = "fm." + format + '(';
4613 format = 'this.call("'+ format.substr(5) + '", ';
4617 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4619 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4622 // branched to use + in gecko and [].join() in others
4624 body = "this.compiled = function(values){ return '" +
4625 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4628 body = ["this.compiled = function(values){ return ['"];
4629 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4630 body.push("'].join('');};");
4631 body = body.join('');
4641 // private function used to call members
4642 call : function(fnName, value, allValues){
4643 return this[fnName](value, allValues);
4647 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4648 * @param {String/HTMLElement/Roo.Element} el The context element
4649 * @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'})
4650 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4651 * @return {HTMLElement/Roo.Element} The new node or Element
4653 insertFirst: function(el, values, returnElement){
4654 return this.doInsert('afterBegin', el, values, returnElement);
4658 * Applies the supplied values to the template and inserts the new node(s) before el.
4659 * @param {String/HTMLElement/Roo.Element} el The context element
4660 * @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'})
4661 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4662 * @return {HTMLElement/Roo.Element} The new node or Element
4664 insertBefore: function(el, values, returnElement){
4665 return this.doInsert('beforeBegin', el, values, returnElement);
4669 * Applies the supplied values to the template and inserts the new node(s) after el.
4670 * @param {String/HTMLElement/Roo.Element} el The context element
4671 * @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'})
4672 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4673 * @return {HTMLElement/Roo.Element} The new node or Element
4675 insertAfter : function(el, values, returnElement){
4676 return this.doInsert('afterEnd', el, values, returnElement);
4680 * Applies the supplied values to the template and appends the new node(s) to el.
4681 * @param {String/HTMLElement/Roo.Element} el The context element
4682 * @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'})
4683 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4684 * @return {HTMLElement/Roo.Element} The new node or Element
4686 append : function(el, values, returnElement){
4687 return this.doInsert('beforeEnd', el, values, returnElement);
4690 doInsert : function(where, el, values, returnEl){
4691 el = Roo.getDom(el);
4692 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4693 return returnEl ? Roo.get(newNode, true) : newNode;
4697 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4698 * @param {String/HTMLElement/Roo.Element} el The context element
4699 * @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'})
4700 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4701 * @return {HTMLElement/Roo.Element} The new node or Element
4703 overwrite : function(el, values, returnElement){
4704 el = Roo.getDom(el);
4705 el.innerHTML = this.applyTemplate(values);
4706 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4710 * Alias for {@link #applyTemplate}
4713 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4716 Roo.DomHelper.Template = Roo.Template;
4719 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4720 * @param {String/HTMLElement} el A DOM element or its id
4721 * @returns {Roo.Template} The created template
4724 Roo.Template.from = function(el){
4725 el = Roo.getDom(el);
4726 return new Roo.Template(el.value || el.innerHTML);
4729 * Ext JS Library 1.1.1
4730 * Copyright(c) 2006-2007, Ext JS, LLC.
4732 * Originally Released Under LGPL - original licence link has changed is not relivant.
4735 * <script type="text/javascript">
4740 * This is code is also distributed under MIT license for use
4741 * with jQuery and prototype JavaScript libraries.
4744 * @class Roo.DomQuery
4745 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).
4747 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>
4750 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.
4752 <h4>Element Selectors:</h4>
4754 <li> <b>*</b> any element</li>
4755 <li> <b>E</b> an element with the tag E</li>
4756 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4757 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4758 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4759 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4761 <h4>Attribute Selectors:</h4>
4762 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4764 <li> <b>E[foo]</b> has an attribute "foo"</li>
4765 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4766 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4767 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4768 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4769 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4770 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4772 <h4>Pseudo Classes:</h4>
4774 <li> <b>E:first-child</b> E is the first child of its parent</li>
4775 <li> <b>E:last-child</b> E is the last child of its parent</li>
4776 <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>
4777 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4778 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4779 <li> <b>E:only-child</b> E is the only child of its parent</li>
4780 <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>
4781 <li> <b>E:first</b> the first E in the resultset</li>
4782 <li> <b>E:last</b> the last E in the resultset</li>
4783 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4784 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4785 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4786 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4787 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4788 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4789 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4790 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4791 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4793 <h4>CSS Value Selectors:</h4>
4795 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4796 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4797 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4798 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4799 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4800 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4804 Roo.DomQuery = function(){
4805 var cache = {}, simpleCache = {}, valueCache = {};
4806 var nonSpace = /\S/;
4807 var trimRe = /^\s+|\s+$/g;
4808 var tplRe = /\{(\d+)\}/g;
4809 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4810 var tagTokenRe = /^(#)?([\w-\*]+)/;
4811 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4813 function child(p, index){
4815 var n = p.firstChild;
4817 if(n.nodeType == 1){
4828 while((n = n.nextSibling) && n.nodeType != 1);
4833 while((n = n.previousSibling) && n.nodeType != 1);
4837 function children(d){
4838 var n = d.firstChild, ni = -1;
4840 var nx = n.nextSibling;
4841 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4851 function byClassName(c, a, v){
4855 var r = [], ri = -1, cn;
4856 for(var i = 0, ci; ci = c[i]; i++){
4857 if((' '+ci.className+' ').indexOf(v) != -1){
4864 function attrValue(n, attr){
4865 if(!n.tagName && typeof n.length != "undefined"){
4874 if(attr == "class" || attr == "className"){
4877 return n.getAttribute(attr) || n[attr];
4881 function getNodes(ns, mode, tagName){
4882 var result = [], ri = -1, cs;
4886 tagName = tagName || "*";
4887 if(typeof ns.getElementsByTagName != "undefined"){
4891 for(var i = 0, ni; ni = ns[i]; i++){
4892 cs = ni.getElementsByTagName(tagName);
4893 for(var j = 0, ci; ci = cs[j]; j++){
4897 }else if(mode == "/" || mode == ">"){
4898 var utag = tagName.toUpperCase();
4899 for(var i = 0, ni, cn; ni = ns[i]; i++){
4900 cn = ni.children || ni.childNodes;
4901 for(var j = 0, cj; cj = cn[j]; j++){
4902 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4907 }else if(mode == "+"){
4908 var utag = tagName.toUpperCase();
4909 for(var i = 0, n; n = ns[i]; i++){
4910 while((n = n.nextSibling) && n.nodeType != 1);
4911 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4915 }else if(mode == "~"){
4916 for(var i = 0, n; n = ns[i]; i++){
4917 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4926 function concat(a, b){
4930 for(var i = 0, l = b.length; i < l; i++){
4936 function byTag(cs, tagName){
4937 if(cs.tagName || cs == document){
4943 var r = [], ri = -1;
4944 tagName = tagName.toLowerCase();
4945 for(var i = 0, ci; ci = cs[i]; i++){
4946 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4953 function byId(cs, attr, id){
4954 if(cs.tagName || cs == document){
4960 var r = [], ri = -1;
4961 for(var i = 0,ci; ci = cs[i]; i++){
4962 if(ci && ci.id == id){
4970 function byAttribute(cs, attr, value, op, custom){
4971 var r = [], ri = -1, st = custom=="{";
4972 var f = Roo.DomQuery.operators[op];
4973 for(var i = 0, ci; ci = cs[i]; i++){
4976 a = Roo.DomQuery.getStyle(ci, attr);
4978 else if(attr == "class" || attr == "className"){
4980 }else if(attr == "for"){
4982 }else if(attr == "href"){
4983 a = ci.getAttribute("href", 2);
4985 a = ci.getAttribute(attr);
4987 if((f && f(a, value)) || (!f && a)){
4994 function byPseudo(cs, name, value){
4995 return Roo.DomQuery.pseudos[name](cs, value);
4998 // This is for IE MSXML which does not support expandos.
4999 // IE runs the same speed using setAttribute, however FF slows way down
5000 // and Safari completely fails so they need to continue to use expandos.
5001 var isIE = window.ActiveXObject ? true : false;
5003 // this eval is stop the compressor from
5004 // renaming the variable to something shorter
5006 /** eval:var:batch */
5011 function nodupIEXml(cs){
5013 cs[0].setAttribute("_nodup", d);
5015 for(var i = 1, len = cs.length; i < len; i++){
5017 if(!c.getAttribute("_nodup") != d){
5018 c.setAttribute("_nodup", d);
5022 for(var i = 0, len = cs.length; i < len; i++){
5023 cs[i].removeAttribute("_nodup");
5032 var len = cs.length, c, i, r = cs, cj, ri = -1;
5033 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5036 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5037 return nodupIEXml(cs);
5041 for(i = 1; c = cs[i]; i++){
5046 for(var j = 0; j < i; j++){
5049 for(j = i+1; cj = cs[j]; j++){
5061 function quickDiffIEXml(c1, c2){
5063 for(var i = 0, len = c1.length; i < len; i++){
5064 c1[i].setAttribute("_qdiff", d);
5067 for(var i = 0, len = c2.length; i < len; i++){
5068 if(c2[i].getAttribute("_qdiff") != d){
5069 r[r.length] = c2[i];
5072 for(var i = 0, len = c1.length; i < len; i++){
5073 c1[i].removeAttribute("_qdiff");
5078 function quickDiff(c1, c2){
5079 var len1 = c1.length;
5083 if(isIE && c1[0].selectSingleNode){
5084 return quickDiffIEXml(c1, c2);
5087 for(var i = 0; i < len1; i++){
5091 for(var i = 0, len = c2.length; i < len; i++){
5092 if(c2[i]._qdiff != d){
5093 r[r.length] = c2[i];
5099 function quickId(ns, mode, root, id){
5101 var d = root.ownerDocument || root;
5102 return d.getElementById(id);
5104 ns = getNodes(ns, mode, "*");
5105 return byId(ns, null, id);
5109 getStyle : function(el, name){
5110 return Roo.fly(el).getStyle(name);
5113 * Compiles a selector/xpath query into a reusable function. The returned function
5114 * takes one parameter "root" (optional), which is the context node from where the query should start.
5115 * @param {String} selector The selector/xpath query
5116 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5117 * @return {Function}
5119 compile : function(path, type){
5120 type = type || "select";
5122 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5123 var q = path, mode, lq;
5124 var tk = Roo.DomQuery.matchers;
5125 var tklen = tk.length;
5128 // accept leading mode switch
5129 var lmode = q.match(modeRe);
5130 if(lmode && lmode[1]){
5131 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5132 q = q.replace(lmode[1], "");
5134 // strip leading slashes
5135 while(path.substr(0, 1)=="/"){
5136 path = path.substr(1);
5139 while(q && lq != q){
5141 var tm = q.match(tagTokenRe);
5142 if(type == "select"){
5145 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5147 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5149 q = q.replace(tm[0], "");
5150 }else if(q.substr(0, 1) != '@'){
5151 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5156 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5158 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5160 q = q.replace(tm[0], "");
5163 while(!(mm = q.match(modeRe))){
5164 var matched = false;
5165 for(var j = 0; j < tklen; j++){
5167 var m = q.match(t.re);
5169 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5172 q = q.replace(m[0], "");
5177 // prevent infinite loop on bad selector
5179 throw 'Error parsing selector, parsing failed at "' + q + '"';
5183 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5184 q = q.replace(mm[1], "");
5187 fn[fn.length] = "return nodup(n);\n}";
5190 * list of variables that need from compression as they are used by eval.
5200 * eval:var:byClassName
5202 * eval:var:byAttribute
5203 * eval:var:attrValue
5211 * Selects a group of elements.
5212 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5213 * @param {Node} root (optional) The start of the query (defaults to document).
5216 select : function(path, root, type){
5217 if(!root || root == document){
5220 if(typeof root == "string"){
5221 root = document.getElementById(root);
5223 var paths = path.split(",");
5225 for(var i = 0, len = paths.length; i < len; i++){
5226 var p = paths[i].replace(trimRe, "");
5228 cache[p] = Roo.DomQuery.compile(p);
5230 throw p + " is not a valid selector";
5233 var result = cache[p](root);
5234 if(result && result != document){
5235 results = results.concat(result);
5238 if(paths.length > 1){
5239 return nodup(results);
5245 * Selects a single element.
5246 * @param {String} selector The selector/xpath query
5247 * @param {Node} root (optional) The start of the query (defaults to document).
5250 selectNode : function(path, root){
5251 return Roo.DomQuery.select(path, root)[0];
5255 * Selects the value of a node, optionally replacing null with the defaultValue.
5256 * @param {String} selector The selector/xpath query
5257 * @param {Node} root (optional) The start of the query (defaults to document).
5258 * @param {String} defaultValue
5260 selectValue : function(path, root, defaultValue){
5261 path = path.replace(trimRe, "");
5262 if(!valueCache[path]){
5263 valueCache[path] = Roo.DomQuery.compile(path, "select");
5265 var n = valueCache[path](root);
5266 n = n[0] ? n[0] : n;
5267 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5268 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5272 * Selects the value of a node, parsing integers and floats.
5273 * @param {String} selector The selector/xpath query
5274 * @param {Node} root (optional) The start of the query (defaults to document).
5275 * @param {Number} defaultValue
5278 selectNumber : function(path, root, defaultValue){
5279 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5280 return parseFloat(v);
5284 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5285 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5286 * @param {String} selector The simple selector to test
5289 is : function(el, ss){
5290 if(typeof el == "string"){
5291 el = document.getElementById(el);
5293 var isArray = (el instanceof Array);
5294 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5295 return isArray ? (result.length == el.length) : (result.length > 0);
5299 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5300 * @param {Array} el An array of elements to filter
5301 * @param {String} selector The simple selector to test
5302 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5303 * the selector instead of the ones that match
5306 filter : function(els, ss, nonMatches){
5307 ss = ss.replace(trimRe, "");
5308 if(!simpleCache[ss]){
5309 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5311 var result = simpleCache[ss](els);
5312 return nonMatches ? quickDiff(result, els) : result;
5316 * Collection of matching regular expressions and code snippets.
5320 select: 'n = byClassName(n, null, " {1} ");'
5322 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5323 select: 'n = byPseudo(n, "{1}", "{2}");'
5325 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5326 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5329 select: 'n = byId(n, null, "{1}");'
5332 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5337 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5338 * 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, > <.
5341 "=" : function(a, v){
5344 "!=" : function(a, v){
5347 "^=" : function(a, v){
5348 return a && a.substr(0, v.length) == v;
5350 "$=" : function(a, v){
5351 return a && a.substr(a.length-v.length) == v;
5353 "*=" : function(a, v){
5354 return a && a.indexOf(v) !== -1;
5356 "%=" : function(a, v){
5357 return (a % v) == 0;
5359 "|=" : function(a, v){
5360 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5362 "~=" : function(a, v){
5363 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5368 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5369 * and the argument (if any) supplied in the selector.
5372 "first-child" : function(c){
5373 var r = [], ri = -1, n;
5374 for(var i = 0, ci; ci = n = c[i]; i++){
5375 while((n = n.previousSibling) && n.nodeType != 1);
5383 "last-child" : function(c){
5384 var r = [], ri = -1, n;
5385 for(var i = 0, ci; ci = n = c[i]; i++){
5386 while((n = n.nextSibling) && n.nodeType != 1);
5394 "nth-child" : function(c, a) {
5395 var r = [], ri = -1;
5396 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5397 var f = (m[1] || 1) - 0, l = m[2] - 0;
5398 for(var i = 0, n; n = c[i]; i++){
5399 var pn = n.parentNode;
5400 if (batch != pn._batch) {
5402 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5403 if(cn.nodeType == 1){
5410 if (l == 0 || n.nodeIndex == l){
5413 } else if ((n.nodeIndex + l) % f == 0){
5421 "only-child" : function(c){
5422 var r = [], ri = -1;;
5423 for(var i = 0, ci; ci = c[i]; i++){
5424 if(!prev(ci) && !next(ci)){
5431 "empty" : function(c){
5432 var r = [], ri = -1;
5433 for(var i = 0, ci; ci = c[i]; i++){
5434 var cns = ci.childNodes, j = 0, cn, empty = true;
5437 if(cn.nodeType == 1 || cn.nodeType == 3){
5449 "contains" : function(c, v){
5450 var r = [], ri = -1;
5451 for(var i = 0, ci; ci = c[i]; i++){
5452 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5459 "nodeValue" : function(c, v){
5460 var r = [], ri = -1;
5461 for(var i = 0, ci; ci = c[i]; i++){
5462 if(ci.firstChild && ci.firstChild.nodeValue == v){
5469 "checked" : function(c){
5470 var r = [], ri = -1;
5471 for(var i = 0, ci; ci = c[i]; i++){
5472 if(ci.checked == true){
5479 "not" : function(c, ss){
5480 return Roo.DomQuery.filter(c, ss, true);
5483 "odd" : function(c){
5484 return this["nth-child"](c, "odd");
5487 "even" : function(c){
5488 return this["nth-child"](c, "even");
5491 "nth" : function(c, a){
5492 return c[a-1] || [];
5495 "first" : function(c){
5499 "last" : function(c){
5500 return c[c.length-1] || [];
5503 "has" : function(c, ss){
5504 var s = Roo.DomQuery.select;
5505 var r = [], ri = -1;
5506 for(var i = 0, ci; ci = c[i]; i++){
5507 if(s(ss, ci).length > 0){
5514 "next" : function(c, ss){
5515 var is = Roo.DomQuery.is;
5516 var r = [], ri = -1;
5517 for(var i = 0, ci; ci = c[i]; i++){
5526 "prev" : function(c, ss){
5527 var is = Roo.DomQuery.is;
5528 var r = [], ri = -1;
5529 for(var i = 0, ci; ci = c[i]; i++){
5542 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5543 * @param {String} path The selector/xpath query
5544 * @param {Node} root (optional) The start of the query (defaults to document).
5549 Roo.query = Roo.DomQuery.select;
5552 * Ext JS Library 1.1.1
5553 * Copyright(c) 2006-2007, Ext JS, LLC.
5555 * Originally Released Under LGPL - original licence link has changed is not relivant.
5558 * <script type="text/javascript">
5562 * @class Roo.util.Observable
5563 * Base class that provides a common interface for publishing events. Subclasses are expected to
5564 * to have a property "events" with all the events defined.<br>
5567 Employee = function(name){
5574 Roo.extend(Employee, Roo.util.Observable);
5576 * @param {Object} config properties to use (incuding events / listeners)
5579 Roo.util.Observable = function(cfg){
5582 this.addEvents(cfg.events || {});
5584 delete cfg.events; // make sure
5587 Roo.apply(this, cfg);
5590 this.on(this.listeners);
5591 delete this.listeners;
5594 Roo.util.Observable.prototype = {
5596 * @cfg {Object} listeners list of events and functions to call for this object,
5600 'click' : function(e) {
5610 * Fires the specified event with the passed parameters (minus the event name).
5611 * @param {String} eventName
5612 * @param {Object...} args Variable number of parameters are passed to handlers
5613 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5615 fireEvent : function(){
5616 var ce = this.events[arguments[0].toLowerCase()];
5617 if(typeof ce == "object"){
5618 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5625 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5628 * Appends an event handler to this component
5629 * @param {String} eventName The type of event to listen for
5630 * @param {Function} handler The method the event invokes
5631 * @param {Object} scope (optional) The scope in which to execute the handler
5632 * function. The handler function's "this" context.
5633 * @param {Object} options (optional) An object containing handler configuration
5634 * properties. This may contain any of the following properties:<ul>
5635 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5636 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5637 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5638 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5639 * by the specified number of milliseconds. If the event fires again within that time, the original
5640 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5643 * <b>Combining Options</b><br>
5644 * Using the options argument, it is possible to combine different types of listeners:<br>
5646 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5648 el.on('click', this.onClick, this, {
5655 * <b>Attaching multiple handlers in 1 call</b><br>
5656 * The method also allows for a single argument to be passed which is a config object containing properties
5657 * which specify multiple handlers.
5666 fn: this.onMouseOver,
5670 fn: this.onMouseOut,
5676 * Or a shorthand syntax which passes the same scope object to all handlers:
5679 'click': this.onClick,
5680 'mouseover': this.onMouseOver,
5681 'mouseout': this.onMouseOut,
5686 addListener : function(eventName, fn, scope, o){
5687 if(typeof eventName == "object"){
5690 if(this.filterOptRe.test(e)){
5693 if(typeof o[e] == "function"){
5695 this.addListener(e, o[e], o.scope, o);
5697 // individual options
5698 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5703 o = (!o || typeof o == "boolean") ? {} : o;
5704 eventName = eventName.toLowerCase();
5705 var ce = this.events[eventName] || true;
5706 if(typeof ce == "boolean"){
5707 ce = new Roo.util.Event(this, eventName);
5708 this.events[eventName] = ce;
5710 ce.addListener(fn, scope, o);
5714 * Removes a listener
5715 * @param {String} eventName The type of event to listen for
5716 * @param {Function} handler The handler to remove
5717 * @param {Object} scope (optional) The scope (this object) for the handler
5719 removeListener : function(eventName, fn, scope){
5720 var ce = this.events[eventName.toLowerCase()];
5721 if(typeof ce == "object"){
5722 ce.removeListener(fn, scope);
5727 * Removes all listeners for this object
5729 purgeListeners : function(){
5730 for(var evt in this.events){
5731 if(typeof this.events[evt] == "object"){
5732 this.events[evt].clearListeners();
5737 relayEvents : function(o, events){
5738 var createHandler = function(ename){
5740 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5743 for(var i = 0, len = events.length; i < len; i++){
5744 var ename = events[i];
5745 if(!this.events[ename]){ this.events[ename] = true; };
5746 o.on(ename, createHandler(ename), this);
5751 * Used to define events on this Observable
5752 * @param {Object} object The object with the events defined
5754 addEvents : function(o){
5758 Roo.applyIf(this.events, o);
5762 * Checks to see if this object has any listeners for a specified event
5763 * @param {String} eventName The name of the event to check for
5764 * @return {Boolean} True if the event is being listened for, else false
5766 hasListener : function(eventName){
5767 var e = this.events[eventName];
5768 return typeof e == "object" && e.listeners.length > 0;
5772 * Appends an event handler to this element (shorthand for addListener)
5773 * @param {String} eventName The type of event to listen for
5774 * @param {Function} handler The method the event invokes
5775 * @param {Object} scope (optional) The scope in which to execute the handler
5776 * function. The handler function's "this" context.
5777 * @param {Object} options (optional)
5780 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5782 * Removes a listener (shorthand for removeListener)
5783 * @param {String} eventName The type of event to listen for
5784 * @param {Function} handler The handler to remove
5785 * @param {Object} scope (optional) The scope (this object) for the handler
5788 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5791 * Starts capture on the specified Observable. All events will be passed
5792 * to the supplied function with the event name + standard signature of the event
5793 * <b>before</b> the event is fired. If the supplied function returns false,
5794 * the event will not fire.
5795 * @param {Observable} o The Observable to capture
5796 * @param {Function} fn The function to call
5797 * @param {Object} scope (optional) The scope (this object) for the fn
5800 Roo.util.Observable.capture = function(o, fn, scope){
5801 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5805 * Removes <b>all</b> added captures from the Observable.
5806 * @param {Observable} o The Observable to release
5809 Roo.util.Observable.releaseCapture = function(o){
5810 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5815 var createBuffered = function(h, o, scope){
5816 var task = new Roo.util.DelayedTask();
5818 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5822 var createSingle = function(h, e, fn, scope){
5824 e.removeListener(fn, scope);
5825 return h.apply(scope, arguments);
5829 var createDelayed = function(h, o, scope){
5831 var args = Array.prototype.slice.call(arguments, 0);
5832 setTimeout(function(){
5833 h.apply(scope, args);
5838 Roo.util.Event = function(obj, name){
5841 this.listeners = [];
5844 Roo.util.Event.prototype = {
5845 addListener : function(fn, scope, options){
5846 var o = options || {};
5847 scope = scope || this.obj;
5848 if(!this.isListening(fn, scope)){
5849 var l = {fn: fn, scope: scope, options: o};
5852 h = createDelayed(h, o, scope);
5855 h = createSingle(h, this, fn, scope);
5858 h = createBuffered(h, o, scope);
5861 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5862 this.listeners.push(l);
5864 this.listeners = this.listeners.slice(0);
5865 this.listeners.push(l);
5870 findListener : function(fn, scope){
5871 scope = scope || this.obj;
5872 var ls = this.listeners;
5873 for(var i = 0, len = ls.length; i < len; i++){
5875 if(l.fn == fn && l.scope == scope){
5882 isListening : function(fn, scope){
5883 return this.findListener(fn, scope) != -1;
5886 removeListener : function(fn, scope){
5888 if((index = this.findListener(fn, scope)) != -1){
5890 this.listeners.splice(index, 1);
5892 this.listeners = this.listeners.slice(0);
5893 this.listeners.splice(index, 1);
5900 clearListeners : function(){
5901 this.listeners = [];
5905 var ls = this.listeners, scope, len = ls.length;
5908 var args = Array.prototype.slice.call(arguments, 0);
5909 for(var i = 0; i < len; i++){
5911 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5912 this.firing = false;
5916 this.firing = false;
5923 * Ext JS Library 1.1.1
5924 * Copyright(c) 2006-2007, Ext JS, LLC.
5926 * Originally Released Under LGPL - original licence link has changed is not relivant.
5929 * <script type="text/javascript">
5933 * @class Roo.EventManager
5934 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5935 * several useful events directly.
5936 * See {@link Roo.EventObject} for more details on normalized event objects.
5939 Roo.EventManager = function(){
5940 var docReadyEvent, docReadyProcId, docReadyState = false;
5941 var resizeEvent, resizeTask, textEvent, textSize;
5942 var E = Roo.lib.Event;
5943 var D = Roo.lib.Dom;
5946 var fireDocReady = function(){
5948 docReadyState = true;
5951 clearInterval(docReadyProcId);
5953 if(Roo.isGecko || Roo.isOpera) {
5954 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5957 var defer = document.getElementById("ie-deferred-loader");
5959 defer.onreadystatechange = null;
5960 defer.parentNode.removeChild(defer);
5964 docReadyEvent.fire();
5965 docReadyEvent.clearListeners();
5970 var initDocReady = function(){
5971 docReadyEvent = new Roo.util.Event();
5972 if(Roo.isGecko || Roo.isOpera) {
5973 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5975 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5976 var defer = document.getElementById("ie-deferred-loader");
5977 defer.onreadystatechange = function(){
5978 if(this.readyState == "complete"){
5982 }else if(Roo.isSafari){
5983 docReadyProcId = setInterval(function(){
5984 var rs = document.readyState;
5985 if(rs == "complete") {
5990 // no matter what, make sure it fires on load
5991 E.on(window, "load", fireDocReady);
5994 var createBuffered = function(h, o){
5995 var task = new Roo.util.DelayedTask(h);
5997 // create new event object impl so new events don't wipe out properties
5998 e = new Roo.EventObjectImpl(e);
5999 task.delay(o.buffer, h, null, [e]);
6003 var createSingle = function(h, el, ename, fn){
6005 Roo.EventManager.removeListener(el, ename, fn);
6010 var createDelayed = function(h, o){
6012 // create new event object impl so new events don't wipe out properties
6013 e = new Roo.EventObjectImpl(e);
6014 setTimeout(function(){
6020 var listen = function(element, ename, opt, fn, scope){
6021 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6022 fn = fn || o.fn; scope = scope || o.scope;
6023 var el = Roo.getDom(element);
6025 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6027 var h = function(e){
6028 e = Roo.EventObject.setEvent(e);
6031 t = e.getTarget(o.delegate, el);
6038 if(o.stopEvent === true){
6041 if(o.preventDefault === true){
6044 if(o.stopPropagation === true){
6045 e.stopPropagation();
6048 if(o.normalized === false){
6052 fn.call(scope || el, e, t, o);
6055 h = createDelayed(h, o);
6058 h = createSingle(h, el, ename, fn);
6061 h = createBuffered(h, o);
6063 fn._handlers = fn._handlers || [];
6064 fn._handlers.push([Roo.id(el), ename, h]);
6067 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6068 el.addEventListener("DOMMouseScroll", h, false);
6069 E.on(window, 'unload', function(){
6070 el.removeEventListener("DOMMouseScroll", h, false);
6073 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6074 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6079 var stopListening = function(el, ename, fn){
6080 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6082 for(var i = 0, len = hds.length; i < len; i++){
6084 if(h[0] == id && h[1] == ename){
6091 E.un(el, ename, hd);
6092 el = Roo.getDom(el);
6093 if(ename == "mousewheel" && el.addEventListener){
6094 el.removeEventListener("DOMMouseScroll", hd, false);
6096 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6097 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6101 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6108 * @scope Roo.EventManager
6113 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6114 * object with a Roo.EventObject
6115 * @param {Function} fn The method the event invokes
6116 * @param {Object} scope An object that becomes the scope of the handler
6117 * @param {boolean} override If true, the obj passed in becomes
6118 * the execution scope of the listener
6119 * @return {Function} The wrapped function
6122 wrap : function(fn, scope, override){
6124 Roo.EventObject.setEvent(e);
6125 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6130 * Appends an event handler to an element (shorthand for addListener)
6131 * @param {String/HTMLElement} element The html element or id to assign the
6132 * @param {String} eventName The type of event to listen for
6133 * @param {Function} handler The method the event invokes
6134 * @param {Object} scope (optional) The scope in which to execute the handler
6135 * function. The handler function's "this" context.
6136 * @param {Object} options (optional) An object containing handler configuration
6137 * properties. This may contain any of the following properties:<ul>
6138 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6139 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6140 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6141 * <li>preventDefault {Boolean} True to prevent the default action</li>
6142 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6143 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6144 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6145 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6146 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6147 * by the specified number of milliseconds. If the event fires again within that time, the original
6148 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6151 * <b>Combining Options</b><br>
6152 * Using the options argument, it is possible to combine different types of listeners:<br>
6154 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6156 el.on('click', this.onClick, this, {
6163 * <b>Attaching multiple handlers in 1 call</b><br>
6164 * The method also allows for a single argument to be passed which is a config object containing properties
6165 * which specify multiple handlers.
6175 fn: this.onMouseOver
6184 * Or a shorthand syntax:<br>
6187 'click' : this.onClick,
6188 'mouseover' : this.onMouseOver,
6189 'mouseout' : this.onMouseOut
6193 addListener : function(element, eventName, fn, scope, options){
6194 if(typeof eventName == "object"){
6200 if(typeof o[e] == "function"){
6202 listen(element, e, o, o[e], o.scope);
6204 // individual options
6205 listen(element, e, o[e]);
6210 return listen(element, eventName, options, fn, scope);
6214 * Removes an event handler
6216 * @param {String/HTMLElement} element The id or html element to remove the
6218 * @param {String} eventName The type of event
6219 * @param {Function} fn
6220 * @return {Boolean} True if a listener was actually removed
6222 removeListener : function(element, eventName, fn){
6223 return stopListening(element, eventName, fn);
6227 * Fires when the document is ready (before onload and before images are loaded). Can be
6228 * accessed shorthanded Roo.onReady().
6229 * @param {Function} fn The method the event invokes
6230 * @param {Object} scope An object that becomes the scope of the handler
6231 * @param {boolean} options
6233 onDocumentReady : function(fn, scope, options){
6234 if(docReadyState){ // if it already fired
6235 docReadyEvent.addListener(fn, scope, options);
6236 docReadyEvent.fire();
6237 docReadyEvent.clearListeners();
6243 docReadyEvent.addListener(fn, scope, options);
6247 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6248 * @param {Function} fn The method the event invokes
6249 * @param {Object} scope An object that becomes the scope of the handler
6250 * @param {boolean} options
6252 onWindowResize : function(fn, scope, options){
6254 resizeEvent = new Roo.util.Event();
6255 resizeTask = new Roo.util.DelayedTask(function(){
6256 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6258 E.on(window, "resize", function(){
6260 resizeTask.delay(50);
6262 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6266 resizeEvent.addListener(fn, scope, options);
6270 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6271 * @param {Function} fn The method the event invokes
6272 * @param {Object} scope An object that becomes the scope of the handler
6273 * @param {boolean} options
6275 onTextResize : function(fn, scope, options){
6277 textEvent = new Roo.util.Event();
6278 var textEl = new Roo.Element(document.createElement('div'));
6279 textEl.dom.className = 'x-text-resize';
6280 textEl.dom.innerHTML = 'X';
6281 textEl.appendTo(document.body);
6282 textSize = textEl.dom.offsetHeight;
6283 setInterval(function(){
6284 if(textEl.dom.offsetHeight != textSize){
6285 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6287 }, this.textResizeInterval);
6289 textEvent.addListener(fn, scope, options);
6293 * Removes the passed window resize listener.
6294 * @param {Function} fn The method the event invokes
6295 * @param {Object} scope The scope of handler
6297 removeResizeListener : function(fn, scope){
6299 resizeEvent.removeListener(fn, scope);
6304 fireResize : function(){
6306 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6310 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6314 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6316 textResizeInterval : 50
6321 * @scopeAlias pub=Roo.EventManager
6325 * Appends an event handler to an element (shorthand for addListener)
6326 * @param {String/HTMLElement} element The html element or id to assign the
6327 * @param {String} eventName The type of event to listen for
6328 * @param {Function} handler The method the event invokes
6329 * @param {Object} scope (optional) The scope in which to execute the handler
6330 * function. The handler function's "this" context.
6331 * @param {Object} options (optional) An object containing handler configuration
6332 * properties. This may contain any of the following properties:<ul>
6333 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6334 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6335 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6336 * <li>preventDefault {Boolean} True to prevent the default action</li>
6337 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6338 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6339 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6340 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6341 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6342 * by the specified number of milliseconds. If the event fires again within that time, the original
6343 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6346 * <b>Combining Options</b><br>
6347 * Using the options argument, it is possible to combine different types of listeners:<br>
6349 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6351 el.on('click', this.onClick, this, {
6358 * <b>Attaching multiple handlers in 1 call</b><br>
6359 * The method also allows for a single argument to be passed which is a config object containing properties
6360 * which specify multiple handlers.
6370 fn: this.onMouseOver
6379 * Or a shorthand syntax:<br>
6382 'click' : this.onClick,
6383 'mouseover' : this.onMouseOver,
6384 'mouseout' : this.onMouseOut
6388 pub.on = pub.addListener;
6389 pub.un = pub.removeListener;
6391 pub.stoppedMouseDownEvent = new Roo.util.Event();
6395 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6396 * @param {Function} fn The method the event invokes
6397 * @param {Object} scope An object that becomes the scope of the handler
6398 * @param {boolean} override If true, the obj passed in becomes
6399 * the execution scope of the listener
6403 Roo.onReady = Roo.EventManager.onDocumentReady;
6405 Roo.onReady(function(){
6406 var bd = Roo.get(document.body);
6411 : Roo.isGecko ? "roo-gecko"
6412 : Roo.isOpera ? "roo-opera"
6413 : Roo.isSafari ? "roo-safari" : ""];
6416 cls.push("roo-mac");
6419 cls.push("roo-linux");
6421 if(Roo.isBorderBox){
6422 cls.push('roo-border-box');
6424 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6425 var p = bd.dom.parentNode;
6427 p.className += ' roo-strict';
6430 bd.addClass(cls.join(' '));
6434 * @class Roo.EventObject
6435 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6436 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6439 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6441 var target = e.getTarget();
6444 var myDiv = Roo.get("myDiv");
6445 myDiv.on("click", handleClick);
6447 Roo.EventManager.on("myDiv", 'click', handleClick);
6448 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6452 Roo.EventObject = function(){
6454 var E = Roo.lib.Event;
6456 // safari keypress events for special keys return bad keycodes
6459 63235 : 39, // right
6462 63276 : 33, // page up
6463 63277 : 34, // page down
6464 63272 : 46, // delete
6469 // normalize button clicks
6470 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6471 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6473 Roo.EventObjectImpl = function(e){
6475 this.setEvent(e.browserEvent || e);
6478 Roo.EventObjectImpl.prototype = {
6480 * Used to fix doc tools.
6481 * @scope Roo.EventObject.prototype
6487 /** The normal browser event */
6488 browserEvent : null,
6489 /** The button pressed in a mouse event */
6491 /** True if the shift key was down during the event */
6493 /** True if the control key was down during the event */
6495 /** True if the alt key was down during the event */
6554 setEvent : function(e){
6555 if(e == this || (e && e.browserEvent)){ // already wrapped
6558 this.browserEvent = e;
6560 // normalize buttons
6561 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6562 if(e.type == 'click' && this.button == -1){
6566 this.shiftKey = e.shiftKey;
6567 // mac metaKey behaves like ctrlKey
6568 this.ctrlKey = e.ctrlKey || e.metaKey;
6569 this.altKey = e.altKey;
6570 // in getKey these will be normalized for the mac
6571 this.keyCode = e.keyCode;
6572 // keyup warnings on firefox.
6573 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6574 // cache the target for the delayed and or buffered events
6575 this.target = E.getTarget(e);
6577 this.xy = E.getXY(e);
6580 this.shiftKey = false;
6581 this.ctrlKey = false;
6582 this.altKey = false;
6592 * Stop the event (preventDefault and stopPropagation)
6594 stopEvent : function(){
6595 if(this.browserEvent){
6596 if(this.browserEvent.type == 'mousedown'){
6597 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6599 E.stopEvent(this.browserEvent);
6604 * Prevents the browsers default handling of the event.
6606 preventDefault : function(){
6607 if(this.browserEvent){
6608 E.preventDefault(this.browserEvent);
6613 isNavKeyPress : function(){
6614 var k = this.keyCode;
6615 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6616 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6619 isSpecialKey : function(){
6620 var k = this.keyCode;
6621 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6622 (k == 16) || (k == 17) ||
6623 (k >= 18 && k <= 20) ||
6624 (k >= 33 && k <= 35) ||
6625 (k >= 36 && k <= 39) ||
6626 (k >= 44 && k <= 45);
6629 * Cancels bubbling of the event.
6631 stopPropagation : function(){
6632 if(this.browserEvent){
6633 if(this.type == 'mousedown'){
6634 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6636 E.stopPropagation(this.browserEvent);
6641 * Gets the key code for the event.
6644 getCharCode : function(){
6645 return this.charCode || this.keyCode;
6649 * Returns a normalized keyCode for the event.
6650 * @return {Number} The key code
6652 getKey : function(){
6653 var k = this.keyCode || this.charCode;
6654 return Roo.isSafari ? (safariKeys[k] || k) : k;
6658 * Gets the x coordinate of the event.
6661 getPageX : function(){
6666 * Gets the y coordinate of the event.
6669 getPageY : function(){
6674 * Gets the time of the event.
6677 getTime : function(){
6678 if(this.browserEvent){
6679 return E.getTime(this.browserEvent);
6685 * Gets the page coordinates of the event.
6686 * @return {Array} The xy values like [x, y]
6693 * Gets the target for the event.
6694 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6695 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6696 search as a number or element (defaults to 10 || document.body)
6697 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6698 * @return {HTMLelement}
6700 getTarget : function(selector, maxDepth, returnEl){
6701 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6704 * Gets the related target.
6705 * @return {HTMLElement}
6707 getRelatedTarget : function(){
6708 if(this.browserEvent){
6709 return E.getRelatedTarget(this.browserEvent);
6715 * Normalizes mouse wheel delta across browsers
6716 * @return {Number} The delta
6718 getWheelDelta : function(){
6719 var e = this.browserEvent;
6721 if(e.wheelDelta){ /* IE/Opera. */
6722 delta = e.wheelDelta/120;
6723 }else if(e.detail){ /* Mozilla case. */
6724 delta = -e.detail/3;
6730 * Returns true if the control, meta, shift or alt key was pressed during this event.
6733 hasModifier : function(){
6734 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6738 * Returns true if the target of this event equals el or is a child of el
6739 * @param {String/HTMLElement/Element} el
6740 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6743 within : function(el, related){
6744 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6745 return t && Roo.fly(el).contains(t);
6748 getPoint : function(){
6749 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6753 return new Roo.EventObjectImpl();
6758 * Ext JS Library 1.1.1
6759 * Copyright(c) 2006-2007, Ext JS, LLC.
6761 * Originally Released Under LGPL - original licence link has changed is not relivant.
6764 * <script type="text/javascript">
6768 // was in Composite Element!??!?!
6771 var D = Roo.lib.Dom;
6772 var E = Roo.lib.Event;
6773 var A = Roo.lib.Anim;
6775 // local style camelizing for speed
6777 var camelRe = /(-[a-z])/gi;
6778 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6779 var view = document.defaultView;
6782 * @class Roo.Element
6783 * Represents an Element in the DOM.<br><br>
6786 var el = Roo.get("my-div");
6789 var el = getEl("my-div");
6791 // or with a DOM element
6792 var el = Roo.get(myDivElement);
6794 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6795 * each call instead of constructing a new one.<br><br>
6796 * <b>Animations</b><br />
6797 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6798 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6800 Option Default Description
6801 --------- -------- ---------------------------------------------
6802 duration .35 The duration of the animation in seconds
6803 easing easeOut The YUI easing method
6804 callback none A function to execute when the anim completes
6805 scope this The scope (this) of the callback function
6807 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6808 * manipulate the animation. Here's an example:
6810 var el = Roo.get("my-div");
6815 // default animation
6816 el.setWidth(100, true);
6818 // animation with some options set
6825 // using the "anim" property to get the Anim object
6831 el.setWidth(100, opt);
6833 if(opt.anim.isAnimated()){
6837 * <b> Composite (Collections of) Elements</b><br />
6838 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6839 * @constructor Create a new Element directly.
6840 * @param {String/HTMLElement} element
6841 * @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).
6843 Roo.Element = function(element, forceNew){
6844 var dom = typeof element == "string" ?
6845 document.getElementById(element) : element;
6846 if(!dom){ // invalid id/element
6850 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6851 return Roo.Element.cache[id];
6861 * The DOM element ID
6864 this.id = id || Roo.id(dom);
6867 var El = Roo.Element;
6871 * The element's default display mode (defaults to "")
6874 originalDisplay : "",
6878 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6883 * Sets the element's visibility mode. When setVisible() is called it
6884 * will use this to determine whether to set the visibility or the display property.
6885 * @param visMode Element.VISIBILITY or Element.DISPLAY
6886 * @return {Roo.Element} this
6888 setVisibilityMode : function(visMode){
6889 this.visibilityMode = visMode;
6893 * Convenience method for setVisibilityMode(Element.DISPLAY)
6894 * @param {String} display (optional) What to set display to when visible
6895 * @return {Roo.Element} this
6897 enableDisplayMode : function(display){
6898 this.setVisibilityMode(El.DISPLAY);
6899 if(typeof display != "undefined") this.originalDisplay = display;
6904 * 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)
6905 * @param {String} selector The simple selector to test
6906 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6907 search as a number or element (defaults to 10 || document.body)
6908 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6909 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6911 findParent : function(simpleSelector, maxDepth, returnEl){
6912 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6913 maxDepth = maxDepth || 50;
6914 if(typeof maxDepth != "number"){
6915 stopEl = Roo.getDom(maxDepth);
6918 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6919 if(dq.is(p, simpleSelector)){
6920 return returnEl ? Roo.get(p) : p;
6930 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6931 * @param {String} selector The simple selector to test
6932 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6933 search as a number or element (defaults to 10 || document.body)
6934 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6935 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6937 findParentNode : function(simpleSelector, maxDepth, returnEl){
6938 var p = Roo.fly(this.dom.parentNode, '_internal');
6939 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6943 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6944 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6945 * @param {String} selector The simple selector to test
6946 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6947 search as a number or element (defaults to 10 || document.body)
6948 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6950 up : function(simpleSelector, maxDepth){
6951 return this.findParentNode(simpleSelector, maxDepth, true);
6957 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6958 * @param {String} selector The simple selector to test
6959 * @return {Boolean} True if this element matches the selector, else false
6961 is : function(simpleSelector){
6962 return Roo.DomQuery.is(this.dom, simpleSelector);
6966 * Perform animation on this element.
6967 * @param {Object} args The YUI animation control args
6968 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6969 * @param {Function} onComplete (optional) Function to call when animation completes
6970 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6971 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6972 * @return {Roo.Element} this
6974 animate : function(args, duration, onComplete, easing, animType){
6975 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6980 * @private Internal animation call
6982 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6983 animType = animType || 'run';
6985 var anim = Roo.lib.Anim[animType](
6987 (opt.duration || defaultDur) || .35,
6988 (opt.easing || defaultEase) || 'easeOut',
6990 Roo.callback(cb, this);
6991 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6999 // private legacy anim prep
7000 preanim : function(a, i){
7001 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7005 * Removes worthless text nodes
7006 * @param {Boolean} forceReclean (optional) By default the element
7007 * keeps track if it has been cleaned already so
7008 * you can call this over and over. However, if you update the element and
7009 * need to force a reclean, you can pass true.
7011 clean : function(forceReclean){
7012 if(this.isCleaned && forceReclean !== true){
7016 var d = this.dom, n = d.firstChild, ni = -1;
7018 var nx = n.nextSibling;
7019 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7026 this.isCleaned = true;
7031 calcOffsetsTo : function(el){
7034 var restorePos = false;
7035 if(el.getStyle('position') == 'static'){
7036 el.position('relative');
7041 while(op && op != d && op.tagName != 'HTML'){
7044 op = op.offsetParent;
7047 el.position('static');
7053 * Scrolls this element into view within the passed container.
7054 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7055 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7056 * @return {Roo.Element} this
7058 scrollIntoView : function(container, hscroll){
7059 var c = Roo.getDom(container) || document.body;
7062 var o = this.calcOffsetsTo(c),
7065 b = t+el.offsetHeight,
7066 r = l+el.offsetWidth;
7068 var ch = c.clientHeight;
7069 var ct = parseInt(c.scrollTop, 10);
7070 var cl = parseInt(c.scrollLeft, 10);
7072 var cr = cl + c.clientWidth;
7080 if(hscroll !== false){
7084 c.scrollLeft = r-c.clientWidth;
7091 scrollChildIntoView : function(child, hscroll){
7092 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7096 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7097 * the new height may not be available immediately.
7098 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7099 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7100 * @param {Function} onComplete (optional) Function to call when animation completes
7101 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7102 * @return {Roo.Element} this
7104 autoHeight : function(animate, duration, onComplete, easing){
7105 var oldHeight = this.getHeight();
7107 this.setHeight(1); // force clipping
7108 setTimeout(function(){
7109 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7111 this.setHeight(height);
7113 if(typeof onComplete == "function"){
7117 this.setHeight(oldHeight); // restore original height
7118 this.setHeight(height, animate, duration, function(){
7120 if(typeof onComplete == "function") onComplete();
7121 }.createDelegate(this), easing);
7123 }.createDelegate(this), 0);
7128 * Returns true if this element is an ancestor of the passed element
7129 * @param {HTMLElement/String} el The element to check
7130 * @return {Boolean} True if this element is an ancestor of el, else false
7132 contains : function(el){
7133 if(!el){return false;}
7134 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7138 * Checks whether the element is currently visible using both visibility and display properties.
7139 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7140 * @return {Boolean} True if the element is currently visible, else false
7142 isVisible : function(deep) {
7143 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7144 if(deep !== true || !vis){
7147 var p = this.dom.parentNode;
7148 while(p && p.tagName.toLowerCase() != "body"){
7149 if(!Roo.fly(p, '_isVisible').isVisible()){
7158 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7159 * @param {String} selector The CSS selector
7160 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7161 * @return {CompositeElement/CompositeElementLite} The composite element
7163 select : function(selector, unique){
7164 return El.select(selector, unique, this.dom);
7168 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7169 * @param {String} selector The CSS selector
7170 * @return {Array} An array of the matched nodes
7172 query : function(selector, unique){
7173 return Roo.DomQuery.select(selector, this.dom);
7177 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7178 * @param {String} selector The CSS selector
7179 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7180 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7182 child : function(selector, returnDom){
7183 var n = Roo.DomQuery.selectNode(selector, this.dom);
7184 return returnDom ? n : Roo.get(n);
7188 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7189 * @param {String} selector The CSS selector
7190 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7191 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7193 down : function(selector, returnDom){
7194 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7195 return returnDom ? n : Roo.get(n);
7199 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7200 * @param {String} group The group the DD object is member of
7201 * @param {Object} config The DD config object
7202 * @param {Object} overrides An object containing methods to override/implement on the DD object
7203 * @return {Roo.dd.DD} The DD object
7205 initDD : function(group, config, overrides){
7206 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7207 return Roo.apply(dd, overrides);
7211 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7212 * @param {String} group The group the DDProxy object is member of
7213 * @param {Object} config The DDProxy config object
7214 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7215 * @return {Roo.dd.DDProxy} The DDProxy object
7217 initDDProxy : function(group, config, overrides){
7218 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7219 return Roo.apply(dd, overrides);
7223 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7224 * @param {String} group The group the DDTarget object is member of
7225 * @param {Object} config The DDTarget config object
7226 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7227 * @return {Roo.dd.DDTarget} The DDTarget object
7229 initDDTarget : function(group, config, overrides){
7230 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7231 return Roo.apply(dd, overrides);
7235 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7236 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7237 * @param {Boolean} visible Whether the element is visible
7238 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7239 * @return {Roo.Element} this
7241 setVisible : function(visible, animate){
7243 if(this.visibilityMode == El.DISPLAY){
7244 this.setDisplayed(visible);
7247 this.dom.style.visibility = visible ? "visible" : "hidden";
7250 // closure for composites
7252 var visMode = this.visibilityMode;
7254 this.setOpacity(.01);
7255 this.setVisible(true);
7257 this.anim({opacity: { to: (visible?1:0) }},
7258 this.preanim(arguments, 1),
7259 null, .35, 'easeIn', function(){
7261 if(visMode == El.DISPLAY){
7262 dom.style.display = "none";
7264 dom.style.visibility = "hidden";
7266 Roo.get(dom).setOpacity(1);
7274 * Returns true if display is not "none"
7277 isDisplayed : function() {
7278 return this.getStyle("display") != "none";
7282 * Toggles the element's visibility or display, depending on visibility mode.
7283 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7284 * @return {Roo.Element} this
7286 toggle : function(animate){
7287 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7292 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7293 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7294 * @return {Roo.Element} this
7296 setDisplayed : function(value) {
7297 if(typeof value == "boolean"){
7298 value = value ? this.originalDisplay : "none";
7300 this.setStyle("display", value);
7305 * Tries to focus the element. Any exceptions are caught and ignored.
7306 * @return {Roo.Element} this
7308 focus : function() {
7316 * Tries to blur the element. Any exceptions are caught and ignored.
7317 * @return {Roo.Element} this
7327 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7328 * @param {String/Array} className The CSS class to add, or an array of classes
7329 * @return {Roo.Element} this
7331 addClass : function(className){
7332 if(className instanceof Array){
7333 for(var i = 0, len = className.length; i < len; i++) {
7334 this.addClass(className[i]);
7337 if(className && !this.hasClass(className)){
7338 this.dom.className = this.dom.className + " " + className;
7345 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7346 * @param {String/Array} className The CSS class to add, or an array of classes
7347 * @return {Roo.Element} this
7349 radioClass : function(className){
7350 var siblings = this.dom.parentNode.childNodes;
7351 for(var i = 0; i < siblings.length; i++) {
7352 var s = siblings[i];
7353 if(s.nodeType == 1){
7354 Roo.get(s).removeClass(className);
7357 this.addClass(className);
7362 * Removes one or more CSS classes from the element.
7363 * @param {String/Array} className The CSS class to remove, or an array of classes
7364 * @return {Roo.Element} this
7366 removeClass : function(className){
7367 if(!className || !this.dom.className){
7370 if(className instanceof Array){
7371 for(var i = 0, len = className.length; i < len; i++) {
7372 this.removeClass(className[i]);
7375 if(this.hasClass(className)){
7376 var re = this.classReCache[className];
7378 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7379 this.classReCache[className] = re;
7381 this.dom.className =
7382 this.dom.className.replace(re, " ");
7392 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7393 * @param {String} className The CSS class to toggle
7394 * @return {Roo.Element} this
7396 toggleClass : function(className){
7397 if(this.hasClass(className)){
7398 this.removeClass(className);
7400 this.addClass(className);
7406 * Checks if the specified CSS class exists on this element's DOM node.
7407 * @param {String} className The CSS class to check for
7408 * @return {Boolean} True if the class exists, else false
7410 hasClass : function(className){
7411 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7415 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7416 * @param {String} oldClassName The CSS class to replace
7417 * @param {String} newClassName The replacement CSS class
7418 * @return {Roo.Element} this
7420 replaceClass : function(oldClassName, newClassName){
7421 this.removeClass(oldClassName);
7422 this.addClass(newClassName);
7427 * Returns an object with properties matching the styles requested.
7428 * For example, el.getStyles('color', 'font-size', 'width') might return
7429 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7430 * @param {String} style1 A style name
7431 * @param {String} style2 A style name
7432 * @param {String} etc.
7433 * @return {Object} The style object
7435 getStyles : function(){
7436 var a = arguments, len = a.length, r = {};
7437 for(var i = 0; i < len; i++){
7438 r[a[i]] = this.getStyle(a[i]);
7444 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7445 * @param {String} property The style property whose value is returned.
7446 * @return {String} The current value of the style property for this element.
7448 getStyle : function(){
7449 return view && view.getComputedStyle ?
7451 var el = this.dom, v, cs, camel;
7452 if(prop == 'float'){
7455 if(el.style && (v = el.style[prop])){
7458 if(cs = view.getComputedStyle(el, "")){
7459 if(!(camel = propCache[prop])){
7460 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7467 var el = this.dom, v, cs, camel;
7468 if(prop == 'opacity'){
7469 if(typeof el.style.filter == 'string'){
7470 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7472 var fv = parseFloat(m[1]);
7474 return fv ? fv / 100 : 0;
7479 }else if(prop == 'float'){
7480 prop = "styleFloat";
7482 if(!(camel = propCache[prop])){
7483 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7485 if(v = el.style[camel]){
7488 if(cs = el.currentStyle){
7496 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7497 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7498 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7499 * @return {Roo.Element} this
7501 setStyle : function(prop, value){
7502 if(typeof prop == "string"){
7504 if (prop == 'float') {
7505 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7510 if(!(camel = propCache[prop])){
7511 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7514 if(camel == 'opacity') {
7515 this.setOpacity(value);
7517 this.dom.style[camel] = value;
7520 for(var style in prop){
7521 if(typeof prop[style] != "function"){
7522 this.setStyle(style, prop[style]);
7530 * More flexible version of {@link #setStyle} for setting style properties.
7531 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7532 * a function which returns such a specification.
7533 * @return {Roo.Element} this
7535 applyStyles : function(style){
7536 Roo.DomHelper.applyStyles(this.dom, style);
7541 * 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).
7542 * @return {Number} The X position of the element
7545 return D.getX(this.dom);
7549 * 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).
7550 * @return {Number} The Y position of the element
7553 return D.getY(this.dom);
7557 * 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).
7558 * @return {Array} The XY position of the element
7561 return D.getXY(this.dom);
7565 * 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).
7566 * @param {Number} The X position of the element
7567 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7568 * @return {Roo.Element} this
7570 setX : function(x, animate){
7572 D.setX(this.dom, x);
7574 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7580 * 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).
7581 * @param {Number} The Y position of the element
7582 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7583 * @return {Roo.Element} this
7585 setY : function(y, animate){
7587 D.setY(this.dom, y);
7589 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7595 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7596 * @param {String} left The left CSS property value
7597 * @return {Roo.Element} this
7599 setLeft : function(left){
7600 this.setStyle("left", this.addUnits(left));
7605 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7606 * @param {String} top The top CSS property value
7607 * @return {Roo.Element} this
7609 setTop : function(top){
7610 this.setStyle("top", this.addUnits(top));
7615 * Sets the element's CSS right style.
7616 * @param {String} right The right CSS property value
7617 * @return {Roo.Element} this
7619 setRight : function(right){
7620 this.setStyle("right", this.addUnits(right));
7625 * Sets the element's CSS bottom style.
7626 * @param {String} bottom The bottom CSS property value
7627 * @return {Roo.Element} this
7629 setBottom : function(bottom){
7630 this.setStyle("bottom", this.addUnits(bottom));
7635 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7636 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7637 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7638 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7639 * @return {Roo.Element} this
7641 setXY : function(pos, animate){
7643 D.setXY(this.dom, pos);
7645 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7651 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7652 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7653 * @param {Number} x X value for new position (coordinates are page-based)
7654 * @param {Number} y Y value for new position (coordinates are page-based)
7655 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7656 * @return {Roo.Element} this
7658 setLocation : function(x, y, animate){
7659 this.setXY([x, y], this.preanim(arguments, 2));
7664 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7665 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7666 * @param {Number} x X value for new position (coordinates are page-based)
7667 * @param {Number} y Y value for new position (coordinates are page-based)
7668 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7669 * @return {Roo.Element} this
7671 moveTo : function(x, y, animate){
7672 this.setXY([x, y], this.preanim(arguments, 2));
7677 * Returns the region of the given element.
7678 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7679 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7681 getRegion : function(){
7682 return D.getRegion(this.dom);
7686 * Returns the offset height of the element
7687 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7688 * @return {Number} The element's height
7690 getHeight : function(contentHeight){
7691 var h = this.dom.offsetHeight || 0;
7692 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7696 * Returns the offset width of the element
7697 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7698 * @return {Number} The element's width
7700 getWidth : function(contentWidth){
7701 var w = this.dom.offsetWidth || 0;
7702 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7706 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7707 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7708 * if a height has not been set using CSS.
7711 getComputedHeight : function(){
7712 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7714 h = parseInt(this.getStyle('height'), 10) || 0;
7715 if(!this.isBorderBox()){
7716 h += this.getFrameWidth('tb');
7723 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7724 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7725 * if a width has not been set using CSS.
7728 getComputedWidth : function(){
7729 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7731 w = parseInt(this.getStyle('width'), 10) || 0;
7732 if(!this.isBorderBox()){
7733 w += this.getFrameWidth('lr');
7740 * Returns the size of the element.
7741 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7742 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7744 getSize : function(contentSize){
7745 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7749 * Returns the width and height of the viewport.
7750 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7752 getViewSize : function(){
7753 var d = this.dom, doc = document, aw = 0, ah = 0;
7754 if(d == doc || d == doc.body){
7755 return {width : D.getViewWidth(), height: D.getViewHeight()};
7758 width : d.clientWidth,
7759 height: d.clientHeight
7765 * Returns the value of the "value" attribute
7766 * @param {Boolean} asNumber true to parse the value as a number
7767 * @return {String/Number}
7769 getValue : function(asNumber){
7770 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7774 adjustWidth : function(width){
7775 if(typeof width == "number"){
7776 if(this.autoBoxAdjust && !this.isBorderBox()){
7777 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7787 adjustHeight : function(height){
7788 if(typeof height == "number"){
7789 if(this.autoBoxAdjust && !this.isBorderBox()){
7790 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7800 * Set the width of the element
7801 * @param {Number} width The new width
7802 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7803 * @return {Roo.Element} this
7805 setWidth : function(width, animate){
7806 width = this.adjustWidth(width);
7808 this.dom.style.width = this.addUnits(width);
7810 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7816 * Set the height of the element
7817 * @param {Number} height The new height
7818 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7819 * @return {Roo.Element} this
7821 setHeight : function(height, animate){
7822 height = this.adjustHeight(height);
7824 this.dom.style.height = this.addUnits(height);
7826 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7832 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7833 * @param {Number} width The new width
7834 * @param {Number} height The new height
7835 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7836 * @return {Roo.Element} this
7838 setSize : function(width, height, animate){
7839 if(typeof width == "object"){ // in case of object from getSize()
7840 height = width.height; width = width.width;
7842 width = this.adjustWidth(width); height = this.adjustHeight(height);
7844 this.dom.style.width = this.addUnits(width);
7845 this.dom.style.height = this.addUnits(height);
7847 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7853 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7854 * @param {Number} x X value for new position (coordinates are page-based)
7855 * @param {Number} y Y value for new position (coordinates are page-based)
7856 * @param {Number} width The new width
7857 * @param {Number} height The new height
7858 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7859 * @return {Roo.Element} this
7861 setBounds : function(x, y, width, height, animate){
7863 this.setSize(width, height);
7864 this.setLocation(x, y);
7866 width = this.adjustWidth(width); height = this.adjustHeight(height);
7867 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7868 this.preanim(arguments, 4), 'motion');
7874 * 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.
7875 * @param {Roo.lib.Region} region The region to fill
7876 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7877 * @return {Roo.Element} this
7879 setRegion : function(region, animate){
7880 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7885 * Appends an event handler
7887 * @param {String} eventName The type of event to append
7888 * @param {Function} fn The method the event invokes
7889 * @param {Object} scope (optional) The scope (this object) of the fn
7890 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7892 addListener : function(eventName, fn, scope, options){
7894 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7899 * Removes an event handler from this element
7900 * @param {String} eventName the type of event to remove
7901 * @param {Function} fn the method the event invokes
7902 * @return {Roo.Element} this
7904 removeListener : function(eventName, fn){
7905 Roo.EventManager.removeListener(this.dom, eventName, fn);
7910 * Removes all previous added listeners from this element
7911 * @return {Roo.Element} this
7913 removeAllListeners : function(){
7914 E.purgeElement(this.dom);
7918 relayEvent : function(eventName, observable){
7919 this.on(eventName, function(e){
7920 observable.fireEvent(eventName, e);
7925 * Set the opacity of the element
7926 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7927 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7928 * @return {Roo.Element} this
7930 setOpacity : function(opacity, animate){
7932 var s = this.dom.style;
7935 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7936 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7938 s.opacity = opacity;
7941 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7947 * Gets the left X coordinate
7948 * @param {Boolean} local True to get the local css position instead of page coordinate
7951 getLeft : function(local){
7955 return parseInt(this.getStyle("left"), 10) || 0;
7960 * Gets the right X coordinate of the element (element X position + element width)
7961 * @param {Boolean} local True to get the local css position instead of page coordinate
7964 getRight : function(local){
7966 return this.getX() + this.getWidth();
7968 return (this.getLeft(true) + this.getWidth()) || 0;
7973 * Gets the top Y coordinate
7974 * @param {Boolean} local True to get the local css position instead of page coordinate
7977 getTop : function(local) {
7981 return parseInt(this.getStyle("top"), 10) || 0;
7986 * Gets the bottom Y coordinate of the element (element Y position + element height)
7987 * @param {Boolean} local True to get the local css position instead of page coordinate
7990 getBottom : function(local){
7992 return this.getY() + this.getHeight();
7994 return (this.getTop(true) + this.getHeight()) || 0;
7999 * Initializes positioning on this element. If a desired position is not passed, it will make the
8000 * the element positioned relative IF it is not already positioned.
8001 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8002 * @param {Number} zIndex (optional) The zIndex to apply
8003 * @param {Number} x (optional) Set the page X position
8004 * @param {Number} y (optional) Set the page Y position
8006 position : function(pos, zIndex, x, y){
8008 if(this.getStyle('position') == 'static'){
8009 this.setStyle('position', 'relative');
8012 this.setStyle("position", pos);
8015 this.setStyle("z-index", zIndex);
8017 if(x !== undefined && y !== undefined){
8019 }else if(x !== undefined){
8021 }else if(y !== undefined){
8027 * Clear positioning back to the default when the document was loaded
8028 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8029 * @return {Roo.Element} this
8031 clearPositioning : function(value){
8039 "position" : "static"
8045 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8046 * snapshot before performing an update and then restoring the element.
8049 getPositioning : function(){
8050 var l = this.getStyle("left");
8051 var t = this.getStyle("top");
8053 "position" : this.getStyle("position"),
8055 "right" : l ? "" : this.getStyle("right"),
8057 "bottom" : t ? "" : this.getStyle("bottom"),
8058 "z-index" : this.getStyle("z-index")
8063 * Gets the width of the border(s) for the specified side(s)
8064 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8065 * passing lr would get the border (l)eft width + the border (r)ight width.
8066 * @return {Number} The width of the sides passed added together
8068 getBorderWidth : function(side){
8069 return this.addStyles(side, El.borders);
8073 * Gets the width of the padding(s) for the specified side(s)
8074 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8075 * passing lr would get the padding (l)eft + the padding (r)ight.
8076 * @return {Number} The padding of the sides passed added together
8078 getPadding : function(side){
8079 return this.addStyles(side, El.paddings);
8083 * Set positioning with an object returned by getPositioning().
8084 * @param {Object} posCfg
8085 * @return {Roo.Element} this
8087 setPositioning : function(pc){
8088 this.applyStyles(pc);
8089 if(pc.right == "auto"){
8090 this.dom.style.right = "";
8092 if(pc.bottom == "auto"){
8093 this.dom.style.bottom = "";
8099 fixDisplay : function(){
8100 if(this.getStyle("display") == "none"){
8101 this.setStyle("visibility", "hidden");
8102 this.setStyle("display", this.originalDisplay); // first try reverting to default
8103 if(this.getStyle("display") == "none"){ // if that fails, default to block
8104 this.setStyle("display", "block");
8110 * Quick set left and top adding default units
8111 * @param {String} left The left CSS property value
8112 * @param {String} top The top CSS property value
8113 * @return {Roo.Element} this
8115 setLeftTop : function(left, top){
8116 this.dom.style.left = this.addUnits(left);
8117 this.dom.style.top = this.addUnits(top);
8122 * Move this element relative to its current position.
8123 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8124 * @param {Number} distance How far to move the element in pixels
8125 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8126 * @return {Roo.Element} this
8128 move : function(direction, distance, animate){
8129 var xy = this.getXY();
8130 direction = direction.toLowerCase();
8134 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8138 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8143 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8148 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8155 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8156 * @return {Roo.Element} this
8159 if(!this.isClipped){
8160 this.isClipped = true;
8161 this.originalClip = {
8162 "o": this.getStyle("overflow"),
8163 "x": this.getStyle("overflow-x"),
8164 "y": this.getStyle("overflow-y")
8166 this.setStyle("overflow", "hidden");
8167 this.setStyle("overflow-x", "hidden");
8168 this.setStyle("overflow-y", "hidden");
8174 * Return clipping (overflow) to original clipping before clip() was called
8175 * @return {Roo.Element} this
8177 unclip : function(){
8179 this.isClipped = false;
8180 var o = this.originalClip;
8181 if(o.o){this.setStyle("overflow", o.o);}
8182 if(o.x){this.setStyle("overflow-x", o.x);}
8183 if(o.y){this.setStyle("overflow-y", o.y);}
8190 * Gets the x,y coordinates specified by the anchor position on the element.
8191 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8192 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8193 * {width: (target width), height: (target height)} (defaults to the element's current size)
8194 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8195 * @return {Array} [x, y] An array containing the element's x and y coordinates
8197 getAnchorXY : function(anchor, local, s){
8198 //Passing a different size is useful for pre-calculating anchors,
8199 //especially for anchored animations that change the el size.
8201 var w, h, vp = false;
8204 if(d == document.body || d == document){
8206 w = D.getViewWidth(); h = D.getViewHeight();
8208 w = this.getWidth(); h = this.getHeight();
8211 w = s.width; h = s.height;
8213 var x = 0, y = 0, r = Math.round;
8214 switch((anchor || "tl").toLowerCase()){
8256 var sc = this.getScroll();
8257 return [x + sc.left, y + sc.top];
8259 //Add the element's offset xy
8260 var o = this.getXY();
8261 return [x+o[0], y+o[1]];
8265 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8266 * supported position values.
8267 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8268 * @param {String} position The position to align to.
8269 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8270 * @return {Array} [x, y]
8272 getAlignToXY : function(el, p, o){
8276 throw "Element.alignTo with an element that doesn't exist";
8278 var c = false; //constrain to viewport
8279 var p1 = "", p2 = "";
8286 }else if(p.indexOf("-") == -1){
8289 p = p.toLowerCase();
8290 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8292 throw "Element.alignTo with an invalid alignment " + p;
8294 p1 = m[1]; p2 = m[2]; c = !!m[3];
8296 //Subtract the aligned el's internal xy from the target's offset xy
8297 //plus custom offset to get the aligned el's new offset xy
8298 var a1 = this.getAnchorXY(p1, true);
8299 var a2 = el.getAnchorXY(p2, false);
8300 var x = a2[0] - a1[0] + o[0];
8301 var y = a2[1] - a1[1] + o[1];
8303 //constrain the aligned el to viewport if necessary
8304 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8305 // 5px of margin for ie
8306 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8308 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8309 //perpendicular to the vp border, allow the aligned el to slide on that border,
8310 //otherwise swap the aligned el to the opposite border of the target.
8311 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8312 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8313 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8314 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8317 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8318 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8320 if((x+w) > dw + scrollX){
8321 x = swapX ? r.left-w : dw+scrollX-w;
8324 x = swapX ? r.right : scrollX;
8326 if((y+h) > dh + scrollY){
8327 y = swapY ? r.top-h : dh+scrollY-h;
8330 y = swapY ? r.bottom : scrollY;
8337 getConstrainToXY : function(){
8338 var os = {top:0, left:0, bottom:0, right: 0};
8340 return function(el, local, offsets, proposedXY){
8342 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8344 var vw, vh, vx = 0, vy = 0;
8345 if(el.dom == document.body || el.dom == document){
8346 vw = Roo.lib.Dom.getViewWidth();
8347 vh = Roo.lib.Dom.getViewHeight();
8349 vw = el.dom.clientWidth;
8350 vh = el.dom.clientHeight;
8352 var vxy = el.getXY();
8358 var s = el.getScroll();
8360 vx += offsets.left + s.left;
8361 vy += offsets.top + s.top;
8363 vw -= offsets.right;
8364 vh -= offsets.bottom;
8369 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8370 var x = xy[0], y = xy[1];
8371 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8373 // only move it if it needs it
8376 // first validate right/bottom
8385 // then make sure top/left isn't negative
8394 return moved ? [x, y] : false;
8399 adjustForConstraints : function(xy, parent, offsets){
8400 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8404 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8405 * document it aligns it to the viewport.
8406 * The position parameter is optional, and can be specified in any one of the following formats:
8408 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8409 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8410 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8411 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8412 * <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
8413 * element's anchor point, and the second value is used as the target's anchor point.</li>
8415 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8416 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8417 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8418 * that specified in order to enforce the viewport constraints.
8419 * Following are all of the supported anchor positions:
8422 ----- -----------------------------
8423 tl The top left corner (default)
8424 t The center of the top edge
8425 tr The top right corner
8426 l The center of the left edge
8427 c In the center of the element
8428 r The center of the right edge
8429 bl The bottom left corner
8430 b The center of the bottom edge
8431 br The bottom right corner
8435 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8436 el.alignTo("other-el");
8438 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8439 el.alignTo("other-el", "tr?");
8441 // align the bottom right corner of el with the center left edge of other-el
8442 el.alignTo("other-el", "br-l?");
8444 // align the center of el with the bottom left corner of other-el and
8445 // adjust the x position by -6 pixels (and the y position by 0)
8446 el.alignTo("other-el", "c-bl", [-6, 0]);
8448 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8449 * @param {String} position The position to align to.
8450 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8451 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8452 * @return {Roo.Element} this
8454 alignTo : function(element, position, offsets, animate){
8455 var xy = this.getAlignToXY(element, position, offsets);
8456 this.setXY(xy, this.preanim(arguments, 3));
8461 * Anchors an element to another element and realigns it when the window is resized.
8462 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8463 * @param {String} position The position to align to.
8464 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8465 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8466 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8467 * is a number, it is used as the buffer delay (defaults to 50ms).
8468 * @param {Function} callback The function to call after the animation finishes
8469 * @return {Roo.Element} this
8471 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8472 var action = function(){
8473 this.alignTo(el, alignment, offsets, animate);
8474 Roo.callback(callback, this);
8476 Roo.EventManager.onWindowResize(action, this);
8477 var tm = typeof monitorScroll;
8478 if(tm != 'undefined'){
8479 Roo.EventManager.on(window, 'scroll', action, this,
8480 {buffer: tm == 'number' ? monitorScroll : 50});
8482 action.call(this); // align immediately
8486 * Clears any opacity settings from this element. Required in some cases for IE.
8487 * @return {Roo.Element} this
8489 clearOpacity : function(){
8490 if (window.ActiveXObject) {
8491 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8492 this.dom.style.filter = "";
8495 this.dom.style.opacity = "";
8496 this.dom.style["-moz-opacity"] = "";
8497 this.dom.style["-khtml-opacity"] = "";
8503 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8504 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8505 * @return {Roo.Element} this
8507 hide : function(animate){
8508 this.setVisible(false, this.preanim(arguments, 0));
8513 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8514 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8515 * @return {Roo.Element} this
8517 show : function(animate){
8518 this.setVisible(true, this.preanim(arguments, 0));
8523 * @private Test if size has a unit, otherwise appends the default
8525 addUnits : function(size){
8526 return Roo.Element.addUnits(size, this.defaultUnit);
8530 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8531 * @return {Roo.Element} this
8533 beginMeasure : function(){
8535 if(el.offsetWidth || el.offsetHeight){
8536 return this; // offsets work already
8539 var p = this.dom, b = document.body; // start with this element
8540 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8541 var pe = Roo.get(p);
8542 if(pe.getStyle('display') == 'none'){
8543 changed.push({el: p, visibility: pe.getStyle("visibility")});
8544 p.style.visibility = "hidden";
8545 p.style.display = "block";
8549 this._measureChanged = changed;
8555 * Restores displays to before beginMeasure was called
8556 * @return {Roo.Element} this
8558 endMeasure : function(){
8559 var changed = this._measureChanged;
8561 for(var i = 0, len = changed.length; i < len; i++) {
8563 r.el.style.visibility = r.visibility;
8564 r.el.style.display = "none";
8566 this._measureChanged = null;
8572 * Update the innerHTML of this element, optionally searching for and processing scripts
8573 * @param {String} html The new HTML
8574 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8575 * @param {Function} callback For async script loading you can be noticed when the update completes
8576 * @return {Roo.Element} this
8578 update : function(html, loadScripts, callback){
8579 if(typeof html == "undefined"){
8582 if(loadScripts !== true){
8583 this.dom.innerHTML = html;
8584 if(typeof callback == "function"){
8592 html += '<span id="' + id + '"></span>';
8594 E.onAvailable(id, function(){
8595 var hd = document.getElementsByTagName("head")[0];
8596 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8597 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8598 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8601 while(match = re.exec(html)){
8602 var attrs = match[1];
8603 var srcMatch = attrs ? attrs.match(srcRe) : false;
8604 if(srcMatch && srcMatch[2]){
8605 var s = document.createElement("script");
8606 s.src = srcMatch[2];
8607 var typeMatch = attrs.match(typeRe);
8608 if(typeMatch && typeMatch[2]){
8609 s.type = typeMatch[2];
8612 }else if(match[2] && match[2].length > 0){
8613 if(window.execScript) {
8614 window.execScript(match[2]);
8622 window.eval(match[2]);
8626 var el = document.getElementById(id);
8627 if(el){el.parentNode.removeChild(el);}
8628 if(typeof callback == "function"){
8632 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8637 * Direct access to the UpdateManager update() method (takes the same parameters).
8638 * @param {String/Function} url The url for this request or a function to call to get the url
8639 * @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}
8640 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8641 * @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.
8642 * @return {Roo.Element} this
8645 var um = this.getUpdateManager();
8646 um.update.apply(um, arguments);
8651 * Gets this element's UpdateManager
8652 * @return {Roo.UpdateManager} The UpdateManager
8654 getUpdateManager : function(){
8655 if(!this.updateManager){
8656 this.updateManager = new Roo.UpdateManager(this);
8658 return this.updateManager;
8662 * Disables text selection for this element (normalized across browsers)
8663 * @return {Roo.Element} this
8665 unselectable : function(){
8666 this.dom.unselectable = "on";
8667 this.swallowEvent("selectstart", true);
8668 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8669 this.addClass("x-unselectable");
8674 * Calculates the x, y to center this element on the screen
8675 * @return {Array} The x, y values [x, y]
8677 getCenterXY : function(){
8678 return this.getAlignToXY(document, 'c-c');
8682 * Centers the Element in either the viewport, or another Element.
8683 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8685 center : function(centerIn){
8686 this.alignTo(centerIn || document, 'c-c');
8691 * Tests various css rules/browsers to determine if this element uses a border box
8694 isBorderBox : function(){
8695 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8699 * Return a box {x, y, width, height} that can be used to set another elements
8700 * size/location to match this element.
8701 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8702 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8703 * @return {Object} box An object in the format {x, y, width, height}
8705 getBox : function(contentBox, local){
8710 var left = parseInt(this.getStyle("left"), 10) || 0;
8711 var top = parseInt(this.getStyle("top"), 10) || 0;
8714 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8716 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8718 var l = this.getBorderWidth("l")+this.getPadding("l");
8719 var r = this.getBorderWidth("r")+this.getPadding("r");
8720 var t = this.getBorderWidth("t")+this.getPadding("t");
8721 var b = this.getBorderWidth("b")+this.getPadding("b");
8722 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)};
8724 bx.right = bx.x + bx.width;
8725 bx.bottom = bx.y + bx.height;
8730 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8731 for more information about the sides.
8732 * @param {String} sides
8735 getFrameWidth : function(sides, onlyContentBox){
8736 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8740 * 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.
8741 * @param {Object} box The box to fill {x, y, width, height}
8742 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8743 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8744 * @return {Roo.Element} this
8746 setBox : function(box, adjust, animate){
8747 var w = box.width, h = box.height;
8748 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8749 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8750 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8752 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8757 * Forces the browser to repaint this element
8758 * @return {Roo.Element} this
8760 repaint : function(){
8762 this.addClass("x-repaint");
8763 setTimeout(function(){
8764 Roo.get(dom).removeClass("x-repaint");
8770 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8771 * then it returns the calculated width of the sides (see getPadding)
8772 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8773 * @return {Object/Number}
8775 getMargins : function(side){
8778 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8779 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8780 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8781 right: parseInt(this.getStyle("margin-right"), 10) || 0
8784 return this.addStyles(side, El.margins);
8789 addStyles : function(sides, styles){
8791 for(var i = 0, len = sides.length; i < len; i++){
8792 v = this.getStyle(styles[sides.charAt(i)]);
8794 w = parseInt(v, 10);
8802 * Creates a proxy element of this element
8803 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8804 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8805 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8806 * @return {Roo.Element} The new proxy element
8808 createProxy : function(config, renderTo, matchBox){
8810 renderTo = Roo.getDom(renderTo);
8812 renderTo = document.body;
8814 config = typeof config == "object" ?
8815 config : {tag : "div", cls: config};
8816 var proxy = Roo.DomHelper.append(renderTo, config, true);
8818 proxy.setBox(this.getBox());
8824 * Puts a mask over this element to disable user interaction. Requires core.css.
8825 * This method can only be applied to elements which accept child nodes.
8826 * @param {String} msg (optional) A message to display in the mask
8827 * @param {String} msgCls (optional) A css class to apply to the msg element
8828 * @return {Element} The mask element
8830 mask : function(msg, msgCls){
8831 if(this.getStyle("position") == "static"){
8832 this.setStyle("position", "relative");
8835 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8837 this.addClass("x-masked");
8838 this._mask.setDisplayed(true);
8839 if(typeof msg == 'string'){
8841 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8843 var mm = this._maskMsg;
8844 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8845 mm.dom.firstChild.innerHTML = msg;
8846 mm.setDisplayed(true);
8849 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8850 this._mask.setHeight(this.getHeight());
8856 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8857 * it is cached for reuse.
8859 unmask : function(removeEl){
8861 if(removeEl === true){
8862 this._mask.remove();
8865 this._maskMsg.remove();
8866 delete this._maskMsg;
8869 this._mask.setDisplayed(false);
8871 this._maskMsg.setDisplayed(false);
8875 this.removeClass("x-masked");
8879 * Returns true if this element is masked
8882 isMasked : function(){
8883 return this._mask && this._mask.isVisible();
8887 * Creates an iframe shim for this element to keep selects and other windowed objects from
8889 * @return {Roo.Element} The new shim element
8891 createShim : function(){
8892 var el = document.createElement('iframe');
8893 el.frameBorder = 'no';
8894 el.className = 'roo-shim';
8895 if(Roo.isIE && Roo.isSecure){
8896 el.src = Roo.SSL_SECURE_URL;
8898 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8899 shim.autoBoxAdjust = false;
8904 * Removes this element from the DOM and deletes it from the cache
8906 remove : function(){
8907 if(this.dom.parentNode){
8908 this.dom.parentNode.removeChild(this.dom);
8910 delete El.cache[this.dom.id];
8914 * Sets up event handlers to add and remove a css class when the mouse is over this element
8915 * @param {String} className
8916 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8917 * mouseout events for children elements
8918 * @return {Roo.Element} this
8920 addClassOnOver : function(className, preventFlicker){
8921 this.on("mouseover", function(){
8922 Roo.fly(this, '_internal').addClass(className);
8924 var removeFn = function(e){
8925 if(preventFlicker !== true || !e.within(this, true)){
8926 Roo.fly(this, '_internal').removeClass(className);
8929 this.on("mouseout", removeFn, this.dom);
8934 * Sets up event handlers to add and remove a css class when this element has the focus
8935 * @param {String} className
8936 * @return {Roo.Element} this
8938 addClassOnFocus : function(className){
8939 this.on("focus", function(){
8940 Roo.fly(this, '_internal').addClass(className);
8942 this.on("blur", function(){
8943 Roo.fly(this, '_internal').removeClass(className);
8948 * 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)
8949 * @param {String} className
8950 * @return {Roo.Element} this
8952 addClassOnClick : function(className){
8954 this.on("mousedown", function(){
8955 Roo.fly(dom, '_internal').addClass(className);
8956 var d = Roo.get(document);
8957 var fn = function(){
8958 Roo.fly(dom, '_internal').removeClass(className);
8959 d.removeListener("mouseup", fn);
8961 d.on("mouseup", fn);
8967 * Stops the specified event from bubbling and optionally prevents the default action
8968 * @param {String} eventName
8969 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8970 * @return {Roo.Element} this
8972 swallowEvent : function(eventName, preventDefault){
8973 var fn = function(e){
8974 e.stopPropagation();
8979 if(eventName instanceof Array){
8980 for(var i = 0, len = eventName.length; i < len; i++){
8981 this.on(eventName[i], fn);
8985 this.on(eventName, fn);
8992 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8995 * Sizes this element to its parent element's dimensions performing
8996 * neccessary box adjustments.
8997 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8998 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8999 * @return {Roo.Element} this
9001 fitToParent : function(monitorResize, targetParent) {
9002 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9003 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9004 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9007 var p = Roo.get(targetParent || this.dom.parentNode);
9008 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9009 if (monitorResize === true) {
9010 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9011 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9017 * Gets the next sibling, skipping text nodes
9018 * @return {HTMLElement} The next sibling or null
9020 getNextSibling : function(){
9021 var n = this.dom.nextSibling;
9022 while(n && n.nodeType != 1){
9029 * Gets the previous sibling, skipping text nodes
9030 * @return {HTMLElement} The previous sibling or null
9032 getPrevSibling : function(){
9033 var n = this.dom.previousSibling;
9034 while(n && n.nodeType != 1){
9035 n = n.previousSibling;
9042 * Appends the passed element(s) to this element
9043 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9044 * @return {Roo.Element} this
9046 appendChild: function(el){
9053 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9054 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9055 * automatically generated with the specified attributes.
9056 * @param {HTMLElement} insertBefore (optional) a child element of this element
9057 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9058 * @return {Roo.Element} The new child element
9060 createChild: function(config, insertBefore, returnDom){
9061 config = config || {tag:'div'};
9063 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9065 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9069 * Appends this element to the passed element
9070 * @param {String/HTMLElement/Element} el The new parent element
9071 * @return {Roo.Element} this
9073 appendTo: function(el){
9074 el = Roo.getDom(el);
9075 el.appendChild(this.dom);
9080 * Inserts this element before the passed element in the DOM
9081 * @param {String/HTMLElement/Element} el The element to insert before
9082 * @return {Roo.Element} this
9084 insertBefore: function(el){
9085 el = Roo.getDom(el);
9086 el.parentNode.insertBefore(this.dom, el);
9091 * Inserts this element after the passed element in the DOM
9092 * @param {String/HTMLElement/Element} el The element to insert after
9093 * @return {Roo.Element} this
9095 insertAfter: function(el){
9096 el = Roo.getDom(el);
9097 el.parentNode.insertBefore(this.dom, el.nextSibling);
9102 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9103 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9104 * @return {Roo.Element} The new child
9106 insertFirst: function(el, returnDom){
9108 if(typeof el == 'object' && !el.nodeType){ // dh config
9109 return this.createChild(el, this.dom.firstChild, returnDom);
9111 el = Roo.getDom(el);
9112 this.dom.insertBefore(el, this.dom.firstChild);
9113 return !returnDom ? Roo.get(el) : el;
9118 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9119 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9120 * @param {String} where (optional) 'before' or 'after' defaults to before
9121 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9122 * @return {Roo.Element} the inserted Element
9124 insertSibling: function(el, where, returnDom){
9125 where = where ? where.toLowerCase() : 'before';
9127 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9129 if(typeof el == 'object' && !el.nodeType){ // dh config
9130 if(where == 'after' && !this.dom.nextSibling){
9131 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9133 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9137 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9138 where == 'before' ? this.dom : this.dom.nextSibling);
9147 * Creates and wraps this element with another element
9148 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9149 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9150 * @return {HTMLElement/Element} The newly created wrapper element
9152 wrap: function(config, returnDom){
9154 config = {tag: "div"};
9156 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9157 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9162 * Replaces the passed element with this element
9163 * @param {String/HTMLElement/Element} el The element to replace
9164 * @return {Roo.Element} this
9166 replace: function(el){
9168 this.insertBefore(el);
9174 * Inserts an html fragment into this element
9175 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9176 * @param {String} html The HTML fragment
9177 * @param {Boolean} returnEl True to return an Roo.Element
9178 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9180 insertHtml : function(where, html, returnEl){
9181 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9182 return returnEl ? Roo.get(el) : el;
9186 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9187 * @param {Object} o The object with the attributes
9188 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9189 * @return {Roo.Element} this
9191 set : function(o, useSet){
9193 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9195 if(attr == "style" || typeof o[attr] == "function") continue;
9197 el.className = o["cls"];
9199 if(useSet) el.setAttribute(attr, o[attr]);
9200 else el[attr] = o[attr];
9204 Roo.DomHelper.applyStyles(el, o.style);
9210 * Convenience method for constructing a KeyMap
9211 * @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:
9212 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9213 * @param {Function} fn The function to call
9214 * @param {Object} scope (optional) The scope of the function
9215 * @return {Roo.KeyMap} The KeyMap created
9217 addKeyListener : function(key, fn, scope){
9219 if(typeof key != "object" || key instanceof Array){
9235 return new Roo.KeyMap(this, config);
9239 * Creates a KeyMap for this element
9240 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9241 * @return {Roo.KeyMap} The KeyMap created
9243 addKeyMap : function(config){
9244 return new Roo.KeyMap(this, config);
9248 * Returns true if this element is scrollable.
9251 isScrollable : function(){
9253 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9257 * 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().
9258 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9259 * @param {Number} value The new scroll value
9260 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9261 * @return {Element} this
9264 scrollTo : function(side, value, animate){
9265 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9267 this.dom[prop] = value;
9269 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9270 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9276 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9277 * within this element's scrollable range.
9278 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9279 * @param {Number} distance How far to scroll the element in pixels
9280 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9281 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9282 * was scrolled as far as it could go.
9284 scroll : function(direction, distance, animate){
9285 if(!this.isScrollable()){
9289 var l = el.scrollLeft, t = el.scrollTop;
9290 var w = el.scrollWidth, h = el.scrollHeight;
9291 var cw = el.clientWidth, ch = el.clientHeight;
9292 direction = direction.toLowerCase();
9293 var scrolled = false;
9294 var a = this.preanim(arguments, 2);
9299 var v = Math.min(l + distance, w-cw);
9300 this.scrollTo("left", v, a);
9307 var v = Math.max(l - distance, 0);
9308 this.scrollTo("left", v, a);
9316 var v = Math.max(t - distance, 0);
9317 this.scrollTo("top", v, a);
9325 var v = Math.min(t + distance, h-ch);
9326 this.scrollTo("top", v, a);
9335 * Translates the passed page coordinates into left/top css values for this element
9336 * @param {Number/Array} x The page x or an array containing [x, y]
9337 * @param {Number} y The page y
9338 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9340 translatePoints : function(x, y){
9341 if(typeof x == 'object' || x instanceof Array){
9344 var p = this.getStyle('position');
9345 var o = this.getXY();
9347 var l = parseInt(this.getStyle('left'), 10);
9348 var t = parseInt(this.getStyle('top'), 10);
9351 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9354 t = (p == "relative") ? 0 : this.dom.offsetTop;
9357 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9361 * Returns the current scroll position of the element.
9362 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9364 getScroll : function(){
9365 var d = this.dom, doc = document;
9366 if(d == doc || d == doc.body){
9367 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9368 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9369 return {left: l, top: t};
9371 return {left: d.scrollLeft, top: d.scrollTop};
9376 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9377 * are convert to standard 6 digit hex color.
9378 * @param {String} attr The css attribute
9379 * @param {String} defaultValue The default value to use when a valid color isn't found
9380 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9383 getColor : function(attr, defaultValue, prefix){
9384 var v = this.getStyle(attr);
9385 if(!v || v == "transparent" || v == "inherit") {
9386 return defaultValue;
9388 var color = typeof prefix == "undefined" ? "#" : prefix;
9389 if(v.substr(0, 4) == "rgb("){
9390 var rvs = v.slice(4, v.length -1).split(",");
9391 for(var i = 0; i < 3; i++){
9392 var h = parseInt(rvs[i]).toString(16);
9399 if(v.substr(0, 1) == "#"){
9401 for(var i = 1; i < 4; i++){
9402 var c = v.charAt(i);
9405 }else if(v.length == 7){
9406 color += v.substr(1);
9410 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9414 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9415 * gradient background, rounded corners and a 4-way shadow.
9416 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9417 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9418 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9419 * @return {Roo.Element} this
9421 boxWrap : function(cls){
9422 cls = cls || 'x-box';
9423 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9424 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9429 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9430 * @param {String} namespace The namespace in which to look for the attribute
9431 * @param {String} name The attribute name
9432 * @return {String} The attribute value
9434 getAttributeNS : Roo.isIE ? function(ns, name){
9436 var type = typeof d[ns+":"+name];
9437 if(type != 'undefined' && type != 'unknown'){
9438 return d[ns+":"+name];
9441 } : function(ns, name){
9443 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9447 var ep = El.prototype;
9450 * Appends an event handler (Shorthand for addListener)
9451 * @param {String} eventName The type of event to append
9452 * @param {Function} fn The method the event invokes
9453 * @param {Object} scope (optional) The scope (this object) of the fn
9454 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9457 ep.on = ep.addListener;
9459 ep.mon = ep.addListener;
9462 * Removes an event handler from this element (shorthand for removeListener)
9463 * @param {String} eventName the type of event to remove
9464 * @param {Function} fn the method the event invokes
9465 * @return {Roo.Element} this
9468 ep.un = ep.removeListener;
9471 * true to automatically adjust width and height settings for box-model issues (default to true)
9473 ep.autoBoxAdjust = true;
9476 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9479 El.addUnits = function(v, defaultUnit){
9480 if(v === "" || v == "auto"){
9483 if(v === undefined){
9486 if(typeof v == "number" || !El.unitPattern.test(v)){
9487 return v + (defaultUnit || 'px');
9492 // special markup used throughout Roo when box wrapping elements
9493 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>';
9495 * Visibility mode constant - Use visibility to hide element
9501 * Visibility mode constant - Use display to hide element
9507 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9508 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9509 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9521 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9522 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9523 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9524 * @return {Element} The Element object
9527 El.get = function(el){
9529 if(!el){ return null; }
9530 if(typeof el == "string"){ // element id
9531 if(!(elm = document.getElementById(el))){
9534 if(ex = El.cache[el]){
9537 ex = El.cache[el] = new El(elm);
9540 }else if(el.tagName){ // dom element
9544 if(ex = El.cache[id]){
9547 ex = El.cache[id] = new El(el);
9550 }else if(el instanceof El){
9552 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9553 // catch case where it hasn't been appended
9554 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9557 }else if(el.isComposite){
9559 }else if(el instanceof Array){
9560 return El.select(el);
9561 }else if(el == document){
9562 // create a bogus element object representing the document object
9564 var f = function(){};
9565 f.prototype = El.prototype;
9567 docEl.dom = document;
9575 El.uncache = function(el){
9576 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9578 delete El.cache[a[i].id || a[i]];
9584 // Garbage collection - uncache elements/purge listeners on orphaned elements
9585 // so we don't hold a reference and cause the browser to retain them
9586 El.garbageCollect = function(){
9587 if(!Roo.enableGarbageCollector){
9588 clearInterval(El.collectorThread);
9591 for(var eid in El.cache){
9592 var el = El.cache[eid], d = el.dom;
9593 // -------------------------------------------------------
9594 // Determining what is garbage:
9595 // -------------------------------------------------------
9597 // dom node is null, definitely garbage
9598 // -------------------------------------------------------
9600 // no parentNode == direct orphan, definitely garbage
9601 // -------------------------------------------------------
9602 // !d.offsetParent && !document.getElementById(eid)
9603 // display none elements have no offsetParent so we will
9604 // also try to look it up by it's id. However, check
9605 // offsetParent first so we don't do unneeded lookups.
9606 // This enables collection of elements that are not orphans
9607 // directly, but somewhere up the line they have an orphan
9609 // -------------------------------------------------------
9610 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9611 delete El.cache[eid];
9612 if(d && Roo.enableListenerCollection){
9618 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9622 El.Flyweight = function(dom){
9625 El.Flyweight.prototype = El.prototype;
9627 El._flyweights = {};
9629 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9630 * the dom node can be overwritten by other code.
9631 * @param {String/HTMLElement} el The dom node or id
9632 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9633 * prevent conflicts (e.g. internally Roo uses "_internal")
9635 * @return {Element} The shared Element object
9637 El.fly = function(el, named){
9638 named = named || '_global';
9639 el = Roo.getDom(el);
9643 if(!El._flyweights[named]){
9644 El._flyweights[named] = new El.Flyweight();
9646 El._flyweights[named].dom = el;
9647 return El._flyweights[named];
9651 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9652 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9653 * Shorthand of {@link Roo.Element#get}
9654 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9655 * @return {Element} The Element object
9661 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9662 * the dom node can be overwritten by other code.
9663 * Shorthand of {@link Roo.Element#fly}
9664 * @param {String/HTMLElement} el The dom node or id
9665 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9666 * prevent conflicts (e.g. internally Roo uses "_internal")
9668 * @return {Element} The shared Element object
9674 // speedy lookup for elements never to box adjust
9675 var noBoxAdjust = Roo.isStrict ? {
9678 input:1, select:1, textarea:1
9680 if(Roo.isIE || Roo.isGecko){
9681 noBoxAdjust['button'] = 1;
9685 Roo.EventManager.on(window, 'unload', function(){
9687 delete El._flyweights;
9695 Roo.Element.selectorFunction = Roo.DomQuery.select;
9698 Roo.Element.select = function(selector, unique, root){
9700 if(typeof selector == "string"){
9701 els = Roo.Element.selectorFunction(selector, root);
9702 }else if(selector.length !== undefined){
9705 throw "Invalid selector";
9707 if(unique === true){
9708 return new Roo.CompositeElement(els);
9710 return new Roo.CompositeElementLite(els);
9714 * Selects elements based on the passed CSS selector to enable working on them as 1.
9715 * @param {String/Array} selector The CSS selector or an array of elements
9716 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9717 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9718 * @return {CompositeElementLite/CompositeElement}
9722 Roo.select = Roo.Element.select;
9739 * Ext JS Library 1.1.1
9740 * Copyright(c) 2006-2007, Ext JS, LLC.
9742 * Originally Released Under LGPL - original licence link has changed is not relivant.
9745 * <script type="text/javascript">
9750 //Notifies Element that fx methods are available
9751 Roo.enableFx = true;
9755 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9756 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9757 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9758 * Element effects to work.</p><br/>
9760 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9761 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9762 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9763 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9764 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9765 * expected results and should be done with care.</p><br/>
9767 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9768 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9771 ----- -----------------------------
9772 tl The top left corner
9773 t The center of the top edge
9774 tr The top right corner
9775 l The center of the left edge
9776 r The center of the right edge
9777 bl The bottom left corner
9778 b The center of the bottom edge
9779 br The bottom right corner
9781 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9782 * below are common options that can be passed to any Fx method.</b>
9783 * @cfg {Function} callback A function called when the effect is finished
9784 * @cfg {Object} scope The scope of the effect function
9785 * @cfg {String} easing A valid Easing value for the effect
9786 * @cfg {String} afterCls A css class to apply after the effect
9787 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9788 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9789 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9790 * effects that end with the element being visually hidden, ignored otherwise)
9791 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9792 * a function which returns such a specification that will be applied to the Element after the effect finishes
9793 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9794 * @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
9795 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9799 * Slides the element into view. An anchor point can be optionally passed to set the point of
9800 * origin for the slide effect. This function automatically handles wrapping the element with
9801 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9804 // default: slide the element in from the top
9807 // custom: slide the element in from the right with a 2-second duration
9808 el.slideIn('r', { duration: 2 });
9810 // common config options shown with default values
9816 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9817 * @param {Object} options (optional) Object literal with any of the Fx config options
9818 * @return {Roo.Element} The Element
9820 slideIn : function(anchor, o){
9821 var el = this.getFxEl();
9824 el.queueFx(o, function(){
9826 anchor = anchor || "t";
9828 // fix display to visibility
9831 // restore values after effect
9832 var r = this.getFxRestore();
9833 var b = this.getBox();
9834 // fixed size for slide
9838 var wrap = this.fxWrap(r.pos, o, "hidden");
9840 var st = this.dom.style;
9841 st.visibility = "visible";
9842 st.position = "absolute";
9844 // clear out temp styles after slide and unwrap
9845 var after = function(){
9846 el.fxUnwrap(wrap, r.pos, o);
9848 st.height = r.height;
9851 // time to calc the positions
9852 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9854 switch(anchor.toLowerCase()){
9856 wrap.setSize(b.width, 0);
9857 st.left = st.bottom = "0";
9861 wrap.setSize(0, b.height);
9862 st.right = st.top = "0";
9866 wrap.setSize(0, b.height);
9868 st.left = st.top = "0";
9869 a = {width: bw, points: pt};
9872 wrap.setSize(b.width, 0);
9873 wrap.setY(b.bottom);
9874 st.left = st.top = "0";
9875 a = {height: bh, points: pt};
9879 st.right = st.bottom = "0";
9880 a = {width: bw, height: bh};
9884 wrap.setY(b.y+b.height);
9885 st.right = st.top = "0";
9886 a = {width: bw, height: bh, points: pt};
9890 wrap.setXY([b.right, b.bottom]);
9891 st.left = st.top = "0";
9892 a = {width: bw, height: bh, points: pt};
9896 wrap.setX(b.x+b.width);
9897 st.left = st.bottom = "0";
9898 a = {width: bw, height: bh, points: pt};
9901 this.dom.style.visibility = "visible";
9904 arguments.callee.anim = wrap.fxanim(a,
9914 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9915 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9916 * 'hidden') but block elements will still take up space in the document. The element must be removed
9917 * from the DOM using the 'remove' config option if desired. This function automatically handles
9918 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9921 // default: slide the element out to the top
9924 // custom: slide the element out to the right with a 2-second duration
9925 el.slideOut('r', { duration: 2 });
9927 // common config options shown with default values
9935 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9936 * @param {Object} options (optional) Object literal with any of the Fx config options
9937 * @return {Roo.Element} The Element
9939 slideOut : function(anchor, o){
9940 var el = this.getFxEl();
9943 el.queueFx(o, function(){
9945 anchor = anchor || "t";
9947 // restore values after effect
9948 var r = this.getFxRestore();
9950 var b = this.getBox();
9951 // fixed size for slide
9955 var wrap = this.fxWrap(r.pos, o, "visible");
9957 var st = this.dom.style;
9958 st.visibility = "visible";
9959 st.position = "absolute";
9963 var after = function(){
9965 el.setDisplayed(false);
9970 el.fxUnwrap(wrap, r.pos, o);
9973 st.height = r.height;
9978 var a, zero = {to: 0};
9979 switch(anchor.toLowerCase()){
9981 st.left = st.bottom = "0";
9985 st.right = st.top = "0";
9989 st.left = st.top = "0";
9990 a = {width: zero, points: {to:[b.right, b.y]}};
9993 st.left = st.top = "0";
9994 a = {height: zero, points: {to:[b.x, b.bottom]}};
9997 st.right = st.bottom = "0";
9998 a = {width: zero, height: zero};
10001 st.right = st.top = "0";
10002 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10005 st.left = st.top = "0";
10006 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10009 st.left = st.bottom = "0";
10010 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10014 arguments.callee.anim = wrap.fxanim(a,
10024 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10025 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10026 * The element must be removed from the DOM using the 'remove' config option if desired.
10032 // common config options shown with default values
10040 * @param {Object} options (optional) Object literal with any of the Fx config options
10041 * @return {Roo.Element} The Element
10043 puff : function(o){
10044 var el = this.getFxEl();
10047 el.queueFx(o, function(){
10048 this.clearOpacity();
10051 // restore values after effect
10052 var r = this.getFxRestore();
10053 var st = this.dom.style;
10055 var after = function(){
10057 el.setDisplayed(false);
10064 el.setPositioning(r.pos);
10065 st.width = r.width;
10066 st.height = r.height;
10071 var width = this.getWidth();
10072 var height = this.getHeight();
10074 arguments.callee.anim = this.fxanim({
10075 width : {to: this.adjustWidth(width * 2)},
10076 height : {to: this.adjustHeight(height * 2)},
10077 points : {by: [-(width * .5), -(height * .5)]},
10079 fontSize: {to:200, unit: "%"}
10090 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10091 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10092 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10098 // all config options shown with default values
10106 * @param {Object} options (optional) Object literal with any of the Fx config options
10107 * @return {Roo.Element} The Element
10109 switchOff : function(o){
10110 var el = this.getFxEl();
10113 el.queueFx(o, function(){
10114 this.clearOpacity();
10117 // restore values after effect
10118 var r = this.getFxRestore();
10119 var st = this.dom.style;
10121 var after = function(){
10123 el.setDisplayed(false);
10129 el.setPositioning(r.pos);
10130 st.width = r.width;
10131 st.height = r.height;
10136 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10137 this.clearOpacity();
10141 points:{by:[0, this.getHeight() * .5]}
10142 }, o, 'motion', 0.3, 'easeIn', after);
10143 }).defer(100, this);
10150 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10151 * changed using the "attr" config option) and then fading back to the original color. If no original
10152 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10155 // default: highlight background to yellow
10158 // custom: highlight foreground text to blue for 2 seconds
10159 el.highlight("0000ff", { attr: 'color', duration: 2 });
10161 // common config options shown with default values
10162 el.highlight("ffff9c", {
10163 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10164 endColor: (current color) or "ffffff",
10169 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10170 * @param {Object} options (optional) Object literal with any of the Fx config options
10171 * @return {Roo.Element} The Element
10173 highlight : function(color, o){
10174 var el = this.getFxEl();
10177 el.queueFx(o, function(){
10178 color = color || "ffff9c";
10179 attr = o.attr || "backgroundColor";
10181 this.clearOpacity();
10184 var origColor = this.getColor(attr);
10185 var restoreColor = this.dom.style[attr];
10186 endColor = (o.endColor || origColor) || "ffffff";
10188 var after = function(){
10189 el.dom.style[attr] = restoreColor;
10194 a[attr] = {from: color, to: endColor};
10195 arguments.callee.anim = this.fxanim(a,
10205 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10208 // default: a single light blue ripple
10211 // custom: 3 red ripples lasting 3 seconds total
10212 el.frame("ff0000", 3, { duration: 3 });
10214 // common config options shown with default values
10215 el.frame("C3DAF9", 1, {
10216 duration: 1 //duration of entire animation (not each individual ripple)
10217 // Note: Easing is not configurable and will be ignored if included
10220 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10221 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10222 * @param {Object} options (optional) Object literal with any of the Fx config options
10223 * @return {Roo.Element} The Element
10225 frame : function(color, count, o){
10226 var el = this.getFxEl();
10229 el.queueFx(o, function(){
10230 color = color || "#C3DAF9";
10231 if(color.length == 6){
10232 color = "#" + color;
10234 count = count || 1;
10235 duration = o.duration || 1;
10238 var b = this.getBox();
10239 var animFn = function(){
10240 var proxy = this.createProxy({
10243 visbility:"hidden",
10244 position:"absolute",
10245 "z-index":"35000", // yee haw
10246 border:"0px solid " + color
10249 var scale = Roo.isBorderBox ? 2 : 1;
10251 top:{from:b.y, to:b.y - 20},
10252 left:{from:b.x, to:b.x - 20},
10253 borderWidth:{from:0, to:10},
10254 opacity:{from:1, to:0},
10255 height:{from:b.height, to:(b.height + (20*scale))},
10256 width:{from:b.width, to:(b.width + (20*scale))}
10257 }, duration, function(){
10261 animFn.defer((duration/2)*1000, this);
10272 * Creates a pause before any subsequent queued effects begin. If there are
10273 * no effects queued after the pause it will have no effect.
10278 * @param {Number} seconds The length of time to pause (in seconds)
10279 * @return {Roo.Element} The Element
10281 pause : function(seconds){
10282 var el = this.getFxEl();
10285 el.queueFx(o, function(){
10286 setTimeout(function(){
10288 }, seconds * 1000);
10294 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10295 * using the "endOpacity" config option.
10298 // default: fade in from opacity 0 to 100%
10301 // custom: fade in from opacity 0 to 75% over 2 seconds
10302 el.fadeIn({ endOpacity: .75, duration: 2});
10304 // common config options shown with default values
10306 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10311 * @param {Object} options (optional) Object literal with any of the Fx config options
10312 * @return {Roo.Element} The Element
10314 fadeIn : function(o){
10315 var el = this.getFxEl();
10317 el.queueFx(o, function(){
10318 this.setOpacity(0);
10320 this.dom.style.visibility = 'visible';
10321 var to = o.endOpacity || 1;
10322 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10323 o, null, .5, "easeOut", function(){
10325 this.clearOpacity();
10334 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10335 * using the "endOpacity" config option.
10338 // default: fade out from the element's current opacity to 0
10341 // custom: fade out from the element's current opacity to 25% over 2 seconds
10342 el.fadeOut({ endOpacity: .25, duration: 2});
10344 // common config options shown with default values
10346 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10353 * @param {Object} options (optional) Object literal with any of the Fx config options
10354 * @return {Roo.Element} The Element
10356 fadeOut : function(o){
10357 var el = this.getFxEl();
10359 el.queueFx(o, function(){
10360 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10361 o, null, .5, "easeOut", function(){
10362 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10363 this.dom.style.display = "none";
10365 this.dom.style.visibility = "hidden";
10367 this.clearOpacity();
10375 * Animates the transition of an element's dimensions from a starting height/width
10376 * to an ending height/width.
10379 // change height and width to 100x100 pixels
10380 el.scale(100, 100);
10382 // common config options shown with default values. The height and width will default to
10383 // the element's existing values if passed as null.
10386 [element's height], {
10391 * @param {Number} width The new width (pass undefined to keep the original width)
10392 * @param {Number} height The new height (pass undefined to keep the original height)
10393 * @param {Object} options (optional) Object literal with any of the Fx config options
10394 * @return {Roo.Element} The Element
10396 scale : function(w, h, o){
10397 this.shift(Roo.apply({}, o, {
10405 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10406 * Any of these properties not specified in the config object will not be changed. This effect
10407 * requires that at least one new dimension, position or opacity setting must be passed in on
10408 * the config object in order for the function to have any effect.
10411 // slide the element horizontally to x position 200 while changing the height and opacity
10412 el.shift({ x: 200, height: 50, opacity: .8 });
10414 // common config options shown with default values.
10416 width: [element's width],
10417 height: [element's height],
10418 x: [element's x position],
10419 y: [element's y position],
10420 opacity: [element's opacity],
10425 * @param {Object} options Object literal with any of the Fx config options
10426 * @return {Roo.Element} The Element
10428 shift : function(o){
10429 var el = this.getFxEl();
10431 el.queueFx(o, function(){
10432 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10433 if(w !== undefined){
10434 a.width = {to: this.adjustWidth(w)};
10436 if(h !== undefined){
10437 a.height = {to: this.adjustHeight(h)};
10439 if(x !== undefined || y !== undefined){
10441 x !== undefined ? x : this.getX(),
10442 y !== undefined ? y : this.getY()
10445 if(op !== undefined){
10446 a.opacity = {to: op};
10448 if(o.xy !== undefined){
10449 a.points = {to: o.xy};
10451 arguments.callee.anim = this.fxanim(a,
10452 o, 'motion', .35, "easeOut", function(){
10460 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10461 * ending point of the effect.
10464 // default: slide the element downward while fading out
10467 // custom: slide the element out to the right with a 2-second duration
10468 el.ghost('r', { duration: 2 });
10470 // common config options shown with default values
10478 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10479 * @param {Object} options (optional) Object literal with any of the Fx config options
10480 * @return {Roo.Element} The Element
10482 ghost : function(anchor, o){
10483 var el = this.getFxEl();
10486 el.queueFx(o, function(){
10487 anchor = anchor || "b";
10489 // restore values after effect
10490 var r = this.getFxRestore();
10491 var w = this.getWidth(),
10492 h = this.getHeight();
10494 var st = this.dom.style;
10496 var after = function(){
10498 el.setDisplayed(false);
10504 el.setPositioning(r.pos);
10505 st.width = r.width;
10506 st.height = r.height;
10511 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10512 switch(anchor.toLowerCase()){
10539 arguments.callee.anim = this.fxanim(a,
10549 * Ensures that all effects queued after syncFx is called on the element are
10550 * run concurrently. This is the opposite of {@link #sequenceFx}.
10551 * @return {Roo.Element} The Element
10553 syncFx : function(){
10554 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10563 * Ensures that all effects queued after sequenceFx is called on the element are
10564 * run in sequence. This is the opposite of {@link #syncFx}.
10565 * @return {Roo.Element} The Element
10567 sequenceFx : function(){
10568 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10570 concurrent : false,
10577 nextFx : function(){
10578 var ef = this.fxQueue[0];
10585 * Returns true if the element has any effects actively running or queued, else returns false.
10586 * @return {Boolean} True if element has active effects, else false
10588 hasActiveFx : function(){
10589 return this.fxQueue && this.fxQueue[0];
10593 * Stops any running effects and clears the element's internal effects queue if it contains
10594 * any additional effects that haven't started yet.
10595 * @return {Roo.Element} The Element
10597 stopFx : function(){
10598 if(this.hasActiveFx()){
10599 var cur = this.fxQueue[0];
10600 if(cur && cur.anim && cur.anim.isAnimated()){
10601 this.fxQueue = [cur]; // clear out others
10602 cur.anim.stop(true);
10609 beforeFx : function(o){
10610 if(this.hasActiveFx() && !o.concurrent){
10621 * Returns true if the element is currently blocking so that no other effect can be queued
10622 * until this effect is finished, else returns false if blocking is not set. This is commonly
10623 * used to ensure that an effect initiated by a user action runs to completion prior to the
10624 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10625 * @return {Boolean} True if blocking, else false
10627 hasFxBlock : function(){
10628 var q = this.fxQueue;
10629 return q && q[0] && q[0].block;
10633 queueFx : function(o, fn){
10637 if(!this.hasFxBlock()){
10638 Roo.applyIf(o, this.fxDefaults);
10640 var run = this.beforeFx(o);
10641 fn.block = o.block;
10642 this.fxQueue.push(fn);
10654 fxWrap : function(pos, o, vis){
10656 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10659 wrapXY = this.getXY();
10661 var div = document.createElement("div");
10662 div.style.visibility = vis;
10663 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10664 wrap.setPositioning(pos);
10665 if(wrap.getStyle("position") == "static"){
10666 wrap.position("relative");
10668 this.clearPositioning('auto');
10670 wrap.dom.appendChild(this.dom);
10672 wrap.setXY(wrapXY);
10679 fxUnwrap : function(wrap, pos, o){
10680 this.clearPositioning();
10681 this.setPositioning(pos);
10683 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10689 getFxRestore : function(){
10690 var st = this.dom.style;
10691 return {pos: this.getPositioning(), width: st.width, height : st.height};
10695 afterFx : function(o){
10697 this.applyStyles(o.afterStyle);
10700 this.addClass(o.afterCls);
10702 if(o.remove === true){
10705 Roo.callback(o.callback, o.scope, [this]);
10707 this.fxQueue.shift();
10713 getFxEl : function(){ // support for composite element fx
10714 return Roo.get(this.dom);
10718 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10719 animType = animType || 'run';
10721 var anim = Roo.lib.Anim[animType](
10723 (opt.duration || defaultDur) || .35,
10724 (opt.easing || defaultEase) || 'easeOut',
10726 Roo.callback(cb, this);
10735 // backwords compat
10736 Roo.Fx.resize = Roo.Fx.scale;
10738 //When included, Roo.Fx is automatically applied to Element so that all basic
10739 //effects are available directly via the Element API
10740 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10742 * Ext JS Library 1.1.1
10743 * Copyright(c) 2006-2007, Ext JS, LLC.
10745 * Originally Released Under LGPL - original licence link has changed is not relivant.
10748 * <script type="text/javascript">
10753 * @class Roo.CompositeElement
10754 * Standard composite class. Creates a Roo.Element for every element in the collection.
10756 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10757 * actions will be performed on all the elements in this collection.</b>
10759 * All methods return <i>this</i> and can be chained.
10761 var els = Roo.select("#some-el div.some-class", true);
10762 // or select directly from an existing element
10763 var el = Roo.get('some-el');
10764 el.select('div.some-class', true);
10766 els.setWidth(100); // all elements become 100 width
10767 els.hide(true); // all elements fade out and hide
10769 els.setWidth(100).hide(true);
10772 Roo.CompositeElement = function(els){
10773 this.elements = [];
10774 this.addElements(els);
10776 Roo.CompositeElement.prototype = {
10778 addElements : function(els){
10779 if(!els) return this;
10780 if(typeof els == "string"){
10781 els = Roo.Element.selectorFunction(els);
10783 var yels = this.elements;
10784 var index = yels.length-1;
10785 for(var i = 0, len = els.length; i < len; i++) {
10786 yels[++index] = Roo.get(els[i]);
10792 * Clears this composite and adds the elements returned by the passed selector.
10793 * @param {String/Array} els A string CSS selector, an array of elements or an element
10794 * @return {CompositeElement} this
10796 fill : function(els){
10797 this.elements = [];
10803 * Filters this composite to only elements that match the passed selector.
10804 * @param {String} selector A string CSS selector
10805 * @return {CompositeElement} this
10807 filter : function(selector){
10809 this.each(function(el){
10810 if(el.is(selector)){
10811 els[els.length] = el.dom;
10818 invoke : function(fn, args){
10819 var els = this.elements;
10820 for(var i = 0, len = els.length; i < len; i++) {
10821 Roo.Element.prototype[fn].apply(els[i], args);
10826 * Adds elements to this composite.
10827 * @param {String/Array} els A string CSS selector, an array of elements or an element
10828 * @return {CompositeElement} this
10830 add : function(els){
10831 if(typeof els == "string"){
10832 this.addElements(Roo.Element.selectorFunction(els));
10833 }else if(els.length !== undefined){
10834 this.addElements(els);
10836 this.addElements([els]);
10841 * Calls the passed function passing (el, this, index) for each element in this composite.
10842 * @param {Function} fn The function to call
10843 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10844 * @return {CompositeElement} this
10846 each : function(fn, scope){
10847 var els = this.elements;
10848 for(var i = 0, len = els.length; i < len; i++){
10849 if(fn.call(scope || els[i], els[i], this, i) === false) {
10857 * Returns the Element object at the specified index
10858 * @param {Number} index
10859 * @return {Roo.Element}
10861 item : function(index){
10862 return this.elements[index] || null;
10866 * Returns the first Element
10867 * @return {Roo.Element}
10869 first : function(){
10870 return this.item(0);
10874 * Returns the last Element
10875 * @return {Roo.Element}
10878 return this.item(this.elements.length-1);
10882 * Returns the number of elements in this composite
10885 getCount : function(){
10886 return this.elements.length;
10890 * Returns true if this composite contains the passed element
10893 contains : function(el){
10894 return this.indexOf(el) !== -1;
10898 * Returns true if this composite contains the passed element
10901 indexOf : function(el){
10902 return this.elements.indexOf(Roo.get(el));
10907 * Removes the specified element(s).
10908 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10909 * or an array of any of those.
10910 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10911 * @return {CompositeElement} this
10913 removeElement : function(el, removeDom){
10914 if(el instanceof Array){
10915 for(var i = 0, len = el.length; i < len; i++){
10916 this.removeElement(el[i]);
10920 var index = typeof el == 'number' ? el : this.indexOf(el);
10923 var d = this.elements[index];
10927 d.parentNode.removeChild(d);
10930 this.elements.splice(index, 1);
10936 * Replaces the specified element with the passed element.
10937 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10939 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10940 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10941 * @return {CompositeElement} this
10943 replaceElement : function(el, replacement, domReplace){
10944 var index = typeof el == 'number' ? el : this.indexOf(el);
10947 this.elements[index].replaceWith(replacement);
10949 this.elements.splice(index, 1, Roo.get(replacement))
10956 * Removes all elements.
10958 clear : function(){
10959 this.elements = [];
10963 Roo.CompositeElement.createCall = function(proto, fnName){
10964 if(!proto[fnName]){
10965 proto[fnName] = function(){
10966 return this.invoke(fnName, arguments);
10970 for(var fnName in Roo.Element.prototype){
10971 if(typeof Roo.Element.prototype[fnName] == "function"){
10972 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10978 * Ext JS Library 1.1.1
10979 * Copyright(c) 2006-2007, Ext JS, LLC.
10981 * Originally Released Under LGPL - original licence link has changed is not relivant.
10984 * <script type="text/javascript">
10988 * @class Roo.CompositeElementLite
10989 * @extends Roo.CompositeElement
10990 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10992 var els = Roo.select("#some-el div.some-class");
10993 // or select directly from an existing element
10994 var el = Roo.get('some-el');
10995 el.select('div.some-class');
10997 els.setWidth(100); // all elements become 100 width
10998 els.hide(true); // all elements fade out and hide
11000 els.setWidth(100).hide(true);
11001 </code></pre><br><br>
11002 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11003 * actions will be performed on all the elements in this collection.</b>
11005 Roo.CompositeElementLite = function(els){
11006 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11007 this.el = new Roo.Element.Flyweight();
11009 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11010 addElements : function(els){
11012 if(els instanceof Array){
11013 this.elements = this.elements.concat(els);
11015 var yels = this.elements;
11016 var index = yels.length-1;
11017 for(var i = 0, len = els.length; i < len; i++) {
11018 yels[++index] = els[i];
11024 invoke : function(fn, args){
11025 var els = this.elements;
11027 for(var i = 0, len = els.length; i < len; i++) {
11029 Roo.Element.prototype[fn].apply(el, args);
11034 * Returns a flyweight Element of the dom element object at the specified index
11035 * @param {Number} index
11036 * @return {Roo.Element}
11038 item : function(index){
11039 if(!this.elements[index]){
11042 this.el.dom = this.elements[index];
11046 // fixes scope with flyweight
11047 addListener : function(eventName, handler, scope, opt){
11048 var els = this.elements;
11049 for(var i = 0, len = els.length; i < len; i++) {
11050 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11056 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11057 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11058 * a reference to the dom node, use el.dom.</b>
11059 * @param {Function} fn The function to call
11060 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11061 * @return {CompositeElement} this
11063 each : function(fn, scope){
11064 var els = this.elements;
11066 for(var i = 0, len = els.length; i < len; i++){
11068 if(fn.call(scope || el, el, this, i) === false){
11075 indexOf : function(el){
11076 return this.elements.indexOf(Roo.getDom(el));
11079 replaceElement : function(el, replacement, domReplace){
11080 var index = typeof el == 'number' ? el : this.indexOf(el);
11082 replacement = Roo.getDom(replacement);
11084 var d = this.elements[index];
11085 d.parentNode.insertBefore(replacement, d);
11086 d.parentNode.removeChild(d);
11088 this.elements.splice(index, 1, replacement);
11093 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11097 * Ext JS Library 1.1.1
11098 * Copyright(c) 2006-2007, Ext JS, LLC.
11100 * Originally Released Under LGPL - original licence link has changed is not relivant.
11103 * <script type="text/javascript">
11109 * @class Roo.data.Connection
11110 * @extends Roo.util.Observable
11111 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11112 * either to a configured URL, or to a URL specified at request time.<br><br>
11114 * Requests made by this class are asynchronous, and will return immediately. No data from
11115 * the server will be available to the statement immediately following the {@link #request} call.
11116 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11118 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11119 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11120 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11121 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11122 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11123 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11124 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11125 * standard DOM methods.
11127 * @param {Object} config a configuration object.
11129 Roo.data.Connection = function(config){
11130 Roo.apply(this, config);
11133 * @event beforerequest
11134 * Fires before a network request is made to retrieve a data object.
11135 * @param {Connection} conn This Connection object.
11136 * @param {Object} options The options config object passed to the {@link #request} method.
11138 "beforerequest" : true,
11140 * @event requestcomplete
11141 * Fires if the request was successfully completed.
11142 * @param {Connection} conn This Connection object.
11143 * @param {Object} response The XHR object containing the response data.
11144 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11145 * @param {Object} options The options config object passed to the {@link #request} method.
11147 "requestcomplete" : true,
11149 * @event requestexception
11150 * Fires if an error HTTP status was returned from the server.
11151 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11152 * @param {Connection} conn This Connection object.
11153 * @param {Object} response The XHR object containing the response data.
11154 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11155 * @param {Object} options The options config object passed to the {@link #request} method.
11157 "requestexception" : true
11159 Roo.data.Connection.superclass.constructor.call(this);
11162 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11164 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11167 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11168 * extra parameters to each request made by this object. (defaults to undefined)
11171 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11172 * to each request made by this object. (defaults to undefined)
11175 * @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)
11178 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11182 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11188 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11191 disableCaching: true,
11194 * Sends an HTTP request to a remote server.
11195 * @param {Object} options An object which may contain the following properties:<ul>
11196 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11197 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11198 * request, a url encoded string or a function to call to get either.</li>
11199 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11200 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11201 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11202 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11203 * <li>options {Object} The parameter to the request call.</li>
11204 * <li>success {Boolean} True if the request succeeded.</li>
11205 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11207 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11208 * The callback is passed the following parameters:<ul>
11209 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11210 * <li>options {Object} The parameter to the request call.</li>
11212 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11213 * The callback is passed the following parameters:<ul>
11214 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11215 * <li>options {Object} The parameter to the request call.</li>
11217 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11218 * for the callback function. Defaults to the browser window.</li>
11219 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11220 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11221 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11222 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11223 * params for the post data. Any params will be appended to the URL.</li>
11224 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11226 * @return {Number} transactionId
11228 request : function(o){
11229 if(this.fireEvent("beforerequest", this, o) !== false){
11232 if(typeof p == "function"){
11233 p = p.call(o.scope||window, o);
11235 if(typeof p == "object"){
11236 p = Roo.urlEncode(o.params);
11238 if(this.extraParams){
11239 var extras = Roo.urlEncode(this.extraParams);
11240 p = p ? (p + '&' + extras) : extras;
11243 var url = o.url || this.url;
11244 if(typeof url == 'function'){
11245 url = url.call(o.scope||window, o);
11249 var form = Roo.getDom(o.form);
11250 url = url || form.action;
11252 var enctype = form.getAttribute("enctype");
11253 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11254 return this.doFormUpload(o, p, url);
11256 var f = Roo.lib.Ajax.serializeForm(form);
11257 p = p ? (p + '&' + f) : f;
11260 var hs = o.headers;
11261 if(this.defaultHeaders){
11262 hs = Roo.apply(hs || {}, this.defaultHeaders);
11269 success: this.handleResponse,
11270 failure: this.handleFailure,
11272 argument: {options: o},
11273 timeout : this.timeout
11276 var method = o.method||this.method||(p ? "POST" : "GET");
11278 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11279 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11282 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11286 }else if(this.autoAbort !== false){
11290 if((method == 'GET' && p) || o.xmlData){
11291 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11294 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11295 return this.transId;
11297 Roo.callback(o.callback, o.scope, [o, null, null]);
11303 * Determine whether this object has a request outstanding.
11304 * @param {Number} transactionId (Optional) defaults to the last transaction
11305 * @return {Boolean} True if there is an outstanding request.
11307 isLoading : function(transId){
11309 return Roo.lib.Ajax.isCallInProgress(transId);
11311 return this.transId ? true : false;
11316 * Aborts any outstanding request.
11317 * @param {Number} transactionId (Optional) defaults to the last transaction
11319 abort : function(transId){
11320 if(transId || this.isLoading()){
11321 Roo.lib.Ajax.abort(transId || this.transId);
11326 handleResponse : function(response){
11327 this.transId = false;
11328 var options = response.argument.options;
11329 response.argument = options ? options.argument : null;
11330 this.fireEvent("requestcomplete", this, response, options);
11331 Roo.callback(options.success, options.scope, [response, options]);
11332 Roo.callback(options.callback, options.scope, [options, true, response]);
11336 handleFailure : function(response, e){
11337 this.transId = false;
11338 var options = response.argument.options;
11339 response.argument = options ? options.argument : null;
11340 this.fireEvent("requestexception", this, response, options, e);
11341 Roo.callback(options.failure, options.scope, [response, options]);
11342 Roo.callback(options.callback, options.scope, [options, false, response]);
11346 doFormUpload : function(o, ps, url){
11348 var frame = document.createElement('iframe');
11351 frame.className = 'x-hidden';
11353 frame.src = Roo.SSL_SECURE_URL;
11355 document.body.appendChild(frame);
11358 document.frames[id].name = id;
11361 var form = Roo.getDom(o.form);
11363 form.method = 'POST';
11364 form.enctype = form.encoding = 'multipart/form-data';
11370 if(ps){ // add dynamic params
11372 ps = Roo.urlDecode(ps, false);
11374 if(ps.hasOwnProperty(k)){
11375 hd = document.createElement('input');
11376 hd.type = 'hidden';
11379 form.appendChild(hd);
11386 var r = { // bogus response object
11391 r.argument = o ? o.argument : null;
11396 doc = frame.contentWindow.document;
11398 doc = (frame.contentDocument || window.frames[id].document);
11400 if(doc && doc.body){
11401 r.responseText = doc.body.innerHTML;
11403 if(doc && doc.XMLDocument){
11404 r.responseXML = doc.XMLDocument;
11406 r.responseXML = doc;
11413 Roo.EventManager.removeListener(frame, 'load', cb, this);
11415 this.fireEvent("requestcomplete", this, r, o);
11416 Roo.callback(o.success, o.scope, [r, o]);
11417 Roo.callback(o.callback, o.scope, [o, true, r]);
11419 setTimeout(function(){document.body.removeChild(frame);}, 100);
11422 Roo.EventManager.on(frame, 'load', cb, this);
11425 if(hiddens){ // remove dynamic params
11426 for(var i = 0, len = hiddens.length; i < len; i++){
11427 form.removeChild(hiddens[i]);
11435 * @extends Roo.data.Connection
11436 * Global Ajax request class.
11440 Roo.Ajax = new Roo.data.Connection({
11443 * @cfg {String} url @hide
11446 * @cfg {Object} extraParams @hide
11449 * @cfg {Object} defaultHeaders @hide
11452 * @cfg {String} method (Optional) @hide
11455 * @cfg {Number} timeout (Optional) @hide
11458 * @cfg {Boolean} autoAbort (Optional) @hide
11462 * @cfg {Boolean} disableCaching (Optional) @hide
11466 * @property disableCaching
11467 * True to add a unique cache-buster param to GET requests. (defaults to true)
11472 * The default URL to be used for requests to the server. (defaults to undefined)
11476 * @property extraParams
11477 * An object containing properties which are used as
11478 * extra parameters to each request made by this object. (defaults to undefined)
11482 * @property defaultHeaders
11483 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11488 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11492 * @property timeout
11493 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11498 * @property autoAbort
11499 * Whether a new request should abort any pending requests. (defaults to false)
11505 * Serialize the passed form into a url encoded string
11506 * @param {String/HTMLElement} form
11509 serializeForm : function(form){
11510 return Roo.lib.Ajax.serializeForm(form);
11514 * Ext JS Library 1.1.1
11515 * Copyright(c) 2006-2007, Ext JS, LLC.
11517 * Originally Released Under LGPL - original licence link has changed is not relivant.
11520 * <script type="text/javascript">
11525 * @extends Roo.data.Connection
11526 * Global Ajax request class.
11528 * @instanceOf Roo.data.Connection
11530 Roo.Ajax = new Roo.data.Connection({
11539 * @cfg {String} url @hide
11542 * @cfg {Object} extraParams @hide
11545 * @cfg {Object} defaultHeaders @hide
11548 * @cfg {String} method (Optional) @hide
11551 * @cfg {Number} timeout (Optional) @hide
11554 * @cfg {Boolean} autoAbort (Optional) @hide
11558 * @cfg {Boolean} disableCaching (Optional) @hide
11562 * @property disableCaching
11563 * True to add a unique cache-buster param to GET requests. (defaults to true)
11568 * The default URL to be used for requests to the server. (defaults to undefined)
11572 * @property extraParams
11573 * An object containing properties which are used as
11574 * extra parameters to each request made by this object. (defaults to undefined)
11578 * @property defaultHeaders
11579 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11584 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11588 * @property timeout
11589 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11594 * @property autoAbort
11595 * Whether a new request should abort any pending requests. (defaults to false)
11601 * Serialize the passed form into a url encoded string
11602 * @param {String/HTMLElement} form
11605 serializeForm : function(form){
11606 return Roo.lib.Ajax.serializeForm(form);
11610 * Ext JS Library 1.1.1
11611 * Copyright(c) 2006-2007, Ext JS, LLC.
11613 * Originally Released Under LGPL - original licence link has changed is not relivant.
11616 * <script type="text/javascript">
11621 * @class Roo.UpdateManager
11622 * @extends Roo.util.Observable
11623 * Provides AJAX-style update for Element object.<br><br>
11626 * // Get it from a Roo.Element object
11627 * var el = Roo.get("foo");
11628 * var mgr = el.getUpdateManager();
11629 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11631 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11633 * // or directly (returns the same UpdateManager instance)
11634 * var mgr = new Roo.UpdateManager("myElementId");
11635 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11636 * mgr.on("update", myFcnNeedsToKnow);
11638 // short handed call directly from the element object
11639 Roo.get("foo").load({
11643 text: "Loading Foo..."
11647 * Create new UpdateManager directly.
11648 * @param {String/HTMLElement/Roo.Element} el The element to update
11649 * @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).
11651 Roo.UpdateManager = function(el, forceNew){
11653 if(!forceNew && el.updateManager){
11654 return el.updateManager;
11657 * The Element object
11658 * @type Roo.Element
11662 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11665 this.defaultUrl = null;
11669 * @event beforeupdate
11670 * Fired before an update is made, return false from your handler and the update is cancelled.
11671 * @param {Roo.Element} el
11672 * @param {String/Object/Function} url
11673 * @param {String/Object} params
11675 "beforeupdate": true,
11678 * Fired after successful update is made.
11679 * @param {Roo.Element} el
11680 * @param {Object} oResponseObject The response Object
11685 * Fired on update failure.
11686 * @param {Roo.Element} el
11687 * @param {Object} oResponseObject The response Object
11691 var d = Roo.UpdateManager.defaults;
11693 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11696 this.sslBlankUrl = d.sslBlankUrl;
11698 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11701 this.disableCaching = d.disableCaching;
11703 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11706 this.indicatorText = d.indicatorText;
11708 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11711 this.showLoadIndicator = d.showLoadIndicator;
11713 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11716 this.timeout = d.timeout;
11719 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11722 this.loadScripts = d.loadScripts;
11725 * Transaction object of current executing transaction
11727 this.transaction = null;
11732 this.autoRefreshProcId = null;
11734 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11737 this.refreshDelegate = this.refresh.createDelegate(this);
11739 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11742 this.updateDelegate = this.update.createDelegate(this);
11744 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11747 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11751 this.successDelegate = this.processSuccess.createDelegate(this);
11755 this.failureDelegate = this.processFailure.createDelegate(this);
11757 if(!this.renderer){
11759 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11761 this.renderer = new Roo.UpdateManager.BasicRenderer();
11764 Roo.UpdateManager.superclass.constructor.call(this);
11767 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11769 * Get the Element this UpdateManager is bound to
11770 * @return {Roo.Element} The element
11772 getEl : function(){
11776 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11777 * @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:
11780 url: "your-url.php",<br/>
11781 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11782 callback: yourFunction,<br/>
11783 scope: yourObject, //(optional scope) <br/>
11784 discardUrl: false, <br/>
11785 nocache: false,<br/>
11786 text: "Loading...",<br/>
11788 scripts: false<br/>
11791 * The only required property is url. The optional properties nocache, text and scripts
11792 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11793 * @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}
11794 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11795 * @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.
11797 update : function(url, params, callback, discardUrl){
11798 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11799 var method = this.method, cfg;
11800 if(typeof url == "object"){ // must be config object
11803 params = params || cfg.params;
11804 callback = callback || cfg.callback;
11805 discardUrl = discardUrl || cfg.discardUrl;
11806 if(callback && cfg.scope){
11807 callback = callback.createDelegate(cfg.scope);
11809 if(typeof cfg.method != "undefined"){method = cfg.method;};
11810 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11811 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11812 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11813 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11815 this.showLoading();
11817 this.defaultUrl = url;
11819 if(typeof url == "function"){
11820 url = url.call(this);
11823 method = method || (params ? "POST" : "GET");
11824 if(method == "GET"){
11825 url = this.prepareUrl(url);
11828 var o = Roo.apply(cfg ||{}, {
11831 success: this.successDelegate,
11832 failure: this.failureDelegate,
11833 callback: undefined,
11834 timeout: (this.timeout*1000),
11835 argument: {"url": url, "form": null, "callback": callback, "params": params}
11838 this.transaction = Roo.Ajax.request(o);
11843 * 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.
11844 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11845 * @param {String/HTMLElement} form The form Id or form element
11846 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11847 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11848 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11850 formUpdate : function(form, url, reset, callback){
11851 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11852 if(typeof url == "function"){
11853 url = url.call(this);
11855 form = Roo.getDom(form);
11856 this.transaction = Roo.Ajax.request({
11859 success: this.successDelegate,
11860 failure: this.failureDelegate,
11861 timeout: (this.timeout*1000),
11862 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11864 this.showLoading.defer(1, this);
11869 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11870 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11872 refresh : function(callback){
11873 if(this.defaultUrl == null){
11876 this.update(this.defaultUrl, null, callback, true);
11880 * Set this element to auto refresh.
11881 * @param {Number} interval How often to update (in seconds).
11882 * @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)
11883 * @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}
11884 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11885 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11887 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11889 this.update(url || this.defaultUrl, params, callback, true);
11891 if(this.autoRefreshProcId){
11892 clearInterval(this.autoRefreshProcId);
11894 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11898 * Stop auto refresh on this element.
11900 stopAutoRefresh : function(){
11901 if(this.autoRefreshProcId){
11902 clearInterval(this.autoRefreshProcId);
11903 delete this.autoRefreshProcId;
11907 isAutoRefreshing : function(){
11908 return this.autoRefreshProcId ? true : false;
11911 * Called to update the element to "Loading" state. Override to perform custom action.
11913 showLoading : function(){
11914 if(this.showLoadIndicator){
11915 this.el.update(this.indicatorText);
11920 * Adds unique parameter to query string if disableCaching = true
11923 prepareUrl : function(url){
11924 if(this.disableCaching){
11925 var append = "_dc=" + (new Date().getTime());
11926 if(url.indexOf("?") !== -1){
11927 url += "&" + append;
11929 url += "?" + append;
11938 processSuccess : function(response){
11939 this.transaction = null;
11940 if(response.argument.form && response.argument.reset){
11941 try{ // put in try/catch since some older FF releases had problems with this
11942 response.argument.form.reset();
11945 if(this.loadScripts){
11946 this.renderer.render(this.el, response, this,
11947 this.updateComplete.createDelegate(this, [response]));
11949 this.renderer.render(this.el, response, this);
11950 this.updateComplete(response);
11954 updateComplete : function(response){
11955 this.fireEvent("update", this.el, response);
11956 if(typeof response.argument.callback == "function"){
11957 response.argument.callback(this.el, true, response);
11964 processFailure : function(response){
11965 this.transaction = null;
11966 this.fireEvent("failure", this.el, response);
11967 if(typeof response.argument.callback == "function"){
11968 response.argument.callback(this.el, false, response);
11973 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11974 * @param {Object} renderer The object implementing the render() method
11976 setRenderer : function(renderer){
11977 this.renderer = renderer;
11980 getRenderer : function(){
11981 return this.renderer;
11985 * Set the defaultUrl used for updates
11986 * @param {String/Function} defaultUrl The url or a function to call to get the url
11988 setDefaultUrl : function(defaultUrl){
11989 this.defaultUrl = defaultUrl;
11993 * Aborts the executing transaction
11995 abort : function(){
11996 if(this.transaction){
11997 Roo.Ajax.abort(this.transaction);
12002 * Returns true if an update is in progress
12003 * @return {Boolean}
12005 isUpdating : function(){
12006 if(this.transaction){
12007 return Roo.Ajax.isLoading(this.transaction);
12014 * @class Roo.UpdateManager.defaults
12015 * @static (not really - but it helps the doc tool)
12016 * The defaults collection enables customizing the default properties of UpdateManager
12018 Roo.UpdateManager.defaults = {
12020 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12026 * True to process scripts by default (Defaults to false).
12029 loadScripts : false,
12032 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12035 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12037 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12040 disableCaching : false,
12042 * Whether to show indicatorText when loading (Defaults to true).
12045 showLoadIndicator : true,
12047 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12050 indicatorText : '<div class="loading-indicator">Loading...</div>'
12054 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12056 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12057 * @param {String/HTMLElement/Roo.Element} el The element to update
12058 * @param {String} url The url
12059 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12060 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12063 * @member Roo.UpdateManager
12065 Roo.UpdateManager.updateElement = function(el, url, params, options){
12066 var um = Roo.get(el, true).getUpdateManager();
12067 Roo.apply(um, options);
12068 um.update(url, params, options ? options.callback : null);
12070 // alias for backwards compat
12071 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12073 * @class Roo.UpdateManager.BasicRenderer
12074 * Default Content renderer. Updates the elements innerHTML with the responseText.
12076 Roo.UpdateManager.BasicRenderer = function(){};
12078 Roo.UpdateManager.BasicRenderer.prototype = {
12080 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12081 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12082 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12083 * @param {Roo.Element} el The element being rendered
12084 * @param {Object} response The YUI Connect response object
12085 * @param {UpdateManager} updateManager The calling update manager
12086 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12088 render : function(el, response, updateManager, callback){
12089 el.update(response.responseText, updateManager.loadScripts, callback);
12094 * Ext JS Library 1.1.1
12095 * Copyright(c) 2006-2007, Ext JS, LLC.
12097 * Originally Released Under LGPL - original licence link has changed is not relivant.
12100 * <script type="text/javascript">
12104 * @class Roo.util.DelayedTask
12105 * Provides a convenient method of performing setTimeout where a new
12106 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12107 * You can use this class to buffer
12108 * the keypress events for a certain number of milliseconds, and perform only if they stop
12109 * for that amount of time.
12110 * @constructor The parameters to this constructor serve as defaults and are not required.
12111 * @param {Function} fn (optional) The default function to timeout
12112 * @param {Object} scope (optional) The default scope of that timeout
12113 * @param {Array} args (optional) The default Array of arguments
12115 Roo.util.DelayedTask = function(fn, scope, args){
12116 var id = null, d, t;
12118 var call = function(){
12119 var now = new Date().getTime();
12123 fn.apply(scope, args || []);
12127 * Cancels any pending timeout and queues a new one
12128 * @param {Number} delay The milliseconds to delay
12129 * @param {Function} newFn (optional) Overrides function passed to constructor
12130 * @param {Object} newScope (optional) Overrides scope passed to constructor
12131 * @param {Array} newArgs (optional) Overrides args passed to constructor
12133 this.delay = function(delay, newFn, newScope, newArgs){
12134 if(id && delay != d){
12138 t = new Date().getTime();
12140 scope = newScope || scope;
12141 args = newArgs || args;
12143 id = setInterval(call, d);
12148 * Cancel the last queued timeout
12150 this.cancel = function(){
12158 * Ext JS Library 1.1.1
12159 * Copyright(c) 2006-2007, Ext JS, LLC.
12161 * Originally Released Under LGPL - original licence link has changed is not relivant.
12164 * <script type="text/javascript">
12168 Roo.util.TaskRunner = function(interval){
12169 interval = interval || 10;
12170 var tasks = [], removeQueue = [];
12172 var running = false;
12174 var stopThread = function(){
12180 var startThread = function(){
12183 id = setInterval(runTasks, interval);
12187 var removeTask = function(task){
12188 removeQueue.push(task);
12194 var runTasks = function(){
12195 if(removeQueue.length > 0){
12196 for(var i = 0, len = removeQueue.length; i < len; i++){
12197 tasks.remove(removeQueue[i]);
12200 if(tasks.length < 1){
12205 var now = new Date().getTime();
12206 for(var i = 0, len = tasks.length; i < len; ++i){
12208 var itime = now - t.taskRunTime;
12209 if(t.interval <= itime){
12210 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12211 t.taskRunTime = now;
12212 if(rt === false || t.taskRunCount === t.repeat){
12217 if(t.duration && t.duration <= (now - t.taskStartTime)){
12224 * Queues a new task.
12225 * @param {Object} task
12227 this.start = function(task){
12229 task.taskStartTime = new Date().getTime();
12230 task.taskRunTime = 0;
12231 task.taskRunCount = 0;
12236 this.stop = function(task){
12241 this.stopAll = function(){
12243 for(var i = 0, len = tasks.length; i < len; i++){
12244 if(tasks[i].onStop){
12253 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12255 * Ext JS Library 1.1.1
12256 * Copyright(c) 2006-2007, Ext JS, LLC.
12258 * Originally Released Under LGPL - original licence link has changed is not relivant.
12261 * <script type="text/javascript">
12266 * @class Roo.util.MixedCollection
12267 * @extends Roo.util.Observable
12268 * A Collection class that maintains both numeric indexes and keys and exposes events.
12270 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12271 * collection (defaults to false)
12272 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12273 * and return the key value for that item. This is used when available to look up the key on items that
12274 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12275 * equivalent to providing an implementation for the {@link #getKey} method.
12277 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12285 * Fires when the collection is cleared.
12290 * Fires when an item is added to the collection.
12291 * @param {Number} index The index at which the item was added.
12292 * @param {Object} o The item added.
12293 * @param {String} key The key associated with the added item.
12298 * Fires when an item is replaced in the collection.
12299 * @param {String} key he key associated with the new added.
12300 * @param {Object} old The item being replaced.
12301 * @param {Object} new The new item.
12306 * Fires when an item is removed from the collection.
12307 * @param {Object} o The item being removed.
12308 * @param {String} key (optional) The key associated with the removed item.
12313 this.allowFunctions = allowFunctions === true;
12315 this.getKey = keyFn;
12317 Roo.util.MixedCollection.superclass.constructor.call(this);
12320 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12321 allowFunctions : false,
12324 * Adds an item to the collection.
12325 * @param {String} key The key to associate with the item
12326 * @param {Object} o The item to add.
12327 * @return {Object} The item added.
12329 add : function(key, o){
12330 if(arguments.length == 1){
12332 key = this.getKey(o);
12334 if(typeof key == "undefined" || key === null){
12336 this.items.push(o);
12337 this.keys.push(null);
12339 var old = this.map[key];
12341 return this.replace(key, o);
12344 this.items.push(o);
12346 this.keys.push(key);
12348 this.fireEvent("add", this.length-1, o, key);
12353 * MixedCollection has a generic way to fetch keys if you implement getKey.
12356 var mc = new Roo.util.MixedCollection();
12357 mc.add(someEl.dom.id, someEl);
12358 mc.add(otherEl.dom.id, otherEl);
12362 var mc = new Roo.util.MixedCollection();
12363 mc.getKey = function(el){
12369 // or via the constructor
12370 var mc = new Roo.util.MixedCollection(false, function(el){
12376 * @param o {Object} The item for which to find the key.
12377 * @return {Object} The key for the passed item.
12379 getKey : function(o){
12384 * Replaces an item in the collection.
12385 * @param {String} key The key associated with the item to replace, or the item to replace.
12386 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12387 * @return {Object} The new item.
12389 replace : function(key, o){
12390 if(arguments.length == 1){
12392 key = this.getKey(o);
12394 var old = this.item(key);
12395 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12396 return this.add(key, o);
12398 var index = this.indexOfKey(key);
12399 this.items[index] = o;
12401 this.fireEvent("replace", key, old, o);
12406 * Adds all elements of an Array or an Object to the collection.
12407 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12408 * an Array of values, each of which are added to the collection.
12410 addAll : function(objs){
12411 if(arguments.length > 1 || objs instanceof Array){
12412 var args = arguments.length > 1 ? arguments : objs;
12413 for(var i = 0, len = args.length; i < len; i++){
12417 for(var key in objs){
12418 if(this.allowFunctions || typeof objs[key] != "function"){
12419 this.add(key, objs[key]);
12426 * Executes the specified function once for every item in the collection, passing each
12427 * item as the first and only parameter. returning false from the function will stop the iteration.
12428 * @param {Function} fn The function to execute for each item.
12429 * @param {Object} scope (optional) The scope in which to execute the function.
12431 each : function(fn, scope){
12432 var items = [].concat(this.items); // each safe for removal
12433 for(var i = 0, len = items.length; i < len; i++){
12434 if(fn.call(scope || items[i], items[i], i, len) === false){
12441 * Executes the specified function once for every key in the collection, passing each
12442 * key, and its associated item as the first two parameters.
12443 * @param {Function} fn The function to execute for each item.
12444 * @param {Object} scope (optional) The scope in which to execute the function.
12446 eachKey : function(fn, scope){
12447 for(var i = 0, len = this.keys.length; i < len; i++){
12448 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12453 * Returns the first item in the collection which elicits a true return value from the
12454 * passed selection function.
12455 * @param {Function} fn The selection function to execute for each item.
12456 * @param {Object} scope (optional) The scope in which to execute the function.
12457 * @return {Object} The first item in the collection which returned true from the selection function.
12459 find : function(fn, scope){
12460 for(var i = 0, len = this.items.length; i < len; i++){
12461 if(fn.call(scope || window, this.items[i], this.keys[i])){
12462 return this.items[i];
12469 * Inserts an item at the specified index in the collection.
12470 * @param {Number} index The index to insert the item at.
12471 * @param {String} key The key to associate with the new item, or the item itself.
12472 * @param {Object} o (optional) If the second parameter was a key, the new item.
12473 * @return {Object} The item inserted.
12475 insert : function(index, key, o){
12476 if(arguments.length == 2){
12478 key = this.getKey(o);
12480 if(index >= this.length){
12481 return this.add(key, o);
12484 this.items.splice(index, 0, o);
12485 if(typeof key != "undefined" && key != null){
12488 this.keys.splice(index, 0, key);
12489 this.fireEvent("add", index, o, key);
12494 * Removed an item from the collection.
12495 * @param {Object} o The item to remove.
12496 * @return {Object} The item removed.
12498 remove : function(o){
12499 return this.removeAt(this.indexOf(o));
12503 * Remove an item from a specified index in the collection.
12504 * @param {Number} index The index within the collection of the item to remove.
12506 removeAt : function(index){
12507 if(index < this.length && index >= 0){
12509 var o = this.items[index];
12510 this.items.splice(index, 1);
12511 var key = this.keys[index];
12512 if(typeof key != "undefined"){
12513 delete this.map[key];
12515 this.keys.splice(index, 1);
12516 this.fireEvent("remove", o, key);
12521 * Removed an item associated with the passed key fom the collection.
12522 * @param {String} key The key of the item to remove.
12524 removeKey : function(key){
12525 return this.removeAt(this.indexOfKey(key));
12529 * Returns the number of items in the collection.
12530 * @return {Number} the number of items in the collection.
12532 getCount : function(){
12533 return this.length;
12537 * Returns index within the collection of the passed Object.
12538 * @param {Object} o The item to find the index of.
12539 * @return {Number} index of the item.
12541 indexOf : function(o){
12542 if(!this.items.indexOf){
12543 for(var i = 0, len = this.items.length; i < len; i++){
12544 if(this.items[i] == o) return i;
12548 return this.items.indexOf(o);
12553 * Returns index within the collection of the passed key.
12554 * @param {String} key The key to find the index of.
12555 * @return {Number} index of the key.
12557 indexOfKey : function(key){
12558 if(!this.keys.indexOf){
12559 for(var i = 0, len = this.keys.length; i < len; i++){
12560 if(this.keys[i] == key) return i;
12564 return this.keys.indexOf(key);
12569 * Returns the item associated with the passed key OR index. Key has priority over index.
12570 * @param {String/Number} key The key or index of the item.
12571 * @return {Object} The item associated with the passed key.
12573 item : function(key){
12574 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12575 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12579 * Returns the item at the specified index.
12580 * @param {Number} index The index of the item.
12583 itemAt : function(index){
12584 return this.items[index];
12588 * Returns the item associated with the passed key.
12589 * @param {String/Number} key The key of the item.
12590 * @return {Object} The item associated with the passed key.
12592 key : function(key){
12593 return this.map[key];
12597 * Returns true if the collection contains the passed Object as an item.
12598 * @param {Object} o The Object to look for in the collection.
12599 * @return {Boolean} True if the collection contains the Object as an item.
12601 contains : function(o){
12602 return this.indexOf(o) != -1;
12606 * Returns true if the collection contains the passed Object as a key.
12607 * @param {String} key The key to look for in the collection.
12608 * @return {Boolean} True if the collection contains the Object as a key.
12610 containsKey : function(key){
12611 return typeof this.map[key] != "undefined";
12615 * Removes all items from the collection.
12617 clear : function(){
12622 this.fireEvent("clear");
12626 * Returns the first item in the collection.
12627 * @return {Object} the first item in the collection..
12629 first : function(){
12630 return this.items[0];
12634 * Returns the last item in the collection.
12635 * @return {Object} the last item in the collection..
12638 return this.items[this.length-1];
12641 _sort : function(property, dir, fn){
12642 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12643 fn = fn || function(a, b){
12646 var c = [], k = this.keys, items = this.items;
12647 for(var i = 0, len = items.length; i < len; i++){
12648 c[c.length] = {key: k[i], value: items[i], index: i};
12650 c.sort(function(a, b){
12651 var v = fn(a[property], b[property]) * dsc;
12653 v = (a.index < b.index ? -1 : 1);
12657 for(var i = 0, len = c.length; i < len; i++){
12658 items[i] = c[i].value;
12661 this.fireEvent("sort", this);
12665 * Sorts this collection with the passed comparison function
12666 * @param {String} direction (optional) "ASC" or "DESC"
12667 * @param {Function} fn (optional) comparison function
12669 sort : function(dir, fn){
12670 this._sort("value", dir, fn);
12674 * Sorts this collection by keys
12675 * @param {String} direction (optional) "ASC" or "DESC"
12676 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12678 keySort : function(dir, fn){
12679 this._sort("key", dir, fn || function(a, b){
12680 return String(a).toUpperCase()-String(b).toUpperCase();
12685 * Returns a range of items in this collection
12686 * @param {Number} startIndex (optional) defaults to 0
12687 * @param {Number} endIndex (optional) default to the last item
12688 * @return {Array} An array of items
12690 getRange : function(start, end){
12691 var items = this.items;
12692 if(items.length < 1){
12695 start = start || 0;
12696 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12699 for(var i = start; i <= end; i++) {
12700 r[r.length] = items[i];
12703 for(var i = start; i >= end; i--) {
12704 r[r.length] = items[i];
12711 * Filter the <i>objects</i> in this collection by a specific property.
12712 * Returns a new collection that has been filtered.
12713 * @param {String} property A property on your objects
12714 * @param {String/RegExp} value Either string that the property values
12715 * should start with or a RegExp to test against the property
12716 * @return {MixedCollection} The new filtered collection
12718 filter : function(property, value){
12719 if(!value.exec){ // not a regex
12720 value = String(value);
12721 if(value.length == 0){
12722 return this.clone();
12724 value = new RegExp("^" + Roo.escapeRe(value), "i");
12726 return this.filterBy(function(o){
12727 return o && value.test(o[property]);
12732 * Filter by a function. * Returns a new collection that has been filtered.
12733 * The passed function will be called with each
12734 * object in the collection. If the function returns true, the value is included
12735 * otherwise it is filtered.
12736 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12737 * @param {Object} scope (optional) The scope of the function (defaults to this)
12738 * @return {MixedCollection} The new filtered collection
12740 filterBy : function(fn, scope){
12741 var r = new Roo.util.MixedCollection();
12742 r.getKey = this.getKey;
12743 var k = this.keys, it = this.items;
12744 for(var i = 0, len = it.length; i < len; i++){
12745 if(fn.call(scope||this, it[i], k[i])){
12746 r.add(k[i], it[i]);
12753 * Creates a duplicate of this collection
12754 * @return {MixedCollection}
12756 clone : function(){
12757 var r = new Roo.util.MixedCollection();
12758 var k = this.keys, it = this.items;
12759 for(var i = 0, len = it.length; i < len; i++){
12760 r.add(k[i], it[i]);
12762 r.getKey = this.getKey;
12767 * Returns the item associated with the passed key or index.
12769 * @param {String/Number} key The key or index of the item.
12770 * @return {Object} The item associated with the passed key.
12772 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12774 * Ext JS Library 1.1.1
12775 * Copyright(c) 2006-2007, Ext JS, LLC.
12777 * Originally Released Under LGPL - original licence link has changed is not relivant.
12780 * <script type="text/javascript">
12783 * @class Roo.util.JSON
12784 * Modified version of Douglas Crockford"s json.js that doesn"t
12785 * mess with the Object prototype
12786 * http://www.json.org/js.html
12789 Roo.util.JSON = new (function(){
12790 var useHasOwn = {}.hasOwnProperty ? true : false;
12792 // crashes Safari in some instances
12793 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12795 var pad = function(n) {
12796 return n < 10 ? "0" + n : n;
12809 var encodeString = function(s){
12810 if (/["\\\x00-\x1f]/.test(s)) {
12811 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12816 c = b.charCodeAt();
12818 Math.floor(c / 16).toString(16) +
12819 (c % 16).toString(16);
12822 return '"' + s + '"';
12825 var encodeArray = function(o){
12826 var a = ["["], b, i, l = o.length, v;
12827 for (i = 0; i < l; i += 1) {
12829 switch (typeof v) {
12838 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12846 var encodeDate = function(o){
12847 return '"' + o.getFullYear() + "-" +
12848 pad(o.getMonth() + 1) + "-" +
12849 pad(o.getDate()) + "T" +
12850 pad(o.getHours()) + ":" +
12851 pad(o.getMinutes()) + ":" +
12852 pad(o.getSeconds()) + '"';
12856 * Encodes an Object, Array or other value
12857 * @param {Mixed} o The variable to encode
12858 * @return {String} The JSON string
12860 this.encode = function(o)
12862 // should this be extended to fully wrap stringify..
12864 if(typeof o == "undefined" || o === null){
12866 }else if(o instanceof Array){
12867 return encodeArray(o);
12868 }else if(o instanceof Date){
12869 return encodeDate(o);
12870 }else if(typeof o == "string"){
12871 return encodeString(o);
12872 }else if(typeof o == "number"){
12873 return isFinite(o) ? String(o) : "null";
12874 }else if(typeof o == "boolean"){
12877 var a = ["{"], b, i, v;
12879 if(!useHasOwn || o.hasOwnProperty(i)) {
12881 switch (typeof v) {
12890 a.push(this.encode(i), ":",
12891 v === null ? "null" : this.encode(v));
12902 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12903 * @param {String} json The JSON string
12904 * @return {Object} The resulting object
12906 this.decode = function(json){
12908 return /** eval:var:json */ eval("(" + json + ')');
12912 * Shorthand for {@link Roo.util.JSON#encode}
12913 * @member Roo encode
12915 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
12917 * Shorthand for {@link Roo.util.JSON#decode}
12918 * @member Roo decode
12920 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
12923 * Ext JS Library 1.1.1
12924 * Copyright(c) 2006-2007, Ext JS, LLC.
12926 * Originally Released Under LGPL - original licence link has changed is not relivant.
12929 * <script type="text/javascript">
12933 * @class Roo.util.Format
12934 * Reusable data formatting functions
12937 Roo.util.Format = function(){
12938 var trimRe = /^\s+|\s+$/g;
12941 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12942 * @param {String} value The string to truncate
12943 * @param {Number} length The maximum length to allow before truncating
12944 * @return {String} The converted text
12946 ellipsis : function(value, len){
12947 if(value && value.length > len){
12948 return value.substr(0, len-3)+"...";
12954 * Checks a reference and converts it to empty string if it is undefined
12955 * @param {Mixed} value Reference to check
12956 * @return {Mixed} Empty string if converted, otherwise the original value
12958 undef : function(value){
12959 return typeof value != "undefined" ? value : "";
12963 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12964 * @param {String} value The string to encode
12965 * @return {String} The encoded text
12967 htmlEncode : function(value){
12968 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12972 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12973 * @param {String} value The string to decode
12974 * @return {String} The decoded text
12976 htmlDecode : function(value){
12977 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12981 * Trims any whitespace from either side of a string
12982 * @param {String} value The text to trim
12983 * @return {String} The trimmed text
12985 trim : function(value){
12986 return String(value).replace(trimRe, "");
12990 * Returns a substring from within an original string
12991 * @param {String} value The original text
12992 * @param {Number} start The start index of the substring
12993 * @param {Number} length The length of the substring
12994 * @return {String} The substring
12996 substr : function(value, start, length){
12997 return String(value).substr(start, length);
13001 * Converts a string to all lower case letters
13002 * @param {String} value The text to convert
13003 * @return {String} The converted text
13005 lowercase : function(value){
13006 return String(value).toLowerCase();
13010 * Converts a string to all upper case letters
13011 * @param {String} value The text to convert
13012 * @return {String} The converted text
13014 uppercase : function(value){
13015 return String(value).toUpperCase();
13019 * Converts the first character only of a string to upper case
13020 * @param {String} value The text to convert
13021 * @return {String} The converted text
13023 capitalize : function(value){
13024 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13028 call : function(value, fn){
13029 if(arguments.length > 2){
13030 var args = Array.prototype.slice.call(arguments, 2);
13031 args.unshift(value);
13033 return /** eval:var:value */ eval(fn).apply(window, args);
13035 /** eval:var:value */
13036 return /** eval:var:value */ eval(fn).call(window, value);
13042 * safer version of Math.toFixed..??/
13043 * @param {Number/String} value The numeric value to format
13044 * @param {Number/String} value Decimal places
13045 * @return {String} The formatted currency string
13047 toFixed : function(v, n)
13049 // why not use to fixed - precision is buggered???
13051 return Math.round(v-0);
13053 var fact = Math.pow(10,n+1);
13054 v = (Math.round((v-0)*fact))/fact;
13055 var z = (''+fact).substring(2);
13056 if (v == Math.floor(v)) {
13057 return Math.floor(v) + '.' + z;
13060 // now just padd decimals..
13061 var ps = String(v).split('.');
13062 var fd = (ps[1] + z);
13063 var r = fd.substring(0,n);
13064 var rm = fd.substring(n);
13066 return ps[0] + '.' + r;
13068 r*=1; // turn it into a number;
13070 if (String(r).length != n) {
13073 r = String(r).substring(1); // chop the end off.
13076 return ps[0] + '.' + r;
13081 * Format a number as US currency
13082 * @param {Number/String} value The numeric value to format
13083 * @return {String} The formatted currency string
13085 usMoney : function(v){
13086 v = (Math.round((v-0)*100))/100;
13087 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13089 var ps = v.split('.');
13091 var sub = ps[1] ? '.'+ ps[1] : '.00';
13092 var r = /(\d+)(\d{3})/;
13093 while (r.test(whole)) {
13094 whole = whole.replace(r, '$1' + ',' + '$2');
13096 return "$" + whole + sub ;
13100 * Parse a value into a formatted date using the specified format pattern.
13101 * @param {Mixed} value The value to format
13102 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13103 * @return {String} The formatted date string
13105 date : function(v, format){
13109 if(!(v instanceof Date)){
13110 v = new Date(Date.parse(v));
13112 return v.dateFormat(format || "m/d/Y");
13116 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13117 * @param {String} format Any valid date format string
13118 * @return {Function} The date formatting function
13120 dateRenderer : function(format){
13121 return function(v){
13122 return Roo.util.Format.date(v, format);
13127 stripTagsRE : /<\/?[^>]+>/gi,
13130 * Strips all HTML tags
13131 * @param {Mixed} value The text from which to strip tags
13132 * @return {String} The stripped text
13134 stripTags : function(v){
13135 return !v ? v : String(v).replace(this.stripTagsRE, "");
13140 * Ext JS Library 1.1.1
13141 * Copyright(c) 2006-2007, Ext JS, LLC.
13143 * Originally Released Under LGPL - original licence link has changed is not relivant.
13146 * <script type="text/javascript">
13153 * @class Roo.MasterTemplate
13154 * @extends Roo.Template
13155 * Provides a template that can have child templates. The syntax is:
13157 var t = new Roo.MasterTemplate(
13158 '<select name="{name}">',
13159 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13162 t.add('options', {value: 'foo', text: 'bar'});
13163 // or you can add multiple child elements in one shot
13164 t.addAll('options', [
13165 {value: 'foo', text: 'bar'},
13166 {value: 'foo2', text: 'bar2'},
13167 {value: 'foo3', text: 'bar3'}
13169 // then append, applying the master template values
13170 t.append('my-form', {name: 'my-select'});
13172 * A name attribute for the child template is not required if you have only one child
13173 * template or you want to refer to them by index.
13175 Roo.MasterTemplate = function(){
13176 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13177 this.originalHtml = this.html;
13179 var m, re = this.subTemplateRe;
13182 while(m = re.exec(this.html)){
13183 var name = m[1], content = m[2];
13188 tpl : new Roo.Template(content)
13191 st[name] = st[subIndex];
13193 st[subIndex].tpl.compile();
13194 st[subIndex].tpl.call = this.call.createDelegate(this);
13197 this.subCount = subIndex;
13200 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13202 * The regular expression used to match sub templates
13206 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13209 * Applies the passed values to a child template.
13210 * @param {String/Number} name (optional) The name or index of the child template
13211 * @param {Array/Object} values The values to be applied to the template
13212 * @return {MasterTemplate} this
13214 add : function(name, values){
13215 if(arguments.length == 1){
13216 values = arguments[0];
13219 var s = this.subs[name];
13220 s.buffer[s.buffer.length] = s.tpl.apply(values);
13225 * Applies all the passed values to a child template.
13226 * @param {String/Number} name (optional) The name or index of the child template
13227 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13228 * @param {Boolean} reset (optional) True to reset the template first
13229 * @return {MasterTemplate} this
13231 fill : function(name, values, reset){
13233 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13241 for(var i = 0, len = values.length; i < len; i++){
13242 this.add(name, values[i]);
13248 * Resets the template for reuse
13249 * @return {MasterTemplate} this
13251 reset : function(){
13253 for(var i = 0; i < this.subCount; i++){
13259 applyTemplate : function(values){
13261 var replaceIndex = -1;
13262 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13263 return s[++replaceIndex].buffer.join("");
13265 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13268 apply : function(){
13269 return this.applyTemplate.apply(this, arguments);
13272 compile : function(){return this;}
13276 * Alias for fill().
13279 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13281 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13282 * var tpl = Roo.MasterTemplate.from('element-id');
13283 * @param {String/HTMLElement} el
13284 * @param {Object} config
13287 Roo.MasterTemplate.from = function(el, config){
13288 el = Roo.getDom(el);
13289 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13292 * Ext JS Library 1.1.1
13293 * Copyright(c) 2006-2007, Ext JS, LLC.
13295 * Originally Released Under LGPL - original licence link has changed is not relivant.
13298 * <script type="text/javascript">
13303 * @class Roo.util.CSS
13304 * Utility class for manipulating CSS rules
13307 Roo.util.CSS = function(){
13309 var doc = document;
13311 var camelRe = /(-[a-z])/gi;
13312 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13316 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13317 * tag and appended to the HEAD of the document.
13318 * @param {String|Object} cssText The text containing the css rules
13319 * @param {String} id An id to add to the stylesheet for later removal
13320 * @return {StyleSheet}
13322 createStyleSheet : function(cssText, id){
13324 var head = doc.getElementsByTagName("head")[0];
13325 var nrules = doc.createElement("style");
13326 nrules.setAttribute("type", "text/css");
13328 nrules.setAttribute("id", id);
13330 if (typeof(cssText) != 'string') {
13331 // support object maps..
13332 // not sure if this a good idea..
13333 // perhaps it should be merged with the general css handling
13334 // and handle js style props.
13335 var cssTextNew = [];
13336 for(var n in cssText) {
13338 for(var k in cssText[n]) {
13339 citems.push( k + ' : ' +cssText[n][k] + ';' );
13341 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13344 cssText = cssTextNew.join("\n");
13350 head.appendChild(nrules);
13351 ss = nrules.styleSheet;
13352 ss.cssText = cssText;
13355 nrules.appendChild(doc.createTextNode(cssText));
13357 nrules.cssText = cssText;
13359 head.appendChild(nrules);
13360 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13362 this.cacheStyleSheet(ss);
13367 * Removes a style or link tag by id
13368 * @param {String} id The id of the tag
13370 removeStyleSheet : function(id){
13371 var existing = doc.getElementById(id);
13373 existing.parentNode.removeChild(existing);
13378 * Dynamically swaps an existing stylesheet reference for a new one
13379 * @param {String} id The id of an existing link tag to remove
13380 * @param {String} url The href of the new stylesheet to include
13382 swapStyleSheet : function(id, url){
13383 this.removeStyleSheet(id);
13384 var ss = doc.createElement("link");
13385 ss.setAttribute("rel", "stylesheet");
13386 ss.setAttribute("type", "text/css");
13387 ss.setAttribute("id", id);
13388 ss.setAttribute("href", url);
13389 doc.getElementsByTagName("head")[0].appendChild(ss);
13393 * Refresh the rule cache if you have dynamically added stylesheets
13394 * @return {Object} An object (hash) of rules indexed by selector
13396 refreshCache : function(){
13397 return this.getRules(true);
13401 cacheStyleSheet : function(stylesheet){
13405 try{// try catch for cross domain access issue
13406 var ssRules = stylesheet.cssRules || stylesheet.rules;
13407 for(var j = ssRules.length-1; j >= 0; --j){
13408 rules[ssRules[j].selectorText] = ssRules[j];
13414 * Gets all css rules for the document
13415 * @param {Boolean} refreshCache true to refresh the internal cache
13416 * @return {Object} An object (hash) of rules indexed by selector
13418 getRules : function(refreshCache){
13419 if(rules == null || refreshCache){
13421 var ds = doc.styleSheets;
13422 for(var i =0, len = ds.length; i < len; i++){
13424 this.cacheStyleSheet(ds[i]);
13432 * Gets an an individual CSS rule by selector(s)
13433 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13434 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13435 * @return {CSSRule} The CSS rule or null if one is not found
13437 getRule : function(selector, refreshCache){
13438 var rs = this.getRules(refreshCache);
13439 if(!(selector instanceof Array)){
13440 return rs[selector];
13442 for(var i = 0; i < selector.length; i++){
13443 if(rs[selector[i]]){
13444 return rs[selector[i]];
13452 * Updates a rule property
13453 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13454 * @param {String} property The css property
13455 * @param {String} value The new value for the property
13456 * @return {Boolean} true If a rule was found and updated
13458 updateRule : function(selector, property, value){
13459 if(!(selector instanceof Array)){
13460 var rule = this.getRule(selector);
13462 rule.style[property.replace(camelRe, camelFn)] = value;
13466 for(var i = 0; i < selector.length; i++){
13467 if(this.updateRule(selector[i], property, value)){
13477 * Ext JS Library 1.1.1
13478 * Copyright(c) 2006-2007, Ext JS, LLC.
13480 * Originally Released Under LGPL - original licence link has changed is not relivant.
13483 * <script type="text/javascript">
13489 * @class Roo.util.ClickRepeater
13490 * @extends Roo.util.Observable
13492 * A wrapper class which can be applied to any element. Fires a "click" event while the
13493 * mouse is pressed. The interval between firings may be specified in the config but
13494 * defaults to 10 milliseconds.
13496 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13498 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13499 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13500 * Similar to an autorepeat key delay.
13501 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13502 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13503 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13504 * "interval" and "delay" are ignored. "immediate" is honored.
13505 * @cfg {Boolean} preventDefault True to prevent the default click event
13506 * @cfg {Boolean} stopDefault True to stop the default click event
13509 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13510 * 2007-02-02 jvs Renamed to ClickRepeater
13511 * 2007-02-03 jvs Modifications for FF Mac and Safari
13514 * @param {String/HTMLElement/Element} el The element to listen on
13515 * @param {Object} config
13517 Roo.util.ClickRepeater = function(el, config)
13519 this.el = Roo.get(el);
13520 this.el.unselectable();
13522 Roo.apply(this, config);
13527 * Fires when the mouse button is depressed.
13528 * @param {Roo.util.ClickRepeater} this
13530 "mousedown" : true,
13533 * Fires on a specified interval during the time the element is pressed.
13534 * @param {Roo.util.ClickRepeater} this
13539 * Fires when the mouse key is released.
13540 * @param {Roo.util.ClickRepeater} this
13545 this.el.on("mousedown", this.handleMouseDown, this);
13546 if(this.preventDefault || this.stopDefault){
13547 this.el.on("click", function(e){
13548 if(this.preventDefault){
13549 e.preventDefault();
13551 if(this.stopDefault){
13557 // allow inline handler
13559 this.on("click", this.handler, this.scope || this);
13562 Roo.util.ClickRepeater.superclass.constructor.call(this);
13565 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13568 preventDefault : true,
13569 stopDefault : false,
13573 handleMouseDown : function(){
13574 clearTimeout(this.timer);
13576 if(this.pressClass){
13577 this.el.addClass(this.pressClass);
13579 this.mousedownTime = new Date();
13581 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13582 this.el.on("mouseout", this.handleMouseOut, this);
13584 this.fireEvent("mousedown", this);
13585 this.fireEvent("click", this);
13587 this.timer = this.click.defer(this.delay || this.interval, this);
13591 click : function(){
13592 this.fireEvent("click", this);
13593 this.timer = this.click.defer(this.getInterval(), this);
13597 getInterval: function(){
13598 if(!this.accelerate){
13599 return this.interval;
13601 var pressTime = this.mousedownTime.getElapsed();
13602 if(pressTime < 500){
13604 }else if(pressTime < 1700){
13606 }else if(pressTime < 2600){
13608 }else if(pressTime < 3500){
13610 }else if(pressTime < 4400){
13612 }else if(pressTime < 5300){
13614 }else if(pressTime < 6200){
13622 handleMouseOut : function(){
13623 clearTimeout(this.timer);
13624 if(this.pressClass){
13625 this.el.removeClass(this.pressClass);
13627 this.el.on("mouseover", this.handleMouseReturn, this);
13631 handleMouseReturn : function(){
13632 this.el.un("mouseover", this.handleMouseReturn);
13633 if(this.pressClass){
13634 this.el.addClass(this.pressClass);
13640 handleMouseUp : function(){
13641 clearTimeout(this.timer);
13642 this.el.un("mouseover", this.handleMouseReturn);
13643 this.el.un("mouseout", this.handleMouseOut);
13644 Roo.get(document).un("mouseup", this.handleMouseUp);
13645 this.el.removeClass(this.pressClass);
13646 this.fireEvent("mouseup", this);
13650 * Ext JS Library 1.1.1
13651 * Copyright(c) 2006-2007, Ext JS, LLC.
13653 * Originally Released Under LGPL - original licence link has changed is not relivant.
13656 * <script type="text/javascript">
13661 * @class Roo.KeyNav
13662 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13663 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13664 * way to implement custom navigation schemes for any UI component.</p>
13665 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13666 * pageUp, pageDown, del, home, end. Usage:</p>
13668 var nav = new Roo.KeyNav("my-element", {
13669 "left" : function(e){
13670 this.moveLeft(e.ctrlKey);
13672 "right" : function(e){
13673 this.moveRight(e.ctrlKey);
13675 "enter" : function(e){
13682 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13683 * @param {Object} config The config
13685 Roo.KeyNav = function(el, config){
13686 this.el = Roo.get(el);
13687 Roo.apply(this, config);
13688 if(!this.disabled){
13689 this.disabled = true;
13694 Roo.KeyNav.prototype = {
13696 * @cfg {Boolean} disabled
13697 * True to disable this KeyNav instance (defaults to false)
13701 * @cfg {String} defaultEventAction
13702 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13703 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13704 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13706 defaultEventAction: "stopEvent",
13708 * @cfg {Boolean} forceKeyDown
13709 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13710 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13711 * handle keydown instead of keypress.
13713 forceKeyDown : false,
13716 prepareEvent : function(e){
13717 var k = e.getKey();
13718 var h = this.keyToHandler[k];
13719 //if(h && this[h]){
13720 // e.stopPropagation();
13722 if(Roo.isSafari && h && k >= 37 && k <= 40){
13728 relay : function(e){
13729 var k = e.getKey();
13730 var h = this.keyToHandler[k];
13732 if(this.doRelay(e, this[h], h) !== true){
13733 e[this.defaultEventAction]();
13739 doRelay : function(e, h, hname){
13740 return h.call(this.scope || this, e);
13743 // possible handlers
13757 // quick lookup hash
13774 * Enable this KeyNav
13776 enable: function(){
13778 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13779 // the EventObject will normalize Safari automatically
13780 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13781 this.el.on("keydown", this.relay, this);
13783 this.el.on("keydown", this.prepareEvent, this);
13784 this.el.on("keypress", this.relay, this);
13786 this.disabled = false;
13791 * Disable this KeyNav
13793 disable: function(){
13794 if(!this.disabled){
13795 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13796 this.el.un("keydown", this.relay);
13798 this.el.un("keydown", this.prepareEvent);
13799 this.el.un("keypress", this.relay);
13801 this.disabled = true;
13806 * Ext JS Library 1.1.1
13807 * Copyright(c) 2006-2007, Ext JS, LLC.
13809 * Originally Released Under LGPL - original licence link has changed is not relivant.
13812 * <script type="text/javascript">
13817 * @class Roo.KeyMap
13818 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13819 * The constructor accepts the same config object as defined by {@link #addBinding}.
13820 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13821 * combination it will call the function with this signature (if the match is a multi-key
13822 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13823 * A KeyMap can also handle a string representation of keys.<br />
13826 // map one key by key code
13827 var map = new Roo.KeyMap("my-element", {
13828 key: 13, // or Roo.EventObject.ENTER
13833 // map multiple keys to one action by string
13834 var map = new Roo.KeyMap("my-element", {
13840 // map multiple keys to multiple actions by strings and array of codes
13841 var map = new Roo.KeyMap("my-element", [
13844 fn: function(){ alert("Return was pressed"); }
13847 fn: function(){ alert('a, b or c was pressed'); }
13852 fn: function(){ alert('Control + shift + tab was pressed.'); }
13856 * <b>Note: A KeyMap starts enabled</b>
13858 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13859 * @param {Object} config The config (see {@link #addBinding})
13860 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13862 Roo.KeyMap = function(el, config, eventName){
13863 this.el = Roo.get(el);
13864 this.eventName = eventName || "keydown";
13865 this.bindings = [];
13867 this.addBinding(config);
13872 Roo.KeyMap.prototype = {
13874 * True to stop the event from bubbling and prevent the default browser action if the
13875 * key was handled by the KeyMap (defaults to false)
13881 * Add a new binding to this KeyMap. The following config object properties are supported:
13883 Property Type Description
13884 ---------- --------------- ----------------------------------------------------------------------
13885 key String/Array A single keycode or an array of keycodes to handle
13886 shift Boolean True to handle key only when shift is pressed (defaults to false)
13887 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13888 alt Boolean True to handle key only when alt is pressed (defaults to false)
13889 fn Function The function to call when KeyMap finds the expected key combination
13890 scope Object The scope of the callback function
13896 var map = new Roo.KeyMap(document, {
13897 key: Roo.EventObject.ENTER,
13902 //Add a new binding to the existing KeyMap later
13910 * @param {Object/Array} config A single KeyMap config or an array of configs
13912 addBinding : function(config){
13913 if(config instanceof Array){
13914 for(var i = 0, len = config.length; i < len; i++){
13915 this.addBinding(config[i]);
13919 var keyCode = config.key,
13920 shift = config.shift,
13921 ctrl = config.ctrl,
13924 scope = config.scope;
13925 if(typeof keyCode == "string"){
13927 var keyString = keyCode.toUpperCase();
13928 for(var j = 0, len = keyString.length; j < len; j++){
13929 ks.push(keyString.charCodeAt(j));
13933 var keyArray = keyCode instanceof Array;
13934 var handler = function(e){
13935 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13936 var k = e.getKey();
13938 for(var i = 0, len = keyCode.length; i < len; i++){
13939 if(keyCode[i] == k){
13940 if(this.stopEvent){
13943 fn.call(scope || window, k, e);
13949 if(this.stopEvent){
13952 fn.call(scope || window, k, e);
13957 this.bindings.push(handler);
13961 * Shorthand for adding a single key listener
13962 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13963 * following options:
13964 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13965 * @param {Function} fn The function to call
13966 * @param {Object} scope (optional) The scope of the function
13968 on : function(key, fn, scope){
13969 var keyCode, shift, ctrl, alt;
13970 if(typeof key == "object" && !(key instanceof Array)){
13989 handleKeyDown : function(e){
13990 if(this.enabled){ //just in case
13991 var b = this.bindings;
13992 for(var i = 0, len = b.length; i < len; i++){
13993 b[i].call(this, e);
13999 * Returns true if this KeyMap is enabled
14000 * @return {Boolean}
14002 isEnabled : function(){
14003 return this.enabled;
14007 * Enables this KeyMap
14009 enable: function(){
14011 this.el.on(this.eventName, this.handleKeyDown, this);
14012 this.enabled = true;
14017 * Disable this KeyMap
14019 disable: function(){
14021 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14022 this.enabled = false;
14027 * Ext JS Library 1.1.1
14028 * Copyright(c) 2006-2007, Ext JS, LLC.
14030 * Originally Released Under LGPL - original licence link has changed is not relivant.
14033 * <script type="text/javascript">
14038 * @class Roo.util.TextMetrics
14039 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14040 * wide, in pixels, a given block of text will be.
14043 Roo.util.TextMetrics = function(){
14047 * Measures the size of the specified text
14048 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14049 * that can affect the size of the rendered text
14050 * @param {String} text The text to measure
14051 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14052 * in order to accurately measure the text height
14053 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14055 measure : function(el, text, fixedWidth){
14057 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14060 shared.setFixedWidth(fixedWidth || 'auto');
14061 return shared.getSize(text);
14065 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14066 * the overhead of multiple calls to initialize the style properties on each measurement.
14067 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14068 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14069 * in order to accurately measure the text height
14070 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14072 createInstance : function(el, fixedWidth){
14073 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14080 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14081 var ml = new Roo.Element(document.createElement('div'));
14082 document.body.appendChild(ml.dom);
14083 ml.position('absolute');
14084 ml.setLeftTop(-1000, -1000);
14088 ml.setWidth(fixedWidth);
14093 * Returns the size of the specified text based on the internal element's style and width properties
14094 * @memberOf Roo.util.TextMetrics.Instance#
14095 * @param {String} text The text to measure
14096 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14098 getSize : function(text){
14100 var s = ml.getSize();
14106 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14107 * that can affect the size of the rendered text
14108 * @memberOf Roo.util.TextMetrics.Instance#
14109 * @param {String/HTMLElement} el The element, dom node or id
14111 bind : function(el){
14113 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14118 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14119 * to set a fixed width in order to accurately measure the text height.
14120 * @memberOf Roo.util.TextMetrics.Instance#
14121 * @param {Number} width The width to set on the element
14123 setFixedWidth : function(width){
14124 ml.setWidth(width);
14128 * Returns the measured width of the specified text
14129 * @memberOf Roo.util.TextMetrics.Instance#
14130 * @param {String} text The text to measure
14131 * @return {Number} width The width in pixels
14133 getWidth : function(text){
14134 ml.dom.style.width = 'auto';
14135 return this.getSize(text).width;
14139 * Returns the measured height of the specified text. For multiline text, be sure to call
14140 * {@link #setFixedWidth} if necessary.
14141 * @memberOf Roo.util.TextMetrics.Instance#
14142 * @param {String} text The text to measure
14143 * @return {Number} height The height in pixels
14145 getHeight : function(text){
14146 return this.getSize(text).height;
14150 instance.bind(bindTo);
14155 // backwards compat
14156 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14158 * Ext JS Library 1.1.1
14159 * Copyright(c) 2006-2007, Ext JS, LLC.
14161 * Originally Released Under LGPL - original licence link has changed is not relivant.
14164 * <script type="text/javascript">
14168 * @class Roo.state.Provider
14169 * Abstract base class for state provider implementations. This class provides methods
14170 * for encoding and decoding <b>typed</b> variables including dates and defines the
14171 * Provider interface.
14173 Roo.state.Provider = function(){
14175 * @event statechange
14176 * Fires when a state change occurs.
14177 * @param {Provider} this This state provider
14178 * @param {String} key The state key which was changed
14179 * @param {String} value The encoded value for the state
14182 "statechange": true
14185 Roo.state.Provider.superclass.constructor.call(this);
14187 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14189 * Returns the current value for a key
14190 * @param {String} name The key name
14191 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14192 * @return {Mixed} The state data
14194 get : function(name, defaultValue){
14195 return typeof this.state[name] == "undefined" ?
14196 defaultValue : this.state[name];
14200 * Clears a value from the state
14201 * @param {String} name The key name
14203 clear : function(name){
14204 delete this.state[name];
14205 this.fireEvent("statechange", this, name, null);
14209 * Sets the value for a key
14210 * @param {String} name The key name
14211 * @param {Mixed} value The value to set
14213 set : function(name, value){
14214 this.state[name] = value;
14215 this.fireEvent("statechange", this, name, value);
14219 * Decodes a string previously encoded with {@link #encodeValue}.
14220 * @param {String} value The value to decode
14221 * @return {Mixed} The decoded value
14223 decodeValue : function(cookie){
14224 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14225 var matches = re.exec(unescape(cookie));
14226 if(!matches || !matches[1]) return; // non state cookie
14227 var type = matches[1];
14228 var v = matches[2];
14231 return parseFloat(v);
14233 return new Date(Date.parse(v));
14238 var values = v.split("^");
14239 for(var i = 0, len = values.length; i < len; i++){
14240 all.push(this.decodeValue(values[i]));
14245 var values = v.split("^");
14246 for(var i = 0, len = values.length; i < len; i++){
14247 var kv = values[i].split("=");
14248 all[kv[0]] = this.decodeValue(kv[1]);
14257 * Encodes a value including type information. Decode with {@link #decodeValue}.
14258 * @param {Mixed} value The value to encode
14259 * @return {String} The encoded value
14261 encodeValue : function(v){
14263 if(typeof v == "number"){
14265 }else if(typeof v == "boolean"){
14266 enc = "b:" + (v ? "1" : "0");
14267 }else if(v instanceof Date){
14268 enc = "d:" + v.toGMTString();
14269 }else if(v instanceof Array){
14271 for(var i = 0, len = v.length; i < len; i++){
14272 flat += this.encodeValue(v[i]);
14273 if(i != len-1) flat += "^";
14276 }else if(typeof v == "object"){
14279 if(typeof v[key] != "function"){
14280 flat += key + "=" + this.encodeValue(v[key]) + "^";
14283 enc = "o:" + flat.substring(0, flat.length-1);
14287 return escape(enc);
14293 * Ext JS Library 1.1.1
14294 * Copyright(c) 2006-2007, Ext JS, LLC.
14296 * Originally Released Under LGPL - original licence link has changed is not relivant.
14299 * <script type="text/javascript">
14302 * @class Roo.state.Manager
14303 * This is the global state manager. By default all components that are "state aware" check this class
14304 * for state information if you don't pass them a custom state provider. In order for this class
14305 * to be useful, it must be initialized with a provider when your application initializes.
14307 // in your initialization function
14309 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14311 // supposed you have a {@link Roo.BorderLayout}
14312 var layout = new Roo.BorderLayout(...);
14313 layout.restoreState();
14314 // or a {Roo.BasicDialog}
14315 var dialog = new Roo.BasicDialog(...);
14316 dialog.restoreState();
14320 Roo.state.Manager = function(){
14321 var provider = new Roo.state.Provider();
14325 * Configures the default state provider for your application
14326 * @param {Provider} stateProvider The state provider to set
14328 setProvider : function(stateProvider){
14329 provider = stateProvider;
14333 * Returns the current value for a key
14334 * @param {String} name The key name
14335 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14336 * @return {Mixed} The state data
14338 get : function(key, defaultValue){
14339 return provider.get(key, defaultValue);
14343 * Sets the value for a key
14344 * @param {String} name The key name
14345 * @param {Mixed} value The state data
14347 set : function(key, value){
14348 provider.set(key, value);
14352 * Clears a value from the state
14353 * @param {String} name The key name
14355 clear : function(key){
14356 provider.clear(key);
14360 * Gets the currently configured state provider
14361 * @return {Provider} The state provider
14363 getProvider : function(){
14370 * Ext JS Library 1.1.1
14371 * Copyright(c) 2006-2007, Ext JS, LLC.
14373 * Originally Released Under LGPL - original licence link has changed is not relivant.
14376 * <script type="text/javascript">
14379 * @class Roo.state.CookieProvider
14380 * @extends Roo.state.Provider
14381 * The default Provider implementation which saves state via cookies.
14384 var cp = new Roo.state.CookieProvider({
14386 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14387 domain: "roojs.com"
14389 Roo.state.Manager.setProvider(cp);
14391 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14392 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14393 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14394 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14395 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14396 * domain the page is running on including the 'www' like 'www.roojs.com')
14397 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14399 * Create a new CookieProvider
14400 * @param {Object} config The configuration object
14402 Roo.state.CookieProvider = function(config){
14403 Roo.state.CookieProvider.superclass.constructor.call(this);
14405 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14406 this.domain = null;
14407 this.secure = false;
14408 Roo.apply(this, config);
14409 this.state = this.readCookies();
14412 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14414 set : function(name, value){
14415 if(typeof value == "undefined" || value === null){
14419 this.setCookie(name, value);
14420 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14424 clear : function(name){
14425 this.clearCookie(name);
14426 Roo.state.CookieProvider.superclass.clear.call(this, name);
14430 readCookies : function(){
14432 var c = document.cookie + ";";
14433 var re = /\s?(.*?)=(.*?);/g;
14435 while((matches = re.exec(c)) != null){
14436 var name = matches[1];
14437 var value = matches[2];
14438 if(name && name.substring(0,3) == "ys-"){
14439 cookies[name.substr(3)] = this.decodeValue(value);
14446 setCookie : function(name, value){
14447 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14448 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14449 ((this.path == null) ? "" : ("; path=" + this.path)) +
14450 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14451 ((this.secure == true) ? "; secure" : "");
14455 clearCookie : function(name){
14456 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14457 ((this.path == null) ? "" : ("; path=" + this.path)) +
14458 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14459 ((this.secure == true) ? "; secure" : "");