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..
4033 if (typeof Range.prototype.createContextualFragment == "undefined") {
4035 if (typeof Range != "undefined" && typeof Range.prototype.createContextualFragment == "undefined") {
4036 >>>>>>> cba88e023db3bc6c12affc2e25a149cdac04fd17
4037 Range.prototype.createContextualFragment = function (html) {
4038 var doc = window.document;
4039 var container = doc.createElement("div");
4040 container.innerHTML = html;
4041 var frag = doc.createDocumentFragment(), n;
4042 while ((n = container.firstChild)) {
4043 frag.appendChild(n);
4050 * @class Roo.DomHelper
4051 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4052 * 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>.
4055 Roo.DomHelper = function(){
4056 var tempTableEl = null;
4057 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4058 var tableRe = /^table|tbody|tr|td$/i;
4060 // build as innerHTML where available
4062 var createHtml = function(o){
4063 if(typeof o == 'string'){
4072 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4073 if(attr == "style"){
4075 if(typeof s == "function"){
4078 if(typeof s == "string"){
4079 b += ' style="' + s + '"';
4080 }else if(typeof s == "object"){
4083 if(typeof s[key] != "function"){
4084 b += key + ":" + s[key] + ";";
4091 b += ' class="' + o["cls"] + '"';
4092 }else if(attr == "htmlFor"){
4093 b += ' for="' + o["htmlFor"] + '"';
4095 b += " " + attr + '="' + o[attr] + '"';
4099 if(emptyTags.test(o.tag)){
4103 var cn = o.children || o.cn;
4105 //http://bugs.kde.org/show_bug.cgi?id=71506
4106 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4107 for(var i = 0, len = cn.length; i < len; i++) {
4108 b += createHtml(cn[i], b);
4111 b += createHtml(cn, b);
4117 b += "</" + o.tag + ">";
4124 var createDom = function(o, parentNode){
4126 // defininition craeted..
4128 if (o.ns && o.ns != 'html') {
4130 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4131 xmlns[o.ns] = o.xmlns;
4134 if (typeof(xmlns[o.ns]) == 'undefined') {
4135 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4141 if (typeof(o) == 'string') {
4142 return parentNode.appendChild(document.createTextNode(o));
4144 o.tag = o.tag || div;
4145 if (o.ns && Roo.isIE) {
4147 o.tag = o.ns + ':' + o.tag;
4150 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4151 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4154 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4155 attr == "style" || typeof o[attr] == "function") continue;
4157 if(attr=="cls" && Roo.isIE){
4158 el.className = o["cls"];
4160 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4161 else el[attr] = o[attr];
4164 Roo.DomHelper.applyStyles(el, o.style);
4165 var cn = o.children || o.cn;
4167 //http://bugs.kde.org/show_bug.cgi?id=71506
4168 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4169 for(var i = 0, len = cn.length; i < len; i++) {
4170 createDom(cn[i], el);
4177 el.innerHTML = o.html;
4180 parentNode.appendChild(el);
4185 var ieTable = function(depth, s, h, e){
4186 tempTableEl.innerHTML = [s, h, e].join('');
4187 var i = -1, el = tempTableEl;
4194 // kill repeat to save bytes
4198 tbe = '</tbody>'+te,
4204 * Nasty code for IE's broken table implementation
4206 var insertIntoTable = function(tag, where, el, html){
4208 tempTableEl = document.createElement('div');
4213 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4216 if(where == 'beforebegin'){
4220 before = el.nextSibling;
4223 node = ieTable(4, trs, html, tre);
4225 else if(tag == 'tr'){
4226 if(where == 'beforebegin'){
4229 node = ieTable(3, tbs, html, tbe);
4230 } else if(where == 'afterend'){
4231 before = el.nextSibling;
4233 node = ieTable(3, tbs, html, tbe);
4234 } else{ // INTO a TR
4235 if(where == 'afterbegin'){
4236 before = el.firstChild;
4238 node = ieTable(4, trs, html, tre);
4240 } else if(tag == 'tbody'){
4241 if(where == 'beforebegin'){
4244 node = ieTable(2, ts, html, te);
4245 } else if(where == 'afterend'){
4246 before = el.nextSibling;
4248 node = ieTable(2, ts, html, te);
4250 if(where == 'afterbegin'){
4251 before = el.firstChild;
4253 node = ieTable(3, tbs, html, tbe);
4256 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4259 if(where == 'afterbegin'){
4260 before = el.firstChild;
4262 node = ieTable(2, ts, html, te);
4264 el.insertBefore(node, before);
4269 /** True to force the use of DOM instead of html fragments @type Boolean */
4273 * Returns the markup for the passed Element(s) config
4274 * @param {Object} o The Dom object spec (and children)
4277 markup : function(o){
4278 return createHtml(o);
4282 * Applies a style specification to an element
4283 * @param {String/HTMLElement} el The element to apply styles to
4284 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4285 * a function which returns such a specification.
4287 applyStyles : function(el, styles){
4290 if(typeof styles == "string"){
4291 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4293 while ((matches = re.exec(styles)) != null){
4294 el.setStyle(matches[1], matches[2]);
4296 }else if (typeof styles == "object"){
4297 for (var style in styles){
4298 el.setStyle(style, styles[style]);
4300 }else if (typeof styles == "function"){
4301 Roo.DomHelper.applyStyles(el, styles.call());
4307 * Inserts an HTML fragment into the Dom
4308 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4309 * @param {HTMLElement} el The context element
4310 * @param {String} html The HTML fragmenet
4311 * @return {HTMLElement} The new node
4313 insertHtml : function(where, el, html){
4314 where = where.toLowerCase();
4315 if(el.insertAdjacentHTML){
4316 if(tableRe.test(el.tagName)){
4318 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4324 el.insertAdjacentHTML('BeforeBegin', html);
4325 return el.previousSibling;
4327 el.insertAdjacentHTML('AfterBegin', html);
4328 return el.firstChild;
4330 el.insertAdjacentHTML('BeforeEnd', html);
4331 return el.lastChild;
4333 el.insertAdjacentHTML('AfterEnd', html);
4334 return el.nextSibling;
4336 throw 'Illegal insertion point -> "' + where + '"';
4338 var range = el.ownerDocument.createRange();
4342 range.setStartBefore(el);
4343 frag = range.createContextualFragment(html);
4344 el.parentNode.insertBefore(frag, el);
4345 return el.previousSibling;
4348 range.setStartBefore(el.firstChild);
4349 frag = range.createContextualFragment(html);
4350 el.insertBefore(frag, el.firstChild);
4351 return el.firstChild;
4353 el.innerHTML = html;
4354 return el.firstChild;
4358 range.setStartAfter(el.lastChild);
4359 frag = range.createContextualFragment(html);
4360 el.appendChild(frag);
4361 return el.lastChild;
4363 el.innerHTML = html;
4364 return el.lastChild;
4367 range.setStartAfter(el);
4368 frag = range.createContextualFragment(html);
4369 el.parentNode.insertBefore(frag, el.nextSibling);
4370 return el.nextSibling;
4372 throw 'Illegal insertion point -> "' + where + '"';
4376 * Creates new Dom element(s) and inserts them before el
4377 * @param {String/HTMLElement/Element} el The context element
4378 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4379 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4380 * @return {HTMLElement/Roo.Element} The new node
4382 insertBefore : function(el, o, returnElement){
4383 return this.doInsert(el, o, returnElement, "beforeBegin");
4387 * Creates new Dom element(s) and inserts them after el
4388 * @param {String/HTMLElement/Element} el The context element
4389 * @param {Object} o The Dom object spec (and children)
4390 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4391 * @return {HTMLElement/Roo.Element} The new node
4393 insertAfter : function(el, o, returnElement){
4394 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4398 * Creates new Dom element(s) and inserts them as the first child of el
4399 * @param {String/HTMLElement/Element} el The context element
4400 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4401 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4402 * @return {HTMLElement/Roo.Element} The new node
4404 insertFirst : function(el, o, returnElement){
4405 return this.doInsert(el, o, returnElement, "afterBegin");
4409 doInsert : function(el, o, returnElement, pos, sibling){
4410 el = Roo.getDom(el);
4412 if(this.useDom || o.ns){
4413 newNode = createDom(o, null);
4414 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4416 var html = createHtml(o);
4417 newNode = this.insertHtml(pos, el, html);
4419 return returnElement ? Roo.get(newNode, true) : newNode;
4423 * Creates new Dom element(s) and appends them to el
4424 * @param {String/HTMLElement/Element} el The context element
4425 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4426 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4427 * @return {HTMLElement/Roo.Element} The new node
4429 append : function(el, o, returnElement){
4430 el = Roo.getDom(el);
4432 if(this.useDom || o.ns){
4433 newNode = createDom(o, null);
4434 el.appendChild(newNode);
4436 var html = createHtml(o);
4437 newNode = this.insertHtml("beforeEnd", el, html);
4439 return returnElement ? Roo.get(newNode, true) : newNode;
4443 * Creates new Dom element(s) and overwrites the contents of el with them
4444 * @param {String/HTMLElement/Element} el The context element
4445 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4446 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4447 * @return {HTMLElement/Roo.Element} The new node
4449 overwrite : function(el, o, returnElement){
4450 el = Roo.getDom(el);
4453 while (el.childNodes.length) {
4454 el.removeChild(el.firstChild);
4458 el.innerHTML = createHtml(o);
4461 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4465 * Creates a new Roo.DomHelper.Template from the Dom object spec
4466 * @param {Object} o The Dom object spec (and children)
4467 * @return {Roo.DomHelper.Template} The new template
4469 createTemplate : function(o){
4470 var html = createHtml(o);
4471 return new Roo.Template(html);
4477 * Ext JS Library 1.1.1
4478 * Copyright(c) 2006-2007, Ext JS, LLC.
4480 * Originally Released Under LGPL - original licence link has changed is not relivant.
4483 * <script type="text/javascript">
4487 * @class Roo.Template
4488 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4489 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4492 var t = new Roo.Template({
4493 html : '<div name="{id}">' +
4494 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4496 myformat: function (value, allValues) {
4497 return 'XX' + value;
4500 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4502 * 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>.
4504 * @param {Object} cfg - Configuration object.
4506 Roo.Template = function(cfg){
4508 if(cfg instanceof Array){
4510 }else if(arguments.length > 1){
4511 cfg = Array.prototype.join.call(arguments, "");
4515 if (typeof(cfg) == 'object') {
4524 Roo.Template.prototype = {
4527 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4531 * Returns an HTML fragment of this template with the specified values applied.
4532 * @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'})
4533 * @return {String} The HTML fragment
4535 applyTemplate : function(values){
4539 return this.compiled(values);
4541 var useF = this.disableFormats !== true;
4542 var fm = Roo.util.Format, tpl = this;
4543 var fn = function(m, name, format, args){
4545 if(format.substr(0, 5) == "this."){
4546 return tpl.call(format.substr(5), values[name], values);
4549 // quoted values are required for strings in compiled templates,
4550 // but for non compiled we need to strip them
4551 // quoted reversed for jsmin
4552 var re = /^\s*['"](.*)["']\s*$/;
4553 args = args.split(',');
4554 for(var i = 0, len = args.length; i < len; i++){
4555 args[i] = args[i].replace(re, "$1");
4557 args = [values[name]].concat(args);
4559 args = [values[name]];
4561 return fm[format].apply(fm, args);
4564 return values[name] !== undefined ? values[name] : "";
4567 return this.html.replace(this.re, fn);
4576 * Sets the HTML used as the template and optionally compiles it.
4577 * @param {String} html
4578 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4579 * @return {Roo.Template} this
4581 set : function(html, compile){
4583 this.compiled = null;
4591 * True to disable format functions (defaults to false)
4594 disableFormats : false,
4597 * The regular expression used to match template variables
4601 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4604 * Compiles the template into an internal function, eliminating the RegEx overhead.
4605 * @return {Roo.Template} this
4607 compile : function(){
4608 var fm = Roo.util.Format;
4609 var useF = this.disableFormats !== true;
4610 var sep = Roo.isGecko ? "+" : ",";
4611 var fn = function(m, name, format, args){
4613 args = args ? ',' + args : "";
4614 if(format.substr(0, 5) != "this."){
4615 format = "fm." + format + '(';
4617 format = 'this.call("'+ format.substr(5) + '", ';
4621 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4623 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4626 // branched to use + in gecko and [].join() in others
4628 body = "this.compiled = function(values){ return '" +
4629 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4632 body = ["this.compiled = function(values){ return ['"];
4633 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4634 body.push("'].join('');};");
4635 body = body.join('');
4645 // private function used to call members
4646 call : function(fnName, value, allValues){
4647 return this[fnName](value, allValues);
4651 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4652 * @param {String/HTMLElement/Roo.Element} el The context element
4653 * @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'})
4654 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4655 * @return {HTMLElement/Roo.Element} The new node or Element
4657 insertFirst: function(el, values, returnElement){
4658 return this.doInsert('afterBegin', el, values, returnElement);
4662 * Applies the supplied values to the template and inserts the new node(s) before el.
4663 * @param {String/HTMLElement/Roo.Element} el The context element
4664 * @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'})
4665 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4666 * @return {HTMLElement/Roo.Element} The new node or Element
4668 insertBefore: function(el, values, returnElement){
4669 return this.doInsert('beforeBegin', el, values, returnElement);
4673 * Applies the supplied values to the template and inserts the new node(s) after el.
4674 * @param {String/HTMLElement/Roo.Element} el The context element
4675 * @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'})
4676 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4677 * @return {HTMLElement/Roo.Element} The new node or Element
4679 insertAfter : function(el, values, returnElement){
4680 return this.doInsert('afterEnd', el, values, returnElement);
4684 * Applies the supplied values to the template and appends the new node(s) to el.
4685 * @param {String/HTMLElement/Roo.Element} el The context element
4686 * @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'})
4687 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4688 * @return {HTMLElement/Roo.Element} The new node or Element
4690 append : function(el, values, returnElement){
4691 return this.doInsert('beforeEnd', el, values, returnElement);
4694 doInsert : function(where, el, values, returnEl){
4695 el = Roo.getDom(el);
4696 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4697 return returnEl ? Roo.get(newNode, true) : newNode;
4701 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4702 * @param {String/HTMLElement/Roo.Element} el The context element
4703 * @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'})
4704 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4705 * @return {HTMLElement/Roo.Element} The new node or Element
4707 overwrite : function(el, values, returnElement){
4708 el = Roo.getDom(el);
4709 el.innerHTML = this.applyTemplate(values);
4710 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4714 * Alias for {@link #applyTemplate}
4717 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4720 Roo.DomHelper.Template = Roo.Template;
4723 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4724 * @param {String/HTMLElement} el A DOM element or its id
4725 * @returns {Roo.Template} The created template
4728 Roo.Template.from = function(el){
4729 el = Roo.getDom(el);
4730 return new Roo.Template(el.value || el.innerHTML);
4733 * Ext JS Library 1.1.1
4734 * Copyright(c) 2006-2007, Ext JS, LLC.
4736 * Originally Released Under LGPL - original licence link has changed is not relivant.
4739 * <script type="text/javascript">
4744 * This is code is also distributed under MIT license for use
4745 * with jQuery and prototype JavaScript libraries.
4748 * @class Roo.DomQuery
4749 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).
4751 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>
4754 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.
4756 <h4>Element Selectors:</h4>
4758 <li> <b>*</b> any element</li>
4759 <li> <b>E</b> an element with the tag E</li>
4760 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4761 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4762 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4763 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4765 <h4>Attribute Selectors:</h4>
4766 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4768 <li> <b>E[foo]</b> has an attribute "foo"</li>
4769 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4770 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4771 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4772 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4773 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4774 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4776 <h4>Pseudo Classes:</h4>
4778 <li> <b>E:first-child</b> E is the first child of its parent</li>
4779 <li> <b>E:last-child</b> E is the last child of its parent</li>
4780 <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>
4781 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4782 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4783 <li> <b>E:only-child</b> E is the only child of its parent</li>
4784 <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>
4785 <li> <b>E:first</b> the first E in the resultset</li>
4786 <li> <b>E:last</b> the last E in the resultset</li>
4787 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4788 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4789 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4790 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4791 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4792 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4793 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4794 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4795 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4797 <h4>CSS Value Selectors:</h4>
4799 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4800 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4801 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4802 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4803 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4804 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4808 Roo.DomQuery = function(){
4809 var cache = {}, simpleCache = {}, valueCache = {};
4810 var nonSpace = /\S/;
4811 var trimRe = /^\s+|\s+$/g;
4812 var tplRe = /\{(\d+)\}/g;
4813 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4814 var tagTokenRe = /^(#)?([\w-\*]+)/;
4815 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4817 function child(p, index){
4819 var n = p.firstChild;
4821 if(n.nodeType == 1){
4832 while((n = n.nextSibling) && n.nodeType != 1);
4837 while((n = n.previousSibling) && n.nodeType != 1);
4841 function children(d){
4842 var n = d.firstChild, ni = -1;
4844 var nx = n.nextSibling;
4845 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4855 function byClassName(c, a, v){
4859 var r = [], ri = -1, cn;
4860 for(var i = 0, ci; ci = c[i]; i++){
4861 if((' '+ci.className+' ').indexOf(v) != -1){
4868 function attrValue(n, attr){
4869 if(!n.tagName && typeof n.length != "undefined"){
4878 if(attr == "class" || attr == "className"){
4881 return n.getAttribute(attr) || n[attr];
4885 function getNodes(ns, mode, tagName){
4886 var result = [], ri = -1, cs;
4890 tagName = tagName || "*";
4891 if(typeof ns.getElementsByTagName != "undefined"){
4895 for(var i = 0, ni; ni = ns[i]; i++){
4896 cs = ni.getElementsByTagName(tagName);
4897 for(var j = 0, ci; ci = cs[j]; j++){
4901 }else if(mode == "/" || mode == ">"){
4902 var utag = tagName.toUpperCase();
4903 for(var i = 0, ni, cn; ni = ns[i]; i++){
4904 cn = ni.children || ni.childNodes;
4905 for(var j = 0, cj; cj = cn[j]; j++){
4906 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4911 }else if(mode == "+"){
4912 var utag = tagName.toUpperCase();
4913 for(var i = 0, n; n = ns[i]; i++){
4914 while((n = n.nextSibling) && n.nodeType != 1);
4915 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4919 }else if(mode == "~"){
4920 for(var i = 0, n; n = ns[i]; i++){
4921 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4930 function concat(a, b){
4934 for(var i = 0, l = b.length; i < l; i++){
4940 function byTag(cs, tagName){
4941 if(cs.tagName || cs == document){
4947 var r = [], ri = -1;
4948 tagName = tagName.toLowerCase();
4949 for(var i = 0, ci; ci = cs[i]; i++){
4950 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4957 function byId(cs, attr, id){
4958 if(cs.tagName || cs == document){
4964 var r = [], ri = -1;
4965 for(var i = 0,ci; ci = cs[i]; i++){
4966 if(ci && ci.id == id){
4974 function byAttribute(cs, attr, value, op, custom){
4975 var r = [], ri = -1, st = custom=="{";
4976 var f = Roo.DomQuery.operators[op];
4977 for(var i = 0, ci; ci = cs[i]; i++){
4980 a = Roo.DomQuery.getStyle(ci, attr);
4982 else if(attr == "class" || attr == "className"){
4984 }else if(attr == "for"){
4986 }else if(attr == "href"){
4987 a = ci.getAttribute("href", 2);
4989 a = ci.getAttribute(attr);
4991 if((f && f(a, value)) || (!f && a)){
4998 function byPseudo(cs, name, value){
4999 return Roo.DomQuery.pseudos[name](cs, value);
5002 // This is for IE MSXML which does not support expandos.
5003 // IE runs the same speed using setAttribute, however FF slows way down
5004 // and Safari completely fails so they need to continue to use expandos.
5005 var isIE = window.ActiveXObject ? true : false;
5007 // this eval is stop the compressor from
5008 // renaming the variable to something shorter
5010 /** eval:var:batch */
5015 function nodupIEXml(cs){
5017 cs[0].setAttribute("_nodup", d);
5019 for(var i = 1, len = cs.length; i < len; i++){
5021 if(!c.getAttribute("_nodup") != d){
5022 c.setAttribute("_nodup", d);
5026 for(var i = 0, len = cs.length; i < len; i++){
5027 cs[i].removeAttribute("_nodup");
5036 var len = cs.length, c, i, r = cs, cj, ri = -1;
5037 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5040 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5041 return nodupIEXml(cs);
5045 for(i = 1; c = cs[i]; i++){
5050 for(var j = 0; j < i; j++){
5053 for(j = i+1; cj = cs[j]; j++){
5065 function quickDiffIEXml(c1, c2){
5067 for(var i = 0, len = c1.length; i < len; i++){
5068 c1[i].setAttribute("_qdiff", d);
5071 for(var i = 0, len = c2.length; i < len; i++){
5072 if(c2[i].getAttribute("_qdiff") != d){
5073 r[r.length] = c2[i];
5076 for(var i = 0, len = c1.length; i < len; i++){
5077 c1[i].removeAttribute("_qdiff");
5082 function quickDiff(c1, c2){
5083 var len1 = c1.length;
5087 if(isIE && c1[0].selectSingleNode){
5088 return quickDiffIEXml(c1, c2);
5091 for(var i = 0; i < len1; i++){
5095 for(var i = 0, len = c2.length; i < len; i++){
5096 if(c2[i]._qdiff != d){
5097 r[r.length] = c2[i];
5103 function quickId(ns, mode, root, id){
5105 var d = root.ownerDocument || root;
5106 return d.getElementById(id);
5108 ns = getNodes(ns, mode, "*");
5109 return byId(ns, null, id);
5113 getStyle : function(el, name){
5114 return Roo.fly(el).getStyle(name);
5117 * Compiles a selector/xpath query into a reusable function. The returned function
5118 * takes one parameter "root" (optional), which is the context node from where the query should start.
5119 * @param {String} selector The selector/xpath query
5120 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5121 * @return {Function}
5123 compile : function(path, type){
5124 type = type || "select";
5126 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5127 var q = path, mode, lq;
5128 var tk = Roo.DomQuery.matchers;
5129 var tklen = tk.length;
5132 // accept leading mode switch
5133 var lmode = q.match(modeRe);
5134 if(lmode && lmode[1]){
5135 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5136 q = q.replace(lmode[1], "");
5138 // strip leading slashes
5139 while(path.substr(0, 1)=="/"){
5140 path = path.substr(1);
5143 while(q && lq != q){
5145 var tm = q.match(tagTokenRe);
5146 if(type == "select"){
5149 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5151 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5153 q = q.replace(tm[0], "");
5154 }else if(q.substr(0, 1) != '@'){
5155 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5160 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5162 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5164 q = q.replace(tm[0], "");
5167 while(!(mm = q.match(modeRe))){
5168 var matched = false;
5169 for(var j = 0; j < tklen; j++){
5171 var m = q.match(t.re);
5173 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5176 q = q.replace(m[0], "");
5181 // prevent infinite loop on bad selector
5183 throw 'Error parsing selector, parsing failed at "' + q + '"';
5187 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5188 q = q.replace(mm[1], "");
5191 fn[fn.length] = "return nodup(n);\n}";
5194 * list of variables that need from compression as they are used by eval.
5204 * eval:var:byClassName
5206 * eval:var:byAttribute
5207 * eval:var:attrValue
5215 * Selects a group of elements.
5216 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5217 * @param {Node} root (optional) The start of the query (defaults to document).
5220 select : function(path, root, type){
5221 if(!root || root == document){
5224 if(typeof root == "string"){
5225 root = document.getElementById(root);
5227 var paths = path.split(",");
5229 for(var i = 0, len = paths.length; i < len; i++){
5230 var p = paths[i].replace(trimRe, "");
5232 cache[p] = Roo.DomQuery.compile(p);
5234 throw p + " is not a valid selector";
5237 var result = cache[p](root);
5238 if(result && result != document){
5239 results = results.concat(result);
5242 if(paths.length > 1){
5243 return nodup(results);
5249 * Selects a single element.
5250 * @param {String} selector The selector/xpath query
5251 * @param {Node} root (optional) The start of the query (defaults to document).
5254 selectNode : function(path, root){
5255 return Roo.DomQuery.select(path, root)[0];
5259 * Selects the value of a node, optionally replacing null with the defaultValue.
5260 * @param {String} selector The selector/xpath query
5261 * @param {Node} root (optional) The start of the query (defaults to document).
5262 * @param {String} defaultValue
5264 selectValue : function(path, root, defaultValue){
5265 path = path.replace(trimRe, "");
5266 if(!valueCache[path]){
5267 valueCache[path] = Roo.DomQuery.compile(path, "select");
5269 var n = valueCache[path](root);
5270 n = n[0] ? n[0] : n;
5271 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5272 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5276 * Selects the value of a node, parsing integers and floats.
5277 * @param {String} selector The selector/xpath query
5278 * @param {Node} root (optional) The start of the query (defaults to document).
5279 * @param {Number} defaultValue
5282 selectNumber : function(path, root, defaultValue){
5283 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5284 return parseFloat(v);
5288 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5289 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5290 * @param {String} selector The simple selector to test
5293 is : function(el, ss){
5294 if(typeof el == "string"){
5295 el = document.getElementById(el);
5297 var isArray = (el instanceof Array);
5298 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5299 return isArray ? (result.length == el.length) : (result.length > 0);
5303 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5304 * @param {Array} el An array of elements to filter
5305 * @param {String} selector The simple selector to test
5306 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5307 * the selector instead of the ones that match
5310 filter : function(els, ss, nonMatches){
5311 ss = ss.replace(trimRe, "");
5312 if(!simpleCache[ss]){
5313 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5315 var result = simpleCache[ss](els);
5316 return nonMatches ? quickDiff(result, els) : result;
5320 * Collection of matching regular expressions and code snippets.
5324 select: 'n = byClassName(n, null, " {1} ");'
5326 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5327 select: 'n = byPseudo(n, "{1}", "{2}");'
5329 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5330 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5333 select: 'n = byId(n, null, "{1}");'
5336 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5341 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5342 * 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, > <.
5345 "=" : function(a, v){
5348 "!=" : function(a, v){
5351 "^=" : function(a, v){
5352 return a && a.substr(0, v.length) == v;
5354 "$=" : function(a, v){
5355 return a && a.substr(a.length-v.length) == v;
5357 "*=" : function(a, v){
5358 return a && a.indexOf(v) !== -1;
5360 "%=" : function(a, v){
5361 return (a % v) == 0;
5363 "|=" : function(a, v){
5364 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5366 "~=" : function(a, v){
5367 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5372 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5373 * and the argument (if any) supplied in the selector.
5376 "first-child" : function(c){
5377 var r = [], ri = -1, n;
5378 for(var i = 0, ci; ci = n = c[i]; i++){
5379 while((n = n.previousSibling) && n.nodeType != 1);
5387 "last-child" : function(c){
5388 var r = [], ri = -1, n;
5389 for(var i = 0, ci; ci = n = c[i]; i++){
5390 while((n = n.nextSibling) && n.nodeType != 1);
5398 "nth-child" : function(c, a) {
5399 var r = [], ri = -1;
5400 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5401 var f = (m[1] || 1) - 0, l = m[2] - 0;
5402 for(var i = 0, n; n = c[i]; i++){
5403 var pn = n.parentNode;
5404 if (batch != pn._batch) {
5406 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5407 if(cn.nodeType == 1){
5414 if (l == 0 || n.nodeIndex == l){
5417 } else if ((n.nodeIndex + l) % f == 0){
5425 "only-child" : function(c){
5426 var r = [], ri = -1;;
5427 for(var i = 0, ci; ci = c[i]; i++){
5428 if(!prev(ci) && !next(ci)){
5435 "empty" : function(c){
5436 var r = [], ri = -1;
5437 for(var i = 0, ci; ci = c[i]; i++){
5438 var cns = ci.childNodes, j = 0, cn, empty = true;
5441 if(cn.nodeType == 1 || cn.nodeType == 3){
5453 "contains" : function(c, v){
5454 var r = [], ri = -1;
5455 for(var i = 0, ci; ci = c[i]; i++){
5456 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5463 "nodeValue" : function(c, v){
5464 var r = [], ri = -1;
5465 for(var i = 0, ci; ci = c[i]; i++){
5466 if(ci.firstChild && ci.firstChild.nodeValue == v){
5473 "checked" : function(c){
5474 var r = [], ri = -1;
5475 for(var i = 0, ci; ci = c[i]; i++){
5476 if(ci.checked == true){
5483 "not" : function(c, ss){
5484 return Roo.DomQuery.filter(c, ss, true);
5487 "odd" : function(c){
5488 return this["nth-child"](c, "odd");
5491 "even" : function(c){
5492 return this["nth-child"](c, "even");
5495 "nth" : function(c, a){
5496 return c[a-1] || [];
5499 "first" : function(c){
5503 "last" : function(c){
5504 return c[c.length-1] || [];
5507 "has" : function(c, ss){
5508 var s = Roo.DomQuery.select;
5509 var r = [], ri = -1;
5510 for(var i = 0, ci; ci = c[i]; i++){
5511 if(s(ss, ci).length > 0){
5518 "next" : function(c, ss){
5519 var is = Roo.DomQuery.is;
5520 var r = [], ri = -1;
5521 for(var i = 0, ci; ci = c[i]; i++){
5530 "prev" : function(c, ss){
5531 var is = Roo.DomQuery.is;
5532 var r = [], ri = -1;
5533 for(var i = 0, ci; ci = c[i]; i++){
5546 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5547 * @param {String} path The selector/xpath query
5548 * @param {Node} root (optional) The start of the query (defaults to document).
5553 Roo.query = Roo.DomQuery.select;
5556 * Ext JS Library 1.1.1
5557 * Copyright(c) 2006-2007, Ext JS, LLC.
5559 * Originally Released Under LGPL - original licence link has changed is not relivant.
5562 * <script type="text/javascript">
5566 * @class Roo.util.Observable
5567 * Base class that provides a common interface for publishing events. Subclasses are expected to
5568 * to have a property "events" with all the events defined.<br>
5571 Employee = function(name){
5578 Roo.extend(Employee, Roo.util.Observable);
5580 * @param {Object} config properties to use (incuding events / listeners)
5583 Roo.util.Observable = function(cfg){
5586 this.addEvents(cfg.events || {});
5588 delete cfg.events; // make sure
5591 Roo.apply(this, cfg);
5594 this.on(this.listeners);
5595 delete this.listeners;
5598 Roo.util.Observable.prototype = {
5600 * @cfg {Object} listeners list of events and functions to call for this object,
5604 'click' : function(e) {
5614 * Fires the specified event with the passed parameters (minus the event name).
5615 * @param {String} eventName
5616 * @param {Object...} args Variable number of parameters are passed to handlers
5617 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5619 fireEvent : function(){
5620 var ce = this.events[arguments[0].toLowerCase()];
5621 if(typeof ce == "object"){
5622 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5629 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5632 * Appends an event handler to this component
5633 * @param {String} eventName The type of event to listen for
5634 * @param {Function} handler The method the event invokes
5635 * @param {Object} scope (optional) The scope in which to execute the handler
5636 * function. The handler function's "this" context.
5637 * @param {Object} options (optional) An object containing handler configuration
5638 * properties. This may contain any of the following properties:<ul>
5639 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5640 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5641 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5642 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5643 * by the specified number of milliseconds. If the event fires again within that time, the original
5644 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5647 * <b>Combining Options</b><br>
5648 * Using the options argument, it is possible to combine different types of listeners:<br>
5650 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5652 el.on('click', this.onClick, this, {
5659 * <b>Attaching multiple handlers in 1 call</b><br>
5660 * The method also allows for a single argument to be passed which is a config object containing properties
5661 * which specify multiple handlers.
5670 fn: this.onMouseOver,
5674 fn: this.onMouseOut,
5680 * Or a shorthand syntax which passes the same scope object to all handlers:
5683 'click': this.onClick,
5684 'mouseover': this.onMouseOver,
5685 'mouseout': this.onMouseOut,
5690 addListener : function(eventName, fn, scope, o){
5691 if(typeof eventName == "object"){
5694 if(this.filterOptRe.test(e)){
5697 if(typeof o[e] == "function"){
5699 this.addListener(e, o[e], o.scope, o);
5701 // individual options
5702 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5707 o = (!o || typeof o == "boolean") ? {} : o;
5708 eventName = eventName.toLowerCase();
5709 var ce = this.events[eventName] || true;
5710 if(typeof ce == "boolean"){
5711 ce = new Roo.util.Event(this, eventName);
5712 this.events[eventName] = ce;
5714 ce.addListener(fn, scope, o);
5718 * Removes a listener
5719 * @param {String} eventName The type of event to listen for
5720 * @param {Function} handler The handler to remove
5721 * @param {Object} scope (optional) The scope (this object) for the handler
5723 removeListener : function(eventName, fn, scope){
5724 var ce = this.events[eventName.toLowerCase()];
5725 if(typeof ce == "object"){
5726 ce.removeListener(fn, scope);
5731 * Removes all listeners for this object
5733 purgeListeners : function(){
5734 for(var evt in this.events){
5735 if(typeof this.events[evt] == "object"){
5736 this.events[evt].clearListeners();
5741 relayEvents : function(o, events){
5742 var createHandler = function(ename){
5744 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5747 for(var i = 0, len = events.length; i < len; i++){
5748 var ename = events[i];
5749 if(!this.events[ename]){ this.events[ename] = true; };
5750 o.on(ename, createHandler(ename), this);
5755 * Used to define events on this Observable
5756 * @param {Object} object The object with the events defined
5758 addEvents : function(o){
5762 Roo.applyIf(this.events, o);
5766 * Checks to see if this object has any listeners for a specified event
5767 * @param {String} eventName The name of the event to check for
5768 * @return {Boolean} True if the event is being listened for, else false
5770 hasListener : function(eventName){
5771 var e = this.events[eventName];
5772 return typeof e == "object" && e.listeners.length > 0;
5776 * Appends an event handler to this element (shorthand for addListener)
5777 * @param {String} eventName The type of event to listen for
5778 * @param {Function} handler The method the event invokes
5779 * @param {Object} scope (optional) The scope in which to execute the handler
5780 * function. The handler function's "this" context.
5781 * @param {Object} options (optional)
5784 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5786 * Removes a listener (shorthand for removeListener)
5787 * @param {String} eventName The type of event to listen for
5788 * @param {Function} handler The handler to remove
5789 * @param {Object} scope (optional) The scope (this object) for the handler
5792 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5795 * Starts capture on the specified Observable. All events will be passed
5796 * to the supplied function with the event name + standard signature of the event
5797 * <b>before</b> the event is fired. If the supplied function returns false,
5798 * the event will not fire.
5799 * @param {Observable} o The Observable to capture
5800 * @param {Function} fn The function to call
5801 * @param {Object} scope (optional) The scope (this object) for the fn
5804 Roo.util.Observable.capture = function(o, fn, scope){
5805 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5809 * Removes <b>all</b> added captures from the Observable.
5810 * @param {Observable} o The Observable to release
5813 Roo.util.Observable.releaseCapture = function(o){
5814 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5819 var createBuffered = function(h, o, scope){
5820 var task = new Roo.util.DelayedTask();
5822 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5826 var createSingle = function(h, e, fn, scope){
5828 e.removeListener(fn, scope);
5829 return h.apply(scope, arguments);
5833 var createDelayed = function(h, o, scope){
5835 var args = Array.prototype.slice.call(arguments, 0);
5836 setTimeout(function(){
5837 h.apply(scope, args);
5842 Roo.util.Event = function(obj, name){
5845 this.listeners = [];
5848 Roo.util.Event.prototype = {
5849 addListener : function(fn, scope, options){
5850 var o = options || {};
5851 scope = scope || this.obj;
5852 if(!this.isListening(fn, scope)){
5853 var l = {fn: fn, scope: scope, options: o};
5856 h = createDelayed(h, o, scope);
5859 h = createSingle(h, this, fn, scope);
5862 h = createBuffered(h, o, scope);
5865 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5866 this.listeners.push(l);
5868 this.listeners = this.listeners.slice(0);
5869 this.listeners.push(l);
5874 findListener : function(fn, scope){
5875 scope = scope || this.obj;
5876 var ls = this.listeners;
5877 for(var i = 0, len = ls.length; i < len; i++){
5879 if(l.fn == fn && l.scope == scope){
5886 isListening : function(fn, scope){
5887 return this.findListener(fn, scope) != -1;
5890 removeListener : function(fn, scope){
5892 if((index = this.findListener(fn, scope)) != -1){
5894 this.listeners.splice(index, 1);
5896 this.listeners = this.listeners.slice(0);
5897 this.listeners.splice(index, 1);
5904 clearListeners : function(){
5905 this.listeners = [];
5909 var ls = this.listeners, scope, len = ls.length;
5912 var args = Array.prototype.slice.call(arguments, 0);
5913 for(var i = 0; i < len; i++){
5915 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5916 this.firing = false;
5920 this.firing = false;
5927 * Ext JS Library 1.1.1
5928 * Copyright(c) 2006-2007, Ext JS, LLC.
5930 * Originally Released Under LGPL - original licence link has changed is not relivant.
5933 * <script type="text/javascript">
5937 * @class Roo.EventManager
5938 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5939 * several useful events directly.
5940 * See {@link Roo.EventObject} for more details on normalized event objects.
5943 Roo.EventManager = function(){
5944 var docReadyEvent, docReadyProcId, docReadyState = false;
5945 var resizeEvent, resizeTask, textEvent, textSize;
5946 var E = Roo.lib.Event;
5947 var D = Roo.lib.Dom;
5950 var fireDocReady = function(){
5952 docReadyState = true;
5955 clearInterval(docReadyProcId);
5957 if(Roo.isGecko || Roo.isOpera) {
5958 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5961 var defer = document.getElementById("ie-deferred-loader");
5963 defer.onreadystatechange = null;
5964 defer.parentNode.removeChild(defer);
5968 docReadyEvent.fire();
5969 docReadyEvent.clearListeners();
5974 var initDocReady = function(){
5975 docReadyEvent = new Roo.util.Event();
5976 if(Roo.isGecko || Roo.isOpera) {
5977 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5979 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5980 var defer = document.getElementById("ie-deferred-loader");
5981 defer.onreadystatechange = function(){
5982 if(this.readyState == "complete"){
5986 }else if(Roo.isSafari){
5987 docReadyProcId = setInterval(function(){
5988 var rs = document.readyState;
5989 if(rs == "complete") {
5994 // no matter what, make sure it fires on load
5995 E.on(window, "load", fireDocReady);
5998 var createBuffered = function(h, o){
5999 var task = new Roo.util.DelayedTask(h);
6001 // create new event object impl so new events don't wipe out properties
6002 e = new Roo.EventObjectImpl(e);
6003 task.delay(o.buffer, h, null, [e]);
6007 var createSingle = function(h, el, ename, fn){
6009 Roo.EventManager.removeListener(el, ename, fn);
6014 var createDelayed = function(h, o){
6016 // create new event object impl so new events don't wipe out properties
6017 e = new Roo.EventObjectImpl(e);
6018 setTimeout(function(){
6024 var listen = function(element, ename, opt, fn, scope){
6025 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6026 fn = fn || o.fn; scope = scope || o.scope;
6027 var el = Roo.getDom(element);
6029 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6031 var h = function(e){
6032 e = Roo.EventObject.setEvent(e);
6035 t = e.getTarget(o.delegate, el);
6042 if(o.stopEvent === true){
6045 if(o.preventDefault === true){
6048 if(o.stopPropagation === true){
6049 e.stopPropagation();
6052 if(o.normalized === false){
6056 fn.call(scope || el, e, t, o);
6059 h = createDelayed(h, o);
6062 h = createSingle(h, el, ename, fn);
6065 h = createBuffered(h, o);
6067 fn._handlers = fn._handlers || [];
6068 fn._handlers.push([Roo.id(el), ename, h]);
6071 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6072 el.addEventListener("DOMMouseScroll", h, false);
6073 E.on(window, 'unload', function(){
6074 el.removeEventListener("DOMMouseScroll", h, false);
6077 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6078 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6083 var stopListening = function(el, ename, fn){
6084 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6086 for(var i = 0, len = hds.length; i < len; i++){
6088 if(h[0] == id && h[1] == ename){
6095 E.un(el, ename, hd);
6096 el = Roo.getDom(el);
6097 if(ename == "mousewheel" && el.addEventListener){
6098 el.removeEventListener("DOMMouseScroll", hd, false);
6100 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6101 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6105 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6112 * @scope Roo.EventManager
6117 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6118 * object with a Roo.EventObject
6119 * @param {Function} fn The method the event invokes
6120 * @param {Object} scope An object that becomes the scope of the handler
6121 * @param {boolean} override If true, the obj passed in becomes
6122 * the execution scope of the listener
6123 * @return {Function} The wrapped function
6126 wrap : function(fn, scope, override){
6128 Roo.EventObject.setEvent(e);
6129 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6134 * Appends an event handler to an element (shorthand for addListener)
6135 * @param {String/HTMLElement} element The html element or id to assign the
6136 * @param {String} eventName The type of event to listen for
6137 * @param {Function} handler The method the event invokes
6138 * @param {Object} scope (optional) The scope in which to execute the handler
6139 * function. The handler function's "this" context.
6140 * @param {Object} options (optional) An object containing handler configuration
6141 * properties. This may contain any of the following properties:<ul>
6142 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6143 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6144 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6145 * <li>preventDefault {Boolean} True to prevent the default action</li>
6146 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6147 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6148 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6149 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6150 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6151 * by the specified number of milliseconds. If the event fires again within that time, the original
6152 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6155 * <b>Combining Options</b><br>
6156 * Using the options argument, it is possible to combine different types of listeners:<br>
6158 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6160 el.on('click', this.onClick, this, {
6167 * <b>Attaching multiple handlers in 1 call</b><br>
6168 * The method also allows for a single argument to be passed which is a config object containing properties
6169 * which specify multiple handlers.
6179 fn: this.onMouseOver
6188 * Or a shorthand syntax:<br>
6191 'click' : this.onClick,
6192 'mouseover' : this.onMouseOver,
6193 'mouseout' : this.onMouseOut
6197 addListener : function(element, eventName, fn, scope, options){
6198 if(typeof eventName == "object"){
6204 if(typeof o[e] == "function"){
6206 listen(element, e, o, o[e], o.scope);
6208 // individual options
6209 listen(element, e, o[e]);
6214 return listen(element, eventName, options, fn, scope);
6218 * Removes an event handler
6220 * @param {String/HTMLElement} element The id or html element to remove the
6222 * @param {String} eventName The type of event
6223 * @param {Function} fn
6224 * @return {Boolean} True if a listener was actually removed
6226 removeListener : function(element, eventName, fn){
6227 return stopListening(element, eventName, fn);
6231 * Fires when the document is ready (before onload and before images are loaded). Can be
6232 * accessed shorthanded Roo.onReady().
6233 * @param {Function} fn The method the event invokes
6234 * @param {Object} scope An object that becomes the scope of the handler
6235 * @param {boolean} options
6237 onDocumentReady : function(fn, scope, options){
6238 if(docReadyState){ // if it already fired
6239 docReadyEvent.addListener(fn, scope, options);
6240 docReadyEvent.fire();
6241 docReadyEvent.clearListeners();
6247 docReadyEvent.addListener(fn, scope, options);
6251 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6252 * @param {Function} fn The method the event invokes
6253 * @param {Object} scope An object that becomes the scope of the handler
6254 * @param {boolean} options
6256 onWindowResize : function(fn, scope, options){
6258 resizeEvent = new Roo.util.Event();
6259 resizeTask = new Roo.util.DelayedTask(function(){
6260 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6262 E.on(window, "resize", function(){
6264 resizeTask.delay(50);
6266 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6270 resizeEvent.addListener(fn, scope, options);
6274 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6275 * @param {Function} fn The method the event invokes
6276 * @param {Object} scope An object that becomes the scope of the handler
6277 * @param {boolean} options
6279 onTextResize : function(fn, scope, options){
6281 textEvent = new Roo.util.Event();
6282 var textEl = new Roo.Element(document.createElement('div'));
6283 textEl.dom.className = 'x-text-resize';
6284 textEl.dom.innerHTML = 'X';
6285 textEl.appendTo(document.body);
6286 textSize = textEl.dom.offsetHeight;
6287 setInterval(function(){
6288 if(textEl.dom.offsetHeight != textSize){
6289 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6291 }, this.textResizeInterval);
6293 textEvent.addListener(fn, scope, options);
6297 * Removes the passed window resize listener.
6298 * @param {Function} fn The method the event invokes
6299 * @param {Object} scope The scope of handler
6301 removeResizeListener : function(fn, scope){
6303 resizeEvent.removeListener(fn, scope);
6308 fireResize : function(){
6310 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6314 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6318 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6320 textResizeInterval : 50
6325 * @scopeAlias pub=Roo.EventManager
6329 * Appends an event handler to an element (shorthand for addListener)
6330 * @param {String/HTMLElement} element The html element or id to assign the
6331 * @param {String} eventName The type of event to listen for
6332 * @param {Function} handler The method the event invokes
6333 * @param {Object} scope (optional) The scope in which to execute the handler
6334 * function. The handler function's "this" context.
6335 * @param {Object} options (optional) An object containing handler configuration
6336 * properties. This may contain any of the following properties:<ul>
6337 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6338 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6339 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6340 * <li>preventDefault {Boolean} True to prevent the default action</li>
6341 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6342 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6343 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6344 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6345 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6346 * by the specified number of milliseconds. If the event fires again within that time, the original
6347 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6350 * <b>Combining Options</b><br>
6351 * Using the options argument, it is possible to combine different types of listeners:<br>
6353 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6355 el.on('click', this.onClick, this, {
6362 * <b>Attaching multiple handlers in 1 call</b><br>
6363 * The method also allows for a single argument to be passed which is a config object containing properties
6364 * which specify multiple handlers.
6374 fn: this.onMouseOver
6383 * Or a shorthand syntax:<br>
6386 'click' : this.onClick,
6387 'mouseover' : this.onMouseOver,
6388 'mouseout' : this.onMouseOut
6392 pub.on = pub.addListener;
6393 pub.un = pub.removeListener;
6395 pub.stoppedMouseDownEvent = new Roo.util.Event();
6399 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6400 * @param {Function} fn The method the event invokes
6401 * @param {Object} scope An object that becomes the scope of the handler
6402 * @param {boolean} override If true, the obj passed in becomes
6403 * the execution scope of the listener
6407 Roo.onReady = Roo.EventManager.onDocumentReady;
6409 Roo.onReady(function(){
6410 var bd = Roo.get(document.body);
6415 : Roo.isGecko ? "roo-gecko"
6416 : Roo.isOpera ? "roo-opera"
6417 : Roo.isSafari ? "roo-safari" : ""];
6420 cls.push("roo-mac");
6423 cls.push("roo-linux");
6425 if(Roo.isBorderBox){
6426 cls.push('roo-border-box');
6428 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6429 var p = bd.dom.parentNode;
6431 p.className += ' roo-strict';
6434 bd.addClass(cls.join(' '));
6438 * @class Roo.EventObject
6439 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6440 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6443 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6445 var target = e.getTarget();
6448 var myDiv = Roo.get("myDiv");
6449 myDiv.on("click", handleClick);
6451 Roo.EventManager.on("myDiv", 'click', handleClick);
6452 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6456 Roo.EventObject = function(){
6458 var E = Roo.lib.Event;
6460 // safari keypress events for special keys return bad keycodes
6463 63235 : 39, // right
6466 63276 : 33, // page up
6467 63277 : 34, // page down
6468 63272 : 46, // delete
6473 // normalize button clicks
6474 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6475 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6477 Roo.EventObjectImpl = function(e){
6479 this.setEvent(e.browserEvent || e);
6482 Roo.EventObjectImpl.prototype = {
6484 * Used to fix doc tools.
6485 * @scope Roo.EventObject.prototype
6491 /** The normal browser event */
6492 browserEvent : null,
6493 /** The button pressed in a mouse event */
6495 /** True if the shift key was down during the event */
6497 /** True if the control key was down during the event */
6499 /** True if the alt key was down during the event */
6558 setEvent : function(e){
6559 if(e == this || (e && e.browserEvent)){ // already wrapped
6562 this.browserEvent = e;
6564 // normalize buttons
6565 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6566 if(e.type == 'click' && this.button == -1){
6570 this.shiftKey = e.shiftKey;
6571 // mac metaKey behaves like ctrlKey
6572 this.ctrlKey = e.ctrlKey || e.metaKey;
6573 this.altKey = e.altKey;
6574 // in getKey these will be normalized for the mac
6575 this.keyCode = e.keyCode;
6576 // keyup warnings on firefox.
6577 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6578 // cache the target for the delayed and or buffered events
6579 this.target = E.getTarget(e);
6581 this.xy = E.getXY(e);
6584 this.shiftKey = false;
6585 this.ctrlKey = false;
6586 this.altKey = false;
6596 * Stop the event (preventDefault and stopPropagation)
6598 stopEvent : function(){
6599 if(this.browserEvent){
6600 if(this.browserEvent.type == 'mousedown'){
6601 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6603 E.stopEvent(this.browserEvent);
6608 * Prevents the browsers default handling of the event.
6610 preventDefault : function(){
6611 if(this.browserEvent){
6612 E.preventDefault(this.browserEvent);
6617 isNavKeyPress : function(){
6618 var k = this.keyCode;
6619 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6620 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6623 isSpecialKey : function(){
6624 var k = this.keyCode;
6625 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6626 (k == 16) || (k == 17) ||
6627 (k >= 18 && k <= 20) ||
6628 (k >= 33 && k <= 35) ||
6629 (k >= 36 && k <= 39) ||
6630 (k >= 44 && k <= 45);
6633 * Cancels bubbling of the event.
6635 stopPropagation : function(){
6636 if(this.browserEvent){
6637 if(this.type == 'mousedown'){
6638 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6640 E.stopPropagation(this.browserEvent);
6645 * Gets the key code for the event.
6648 getCharCode : function(){
6649 return this.charCode || this.keyCode;
6653 * Returns a normalized keyCode for the event.
6654 * @return {Number} The key code
6656 getKey : function(){
6657 var k = this.keyCode || this.charCode;
6658 return Roo.isSafari ? (safariKeys[k] || k) : k;
6662 * Gets the x coordinate of the event.
6665 getPageX : function(){
6670 * Gets the y coordinate of the event.
6673 getPageY : function(){
6678 * Gets the time of the event.
6681 getTime : function(){
6682 if(this.browserEvent){
6683 return E.getTime(this.browserEvent);
6689 * Gets the page coordinates of the event.
6690 * @return {Array} The xy values like [x, y]
6697 * Gets the target for the event.
6698 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6699 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6700 search as a number or element (defaults to 10 || document.body)
6701 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6702 * @return {HTMLelement}
6704 getTarget : function(selector, maxDepth, returnEl){
6705 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6708 * Gets the related target.
6709 * @return {HTMLElement}
6711 getRelatedTarget : function(){
6712 if(this.browserEvent){
6713 return E.getRelatedTarget(this.browserEvent);
6719 * Normalizes mouse wheel delta across browsers
6720 * @return {Number} The delta
6722 getWheelDelta : function(){
6723 var e = this.browserEvent;
6725 if(e.wheelDelta){ /* IE/Opera. */
6726 delta = e.wheelDelta/120;
6727 }else if(e.detail){ /* Mozilla case. */
6728 delta = -e.detail/3;
6734 * Returns true if the control, meta, shift or alt key was pressed during this event.
6737 hasModifier : function(){
6738 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6742 * Returns true if the target of this event equals el or is a child of el
6743 * @param {String/HTMLElement/Element} el
6744 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6747 within : function(el, related){
6748 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6749 return t && Roo.fly(el).contains(t);
6752 getPoint : function(){
6753 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6757 return new Roo.EventObjectImpl();
6762 * Ext JS Library 1.1.1
6763 * Copyright(c) 2006-2007, Ext JS, LLC.
6765 * Originally Released Under LGPL - original licence link has changed is not relivant.
6768 * <script type="text/javascript">
6772 // was in Composite Element!??!?!
6775 var D = Roo.lib.Dom;
6776 var E = Roo.lib.Event;
6777 var A = Roo.lib.Anim;
6779 // local style camelizing for speed
6781 var camelRe = /(-[a-z])/gi;
6782 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6783 var view = document.defaultView;
6786 * @class Roo.Element
6787 * Represents an Element in the DOM.<br><br>
6790 var el = Roo.get("my-div");
6793 var el = getEl("my-div");
6795 // or with a DOM element
6796 var el = Roo.get(myDivElement);
6798 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6799 * each call instead of constructing a new one.<br><br>
6800 * <b>Animations</b><br />
6801 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6802 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6804 Option Default Description
6805 --------- -------- ---------------------------------------------
6806 duration .35 The duration of the animation in seconds
6807 easing easeOut The YUI easing method
6808 callback none A function to execute when the anim completes
6809 scope this The scope (this) of the callback function
6811 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6812 * manipulate the animation. Here's an example:
6814 var el = Roo.get("my-div");
6819 // default animation
6820 el.setWidth(100, true);
6822 // animation with some options set
6829 // using the "anim" property to get the Anim object
6835 el.setWidth(100, opt);
6837 if(opt.anim.isAnimated()){
6841 * <b> Composite (Collections of) Elements</b><br />
6842 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6843 * @constructor Create a new Element directly.
6844 * @param {String/HTMLElement} element
6845 * @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).
6847 Roo.Element = function(element, forceNew){
6848 var dom = typeof element == "string" ?
6849 document.getElementById(element) : element;
6850 if(!dom){ // invalid id/element
6854 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6855 return Roo.Element.cache[id];
6865 * The DOM element ID
6868 this.id = id || Roo.id(dom);
6871 var El = Roo.Element;
6875 * The element's default display mode (defaults to "")
6878 originalDisplay : "",
6882 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6887 * Sets the element's visibility mode. When setVisible() is called it
6888 * will use this to determine whether to set the visibility or the display property.
6889 * @param visMode Element.VISIBILITY or Element.DISPLAY
6890 * @return {Roo.Element} this
6892 setVisibilityMode : function(visMode){
6893 this.visibilityMode = visMode;
6897 * Convenience method for setVisibilityMode(Element.DISPLAY)
6898 * @param {String} display (optional) What to set display to when visible
6899 * @return {Roo.Element} this
6901 enableDisplayMode : function(display){
6902 this.setVisibilityMode(El.DISPLAY);
6903 if(typeof display != "undefined") this.originalDisplay = display;
6908 * 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)
6909 * @param {String} selector The simple selector to test
6910 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6911 search as a number or element (defaults to 10 || document.body)
6912 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6913 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6915 findParent : function(simpleSelector, maxDepth, returnEl){
6916 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6917 maxDepth = maxDepth || 50;
6918 if(typeof maxDepth != "number"){
6919 stopEl = Roo.getDom(maxDepth);
6922 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6923 if(dq.is(p, simpleSelector)){
6924 return returnEl ? Roo.get(p) : p;
6934 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6935 * @param {String} selector The simple selector to test
6936 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6937 search as a number or element (defaults to 10 || document.body)
6938 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6939 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6941 findParentNode : function(simpleSelector, maxDepth, returnEl){
6942 var p = Roo.fly(this.dom.parentNode, '_internal');
6943 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6947 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6948 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6949 * @param {String} selector The simple selector to test
6950 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6951 search as a number or element (defaults to 10 || document.body)
6952 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6954 up : function(simpleSelector, maxDepth){
6955 return this.findParentNode(simpleSelector, maxDepth, true);
6961 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6962 * @param {String} selector The simple selector to test
6963 * @return {Boolean} True if this element matches the selector, else false
6965 is : function(simpleSelector){
6966 return Roo.DomQuery.is(this.dom, simpleSelector);
6970 * Perform animation on this element.
6971 * @param {Object} args The YUI animation control args
6972 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6973 * @param {Function} onComplete (optional) Function to call when animation completes
6974 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6975 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6976 * @return {Roo.Element} this
6978 animate : function(args, duration, onComplete, easing, animType){
6979 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6984 * @private Internal animation call
6986 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6987 animType = animType || 'run';
6989 var anim = Roo.lib.Anim[animType](
6991 (opt.duration || defaultDur) || .35,
6992 (opt.easing || defaultEase) || 'easeOut',
6994 Roo.callback(cb, this);
6995 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
7003 // private legacy anim prep
7004 preanim : function(a, i){
7005 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
7009 * Removes worthless text nodes
7010 * @param {Boolean} forceReclean (optional) By default the element
7011 * keeps track if it has been cleaned already so
7012 * you can call this over and over. However, if you update the element and
7013 * need to force a reclean, you can pass true.
7015 clean : function(forceReclean){
7016 if(this.isCleaned && forceReclean !== true){
7020 var d = this.dom, n = d.firstChild, ni = -1;
7022 var nx = n.nextSibling;
7023 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7030 this.isCleaned = true;
7035 calcOffsetsTo : function(el){
7038 var restorePos = false;
7039 if(el.getStyle('position') == 'static'){
7040 el.position('relative');
7045 while(op && op != d && op.tagName != 'HTML'){
7048 op = op.offsetParent;
7051 el.position('static');
7057 * Scrolls this element into view within the passed container.
7058 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7059 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7060 * @return {Roo.Element} this
7062 scrollIntoView : function(container, hscroll){
7063 var c = Roo.getDom(container) || document.body;
7066 var o = this.calcOffsetsTo(c),
7069 b = t+el.offsetHeight,
7070 r = l+el.offsetWidth;
7072 var ch = c.clientHeight;
7073 var ct = parseInt(c.scrollTop, 10);
7074 var cl = parseInt(c.scrollLeft, 10);
7076 var cr = cl + c.clientWidth;
7084 if(hscroll !== false){
7088 c.scrollLeft = r-c.clientWidth;
7095 scrollChildIntoView : function(child, hscroll){
7096 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7100 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7101 * the new height may not be available immediately.
7102 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7103 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7104 * @param {Function} onComplete (optional) Function to call when animation completes
7105 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7106 * @return {Roo.Element} this
7108 autoHeight : function(animate, duration, onComplete, easing){
7109 var oldHeight = this.getHeight();
7111 this.setHeight(1); // force clipping
7112 setTimeout(function(){
7113 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7115 this.setHeight(height);
7117 if(typeof onComplete == "function"){
7121 this.setHeight(oldHeight); // restore original height
7122 this.setHeight(height, animate, duration, function(){
7124 if(typeof onComplete == "function") onComplete();
7125 }.createDelegate(this), easing);
7127 }.createDelegate(this), 0);
7132 * Returns true if this element is an ancestor of the passed element
7133 * @param {HTMLElement/String} el The element to check
7134 * @return {Boolean} True if this element is an ancestor of el, else false
7136 contains : function(el){
7137 if(!el){return false;}
7138 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7142 * Checks whether the element is currently visible using both visibility and display properties.
7143 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7144 * @return {Boolean} True if the element is currently visible, else false
7146 isVisible : function(deep) {
7147 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7148 if(deep !== true || !vis){
7151 var p = this.dom.parentNode;
7152 while(p && p.tagName.toLowerCase() != "body"){
7153 if(!Roo.fly(p, '_isVisible').isVisible()){
7162 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7163 * @param {String} selector The CSS selector
7164 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7165 * @return {CompositeElement/CompositeElementLite} The composite element
7167 select : function(selector, unique){
7168 return El.select(selector, unique, this.dom);
7172 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7173 * @param {String} selector The CSS selector
7174 * @return {Array} An array of the matched nodes
7176 query : function(selector, unique){
7177 return Roo.DomQuery.select(selector, this.dom);
7181 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7182 * @param {String} selector The CSS selector
7183 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7184 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7186 child : function(selector, returnDom){
7187 var n = Roo.DomQuery.selectNode(selector, this.dom);
7188 return returnDom ? n : Roo.get(n);
7192 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7193 * @param {String} selector The CSS selector
7194 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7195 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7197 down : function(selector, returnDom){
7198 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7199 return returnDom ? n : Roo.get(n);
7203 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7204 * @param {String} group The group the DD object is member of
7205 * @param {Object} config The DD config object
7206 * @param {Object} overrides An object containing methods to override/implement on the DD object
7207 * @return {Roo.dd.DD} The DD object
7209 initDD : function(group, config, overrides){
7210 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7211 return Roo.apply(dd, overrides);
7215 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7216 * @param {String} group The group the DDProxy object is member of
7217 * @param {Object} config The DDProxy config object
7218 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7219 * @return {Roo.dd.DDProxy} The DDProxy object
7221 initDDProxy : function(group, config, overrides){
7222 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7223 return Roo.apply(dd, overrides);
7227 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7228 * @param {String} group The group the DDTarget object is member of
7229 * @param {Object} config The DDTarget config object
7230 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7231 * @return {Roo.dd.DDTarget} The DDTarget object
7233 initDDTarget : function(group, config, overrides){
7234 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7235 return Roo.apply(dd, overrides);
7239 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7240 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7241 * @param {Boolean} visible Whether the element is visible
7242 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7243 * @return {Roo.Element} this
7245 setVisible : function(visible, animate){
7247 if(this.visibilityMode == El.DISPLAY){
7248 this.setDisplayed(visible);
7251 this.dom.style.visibility = visible ? "visible" : "hidden";
7254 // closure for composites
7256 var visMode = this.visibilityMode;
7258 this.setOpacity(.01);
7259 this.setVisible(true);
7261 this.anim({opacity: { to: (visible?1:0) }},
7262 this.preanim(arguments, 1),
7263 null, .35, 'easeIn', function(){
7265 if(visMode == El.DISPLAY){
7266 dom.style.display = "none";
7268 dom.style.visibility = "hidden";
7270 Roo.get(dom).setOpacity(1);
7278 * Returns true if display is not "none"
7281 isDisplayed : function() {
7282 return this.getStyle("display") != "none";
7286 * Toggles the element's visibility or display, depending on visibility mode.
7287 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7288 * @return {Roo.Element} this
7290 toggle : function(animate){
7291 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7296 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7297 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7298 * @return {Roo.Element} this
7300 setDisplayed : function(value) {
7301 if(typeof value == "boolean"){
7302 value = value ? this.originalDisplay : "none";
7304 this.setStyle("display", value);
7309 * Tries to focus the element. Any exceptions are caught and ignored.
7310 * @return {Roo.Element} this
7312 focus : function() {
7320 * Tries to blur the element. Any exceptions are caught and ignored.
7321 * @return {Roo.Element} this
7331 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7332 * @param {String/Array} className The CSS class to add, or an array of classes
7333 * @return {Roo.Element} this
7335 addClass : function(className){
7336 if(className instanceof Array){
7337 for(var i = 0, len = className.length; i < len; i++) {
7338 this.addClass(className[i]);
7341 if(className && !this.hasClass(className)){
7342 this.dom.className = this.dom.className + " " + className;
7349 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7350 * @param {String/Array} className The CSS class to add, or an array of classes
7351 * @return {Roo.Element} this
7353 radioClass : function(className){
7354 var siblings = this.dom.parentNode.childNodes;
7355 for(var i = 0; i < siblings.length; i++) {
7356 var s = siblings[i];
7357 if(s.nodeType == 1){
7358 Roo.get(s).removeClass(className);
7361 this.addClass(className);
7366 * Removes one or more CSS classes from the element.
7367 * @param {String/Array} className The CSS class to remove, or an array of classes
7368 * @return {Roo.Element} this
7370 removeClass : function(className){
7371 if(!className || !this.dom.className){
7374 if(className instanceof Array){
7375 for(var i = 0, len = className.length; i < len; i++) {
7376 this.removeClass(className[i]);
7379 if(this.hasClass(className)){
7380 var re = this.classReCache[className];
7382 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7383 this.classReCache[className] = re;
7385 this.dom.className =
7386 this.dom.className.replace(re, " ");
7396 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7397 * @param {String} className The CSS class to toggle
7398 * @return {Roo.Element} this
7400 toggleClass : function(className){
7401 if(this.hasClass(className)){
7402 this.removeClass(className);
7404 this.addClass(className);
7410 * Checks if the specified CSS class exists on this element's DOM node.
7411 * @param {String} className The CSS class to check for
7412 * @return {Boolean} True if the class exists, else false
7414 hasClass : function(className){
7415 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7419 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7420 * @param {String} oldClassName The CSS class to replace
7421 * @param {String} newClassName The replacement CSS class
7422 * @return {Roo.Element} this
7424 replaceClass : function(oldClassName, newClassName){
7425 this.removeClass(oldClassName);
7426 this.addClass(newClassName);
7431 * Returns an object with properties matching the styles requested.
7432 * For example, el.getStyles('color', 'font-size', 'width') might return
7433 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7434 * @param {String} style1 A style name
7435 * @param {String} style2 A style name
7436 * @param {String} etc.
7437 * @return {Object} The style object
7439 getStyles : function(){
7440 var a = arguments, len = a.length, r = {};
7441 for(var i = 0; i < len; i++){
7442 r[a[i]] = this.getStyle(a[i]);
7448 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7449 * @param {String} property The style property whose value is returned.
7450 * @return {String} The current value of the style property for this element.
7452 getStyle : function(){
7453 return view && view.getComputedStyle ?
7455 var el = this.dom, v, cs, camel;
7456 if(prop == 'float'){
7459 if(el.style && (v = el.style[prop])){
7462 if(cs = view.getComputedStyle(el, "")){
7463 if(!(camel = propCache[prop])){
7464 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7471 var el = this.dom, v, cs, camel;
7472 if(prop == 'opacity'){
7473 if(typeof el.style.filter == 'string'){
7474 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7476 var fv = parseFloat(m[1]);
7478 return fv ? fv / 100 : 0;
7483 }else if(prop == 'float'){
7484 prop = "styleFloat";
7486 if(!(camel = propCache[prop])){
7487 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7489 if(v = el.style[camel]){
7492 if(cs = el.currentStyle){
7500 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7501 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7502 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7503 * @return {Roo.Element} this
7505 setStyle : function(prop, value){
7506 if(typeof prop == "string"){
7508 if (prop == 'float') {
7509 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7514 if(!(camel = propCache[prop])){
7515 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7518 if(camel == 'opacity') {
7519 this.setOpacity(value);
7521 this.dom.style[camel] = value;
7524 for(var style in prop){
7525 if(typeof prop[style] != "function"){
7526 this.setStyle(style, prop[style]);
7534 * More flexible version of {@link #setStyle} for setting style properties.
7535 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7536 * a function which returns such a specification.
7537 * @return {Roo.Element} this
7539 applyStyles : function(style){
7540 Roo.DomHelper.applyStyles(this.dom, style);
7545 * 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).
7546 * @return {Number} The X position of the element
7549 return D.getX(this.dom);
7553 * 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).
7554 * @return {Number} The Y position of the element
7557 return D.getY(this.dom);
7561 * 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).
7562 * @return {Array} The XY position of the element
7565 return D.getXY(this.dom);
7569 * 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).
7570 * @param {Number} The X position of the element
7571 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7572 * @return {Roo.Element} this
7574 setX : function(x, animate){
7576 D.setX(this.dom, x);
7578 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7584 * 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).
7585 * @param {Number} The Y position of the element
7586 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7587 * @return {Roo.Element} this
7589 setY : function(y, animate){
7591 D.setY(this.dom, y);
7593 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7599 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7600 * @param {String} left The left CSS property value
7601 * @return {Roo.Element} this
7603 setLeft : function(left){
7604 this.setStyle("left", this.addUnits(left));
7609 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7610 * @param {String} top The top CSS property value
7611 * @return {Roo.Element} this
7613 setTop : function(top){
7614 this.setStyle("top", this.addUnits(top));
7619 * Sets the element's CSS right style.
7620 * @param {String} right The right CSS property value
7621 * @return {Roo.Element} this
7623 setRight : function(right){
7624 this.setStyle("right", this.addUnits(right));
7629 * Sets the element's CSS bottom style.
7630 * @param {String} bottom The bottom CSS property value
7631 * @return {Roo.Element} this
7633 setBottom : function(bottom){
7634 this.setStyle("bottom", this.addUnits(bottom));
7639 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7640 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7641 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7642 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7643 * @return {Roo.Element} this
7645 setXY : function(pos, animate){
7647 D.setXY(this.dom, pos);
7649 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7655 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7656 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7657 * @param {Number} x X value for new position (coordinates are page-based)
7658 * @param {Number} y Y value for new position (coordinates are page-based)
7659 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7660 * @return {Roo.Element} this
7662 setLocation : function(x, y, animate){
7663 this.setXY([x, y], this.preanim(arguments, 2));
7668 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7669 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7670 * @param {Number} x X value for new position (coordinates are page-based)
7671 * @param {Number} y Y value for new position (coordinates are page-based)
7672 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7673 * @return {Roo.Element} this
7675 moveTo : function(x, y, animate){
7676 this.setXY([x, y], this.preanim(arguments, 2));
7681 * Returns the region of the given element.
7682 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7683 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7685 getRegion : function(){
7686 return D.getRegion(this.dom);
7690 * Returns the offset height of the element
7691 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7692 * @return {Number} The element's height
7694 getHeight : function(contentHeight){
7695 var h = this.dom.offsetHeight || 0;
7696 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7700 * Returns the offset width of the element
7701 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7702 * @return {Number} The element's width
7704 getWidth : function(contentWidth){
7705 var w = this.dom.offsetWidth || 0;
7706 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7710 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7711 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7712 * if a height has not been set using CSS.
7715 getComputedHeight : function(){
7716 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7718 h = parseInt(this.getStyle('height'), 10) || 0;
7719 if(!this.isBorderBox()){
7720 h += this.getFrameWidth('tb');
7727 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7728 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7729 * if a width has not been set using CSS.
7732 getComputedWidth : function(){
7733 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7735 w = parseInt(this.getStyle('width'), 10) || 0;
7736 if(!this.isBorderBox()){
7737 w += this.getFrameWidth('lr');
7744 * Returns the size of the element.
7745 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7746 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7748 getSize : function(contentSize){
7749 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7753 * Returns the width and height of the viewport.
7754 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7756 getViewSize : function(){
7757 var d = this.dom, doc = document, aw = 0, ah = 0;
7758 if(d == doc || d == doc.body){
7759 return {width : D.getViewWidth(), height: D.getViewHeight()};
7762 width : d.clientWidth,
7763 height: d.clientHeight
7769 * Returns the value of the "value" attribute
7770 * @param {Boolean} asNumber true to parse the value as a number
7771 * @return {String/Number}
7773 getValue : function(asNumber){
7774 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7778 adjustWidth : function(width){
7779 if(typeof width == "number"){
7780 if(this.autoBoxAdjust && !this.isBorderBox()){
7781 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7791 adjustHeight : function(height){
7792 if(typeof height == "number"){
7793 if(this.autoBoxAdjust && !this.isBorderBox()){
7794 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7804 * Set the width of the element
7805 * @param {Number} width The new width
7806 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7807 * @return {Roo.Element} this
7809 setWidth : function(width, animate){
7810 width = this.adjustWidth(width);
7812 this.dom.style.width = this.addUnits(width);
7814 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7820 * Set the height of the element
7821 * @param {Number} height The new height
7822 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7823 * @return {Roo.Element} this
7825 setHeight : function(height, animate){
7826 height = this.adjustHeight(height);
7828 this.dom.style.height = this.addUnits(height);
7830 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7836 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7837 * @param {Number} width The new width
7838 * @param {Number} height The new height
7839 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7840 * @return {Roo.Element} this
7842 setSize : function(width, height, animate){
7843 if(typeof width == "object"){ // in case of object from getSize()
7844 height = width.height; width = width.width;
7846 width = this.adjustWidth(width); height = this.adjustHeight(height);
7848 this.dom.style.width = this.addUnits(width);
7849 this.dom.style.height = this.addUnits(height);
7851 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7857 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7858 * @param {Number} x X value for new position (coordinates are page-based)
7859 * @param {Number} y Y value for new position (coordinates are page-based)
7860 * @param {Number} width The new width
7861 * @param {Number} height The new height
7862 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7863 * @return {Roo.Element} this
7865 setBounds : function(x, y, width, height, animate){
7867 this.setSize(width, height);
7868 this.setLocation(x, y);
7870 width = this.adjustWidth(width); height = this.adjustHeight(height);
7871 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7872 this.preanim(arguments, 4), 'motion');
7878 * 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.
7879 * @param {Roo.lib.Region} region The region to fill
7880 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7881 * @return {Roo.Element} this
7883 setRegion : function(region, animate){
7884 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7889 * Appends an event handler
7891 * @param {String} eventName The type of event to append
7892 * @param {Function} fn The method the event invokes
7893 * @param {Object} scope (optional) The scope (this object) of the fn
7894 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7896 addListener : function(eventName, fn, scope, options){
7898 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7903 * Removes an event handler from this element
7904 * @param {String} eventName the type of event to remove
7905 * @param {Function} fn the method the event invokes
7906 * @return {Roo.Element} this
7908 removeListener : function(eventName, fn){
7909 Roo.EventManager.removeListener(this.dom, eventName, fn);
7914 * Removes all previous added listeners from this element
7915 * @return {Roo.Element} this
7917 removeAllListeners : function(){
7918 E.purgeElement(this.dom);
7922 relayEvent : function(eventName, observable){
7923 this.on(eventName, function(e){
7924 observable.fireEvent(eventName, e);
7929 * Set the opacity of the element
7930 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7931 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7932 * @return {Roo.Element} this
7934 setOpacity : function(opacity, animate){
7936 var s = this.dom.style;
7939 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7940 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7942 s.opacity = opacity;
7945 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7951 * Gets the left X coordinate
7952 * @param {Boolean} local True to get the local css position instead of page coordinate
7955 getLeft : function(local){
7959 return parseInt(this.getStyle("left"), 10) || 0;
7964 * Gets the right X coordinate of the element (element X position + element width)
7965 * @param {Boolean} local True to get the local css position instead of page coordinate
7968 getRight : function(local){
7970 return this.getX() + this.getWidth();
7972 return (this.getLeft(true) + this.getWidth()) || 0;
7977 * Gets the top Y coordinate
7978 * @param {Boolean} local True to get the local css position instead of page coordinate
7981 getTop : function(local) {
7985 return parseInt(this.getStyle("top"), 10) || 0;
7990 * Gets the bottom Y coordinate of the element (element Y position + element height)
7991 * @param {Boolean} local True to get the local css position instead of page coordinate
7994 getBottom : function(local){
7996 return this.getY() + this.getHeight();
7998 return (this.getTop(true) + this.getHeight()) || 0;
8003 * Initializes positioning on this element. If a desired position is not passed, it will make the
8004 * the element positioned relative IF it is not already positioned.
8005 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
8006 * @param {Number} zIndex (optional) The zIndex to apply
8007 * @param {Number} x (optional) Set the page X position
8008 * @param {Number} y (optional) Set the page Y position
8010 position : function(pos, zIndex, x, y){
8012 if(this.getStyle('position') == 'static'){
8013 this.setStyle('position', 'relative');
8016 this.setStyle("position", pos);
8019 this.setStyle("z-index", zIndex);
8021 if(x !== undefined && y !== undefined){
8023 }else if(x !== undefined){
8025 }else if(y !== undefined){
8031 * Clear positioning back to the default when the document was loaded
8032 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8033 * @return {Roo.Element} this
8035 clearPositioning : function(value){
8043 "position" : "static"
8049 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8050 * snapshot before performing an update and then restoring the element.
8053 getPositioning : function(){
8054 var l = this.getStyle("left");
8055 var t = this.getStyle("top");
8057 "position" : this.getStyle("position"),
8059 "right" : l ? "" : this.getStyle("right"),
8061 "bottom" : t ? "" : this.getStyle("bottom"),
8062 "z-index" : this.getStyle("z-index")
8067 * Gets the width of the border(s) for the specified side(s)
8068 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8069 * passing lr would get the border (l)eft width + the border (r)ight width.
8070 * @return {Number} The width of the sides passed added together
8072 getBorderWidth : function(side){
8073 return this.addStyles(side, El.borders);
8077 * Gets the width of the padding(s) for the specified side(s)
8078 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8079 * passing lr would get the padding (l)eft + the padding (r)ight.
8080 * @return {Number} The padding of the sides passed added together
8082 getPadding : function(side){
8083 return this.addStyles(side, El.paddings);
8087 * Set positioning with an object returned by getPositioning().
8088 * @param {Object} posCfg
8089 * @return {Roo.Element} this
8091 setPositioning : function(pc){
8092 this.applyStyles(pc);
8093 if(pc.right == "auto"){
8094 this.dom.style.right = "";
8096 if(pc.bottom == "auto"){
8097 this.dom.style.bottom = "";
8103 fixDisplay : function(){
8104 if(this.getStyle("display") == "none"){
8105 this.setStyle("visibility", "hidden");
8106 this.setStyle("display", this.originalDisplay); // first try reverting to default
8107 if(this.getStyle("display") == "none"){ // if that fails, default to block
8108 this.setStyle("display", "block");
8114 * Quick set left and top adding default units
8115 * @param {String} left The left CSS property value
8116 * @param {String} top The top CSS property value
8117 * @return {Roo.Element} this
8119 setLeftTop : function(left, top){
8120 this.dom.style.left = this.addUnits(left);
8121 this.dom.style.top = this.addUnits(top);
8126 * Move this element relative to its current position.
8127 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8128 * @param {Number} distance How far to move the element in pixels
8129 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8130 * @return {Roo.Element} this
8132 move : function(direction, distance, animate){
8133 var xy = this.getXY();
8134 direction = direction.toLowerCase();
8138 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8142 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8147 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8152 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8159 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8160 * @return {Roo.Element} this
8163 if(!this.isClipped){
8164 this.isClipped = true;
8165 this.originalClip = {
8166 "o": this.getStyle("overflow"),
8167 "x": this.getStyle("overflow-x"),
8168 "y": this.getStyle("overflow-y")
8170 this.setStyle("overflow", "hidden");
8171 this.setStyle("overflow-x", "hidden");
8172 this.setStyle("overflow-y", "hidden");
8178 * Return clipping (overflow) to original clipping before clip() was called
8179 * @return {Roo.Element} this
8181 unclip : function(){
8183 this.isClipped = false;
8184 var o = this.originalClip;
8185 if(o.o){this.setStyle("overflow", o.o);}
8186 if(o.x){this.setStyle("overflow-x", o.x);}
8187 if(o.y){this.setStyle("overflow-y", o.y);}
8194 * Gets the x,y coordinates specified by the anchor position on the element.
8195 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8196 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8197 * {width: (target width), height: (target height)} (defaults to the element's current size)
8198 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8199 * @return {Array} [x, y] An array containing the element's x and y coordinates
8201 getAnchorXY : function(anchor, local, s){
8202 //Passing a different size is useful for pre-calculating anchors,
8203 //especially for anchored animations that change the el size.
8205 var w, h, vp = false;
8208 if(d == document.body || d == document){
8210 w = D.getViewWidth(); h = D.getViewHeight();
8212 w = this.getWidth(); h = this.getHeight();
8215 w = s.width; h = s.height;
8217 var x = 0, y = 0, r = Math.round;
8218 switch((anchor || "tl").toLowerCase()){
8260 var sc = this.getScroll();
8261 return [x + sc.left, y + sc.top];
8263 //Add the element's offset xy
8264 var o = this.getXY();
8265 return [x+o[0], y+o[1]];
8269 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8270 * supported position values.
8271 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8272 * @param {String} position The position to align to.
8273 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8274 * @return {Array} [x, y]
8276 getAlignToXY : function(el, p, o){
8280 throw "Element.alignTo with an element that doesn't exist";
8282 var c = false; //constrain to viewport
8283 var p1 = "", p2 = "";
8290 }else if(p.indexOf("-") == -1){
8293 p = p.toLowerCase();
8294 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8296 throw "Element.alignTo with an invalid alignment " + p;
8298 p1 = m[1]; p2 = m[2]; c = !!m[3];
8300 //Subtract the aligned el's internal xy from the target's offset xy
8301 //plus custom offset to get the aligned el's new offset xy
8302 var a1 = this.getAnchorXY(p1, true);
8303 var a2 = el.getAnchorXY(p2, false);
8304 var x = a2[0] - a1[0] + o[0];
8305 var y = a2[1] - a1[1] + o[1];
8307 //constrain the aligned el to viewport if necessary
8308 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8309 // 5px of margin for ie
8310 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8312 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8313 //perpendicular to the vp border, allow the aligned el to slide on that border,
8314 //otherwise swap the aligned el to the opposite border of the target.
8315 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8316 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8317 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8318 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8321 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8322 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8324 if((x+w) > dw + scrollX){
8325 x = swapX ? r.left-w : dw+scrollX-w;
8328 x = swapX ? r.right : scrollX;
8330 if((y+h) > dh + scrollY){
8331 y = swapY ? r.top-h : dh+scrollY-h;
8334 y = swapY ? r.bottom : scrollY;
8341 getConstrainToXY : function(){
8342 var os = {top:0, left:0, bottom:0, right: 0};
8344 return function(el, local, offsets, proposedXY){
8346 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8348 var vw, vh, vx = 0, vy = 0;
8349 if(el.dom == document.body || el.dom == document){
8350 vw = Roo.lib.Dom.getViewWidth();
8351 vh = Roo.lib.Dom.getViewHeight();
8353 vw = el.dom.clientWidth;
8354 vh = el.dom.clientHeight;
8356 var vxy = el.getXY();
8362 var s = el.getScroll();
8364 vx += offsets.left + s.left;
8365 vy += offsets.top + s.top;
8367 vw -= offsets.right;
8368 vh -= offsets.bottom;
8373 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8374 var x = xy[0], y = xy[1];
8375 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8377 // only move it if it needs it
8380 // first validate right/bottom
8389 // then make sure top/left isn't negative
8398 return moved ? [x, y] : false;
8403 adjustForConstraints : function(xy, parent, offsets){
8404 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8408 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8409 * document it aligns it to the viewport.
8410 * The position parameter is optional, and can be specified in any one of the following formats:
8412 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8413 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8414 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8415 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8416 * <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
8417 * element's anchor point, and the second value is used as the target's anchor point.</li>
8419 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8420 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8421 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8422 * that specified in order to enforce the viewport constraints.
8423 * Following are all of the supported anchor positions:
8426 ----- -----------------------------
8427 tl The top left corner (default)
8428 t The center of the top edge
8429 tr The top right corner
8430 l The center of the left edge
8431 c In the center of the element
8432 r The center of the right edge
8433 bl The bottom left corner
8434 b The center of the bottom edge
8435 br The bottom right corner
8439 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8440 el.alignTo("other-el");
8442 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8443 el.alignTo("other-el", "tr?");
8445 // align the bottom right corner of el with the center left edge of other-el
8446 el.alignTo("other-el", "br-l?");
8448 // align the center of el with the bottom left corner of other-el and
8449 // adjust the x position by -6 pixels (and the y position by 0)
8450 el.alignTo("other-el", "c-bl", [-6, 0]);
8452 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8453 * @param {String} position The position to align to.
8454 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8455 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8456 * @return {Roo.Element} this
8458 alignTo : function(element, position, offsets, animate){
8459 var xy = this.getAlignToXY(element, position, offsets);
8460 this.setXY(xy, this.preanim(arguments, 3));
8465 * Anchors an element to another element and realigns it when the window is resized.
8466 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8467 * @param {String} position The position to align to.
8468 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8469 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8470 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8471 * is a number, it is used as the buffer delay (defaults to 50ms).
8472 * @param {Function} callback The function to call after the animation finishes
8473 * @return {Roo.Element} this
8475 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8476 var action = function(){
8477 this.alignTo(el, alignment, offsets, animate);
8478 Roo.callback(callback, this);
8480 Roo.EventManager.onWindowResize(action, this);
8481 var tm = typeof monitorScroll;
8482 if(tm != 'undefined'){
8483 Roo.EventManager.on(window, 'scroll', action, this,
8484 {buffer: tm == 'number' ? monitorScroll : 50});
8486 action.call(this); // align immediately
8490 * Clears any opacity settings from this element. Required in some cases for IE.
8491 * @return {Roo.Element} this
8493 clearOpacity : function(){
8494 if (window.ActiveXObject) {
8495 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8496 this.dom.style.filter = "";
8499 this.dom.style.opacity = "";
8500 this.dom.style["-moz-opacity"] = "";
8501 this.dom.style["-khtml-opacity"] = "";
8507 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8508 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8509 * @return {Roo.Element} this
8511 hide : function(animate){
8512 this.setVisible(false, this.preanim(arguments, 0));
8517 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8518 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8519 * @return {Roo.Element} this
8521 show : function(animate){
8522 this.setVisible(true, this.preanim(arguments, 0));
8527 * @private Test if size has a unit, otherwise appends the default
8529 addUnits : function(size){
8530 return Roo.Element.addUnits(size, this.defaultUnit);
8534 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8535 * @return {Roo.Element} this
8537 beginMeasure : function(){
8539 if(el.offsetWidth || el.offsetHeight){
8540 return this; // offsets work already
8543 var p = this.dom, b = document.body; // start with this element
8544 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8545 var pe = Roo.get(p);
8546 if(pe.getStyle('display') == 'none'){
8547 changed.push({el: p, visibility: pe.getStyle("visibility")});
8548 p.style.visibility = "hidden";
8549 p.style.display = "block";
8553 this._measureChanged = changed;
8559 * Restores displays to before beginMeasure was called
8560 * @return {Roo.Element} this
8562 endMeasure : function(){
8563 var changed = this._measureChanged;
8565 for(var i = 0, len = changed.length; i < len; i++) {
8567 r.el.style.visibility = r.visibility;
8568 r.el.style.display = "none";
8570 this._measureChanged = null;
8576 * Update the innerHTML of this element, optionally searching for and processing scripts
8577 * @param {String} html The new HTML
8578 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8579 * @param {Function} callback For async script loading you can be noticed when the update completes
8580 * @return {Roo.Element} this
8582 update : function(html, loadScripts, callback){
8583 if(typeof html == "undefined"){
8586 if(loadScripts !== true){
8587 this.dom.innerHTML = html;
8588 if(typeof callback == "function"){
8596 html += '<span id="' + id + '"></span>';
8598 E.onAvailable(id, function(){
8599 var hd = document.getElementsByTagName("head")[0];
8600 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8601 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8602 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8605 while(match = re.exec(html)){
8606 var attrs = match[1];
8607 var srcMatch = attrs ? attrs.match(srcRe) : false;
8608 if(srcMatch && srcMatch[2]){
8609 var s = document.createElement("script");
8610 s.src = srcMatch[2];
8611 var typeMatch = attrs.match(typeRe);
8612 if(typeMatch && typeMatch[2]){
8613 s.type = typeMatch[2];
8616 }else if(match[2] && match[2].length > 0){
8617 if(window.execScript) {
8618 window.execScript(match[2]);
8626 window.eval(match[2]);
8630 var el = document.getElementById(id);
8631 if(el){el.parentNode.removeChild(el);}
8632 if(typeof callback == "function"){
8636 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8641 * Direct access to the UpdateManager update() method (takes the same parameters).
8642 * @param {String/Function} url The url for this request or a function to call to get the url
8643 * @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}
8644 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8645 * @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.
8646 * @return {Roo.Element} this
8649 var um = this.getUpdateManager();
8650 um.update.apply(um, arguments);
8655 * Gets this element's UpdateManager
8656 * @return {Roo.UpdateManager} The UpdateManager
8658 getUpdateManager : function(){
8659 if(!this.updateManager){
8660 this.updateManager = new Roo.UpdateManager(this);
8662 return this.updateManager;
8666 * Disables text selection for this element (normalized across browsers)
8667 * @return {Roo.Element} this
8669 unselectable : function(){
8670 this.dom.unselectable = "on";
8671 this.swallowEvent("selectstart", true);
8672 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8673 this.addClass("x-unselectable");
8678 * Calculates the x, y to center this element on the screen
8679 * @return {Array} The x, y values [x, y]
8681 getCenterXY : function(){
8682 return this.getAlignToXY(document, 'c-c');
8686 * Centers the Element in either the viewport, or another Element.
8687 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8689 center : function(centerIn){
8690 this.alignTo(centerIn || document, 'c-c');
8695 * Tests various css rules/browsers to determine if this element uses a border box
8698 isBorderBox : function(){
8699 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8703 * Return a box {x, y, width, height} that can be used to set another elements
8704 * size/location to match this element.
8705 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8706 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8707 * @return {Object} box An object in the format {x, y, width, height}
8709 getBox : function(contentBox, local){
8714 var left = parseInt(this.getStyle("left"), 10) || 0;
8715 var top = parseInt(this.getStyle("top"), 10) || 0;
8718 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8720 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8722 var l = this.getBorderWidth("l")+this.getPadding("l");
8723 var r = this.getBorderWidth("r")+this.getPadding("r");
8724 var t = this.getBorderWidth("t")+this.getPadding("t");
8725 var b = this.getBorderWidth("b")+this.getPadding("b");
8726 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)};
8728 bx.right = bx.x + bx.width;
8729 bx.bottom = bx.y + bx.height;
8734 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8735 for more information about the sides.
8736 * @param {String} sides
8739 getFrameWidth : function(sides, onlyContentBox){
8740 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8744 * 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.
8745 * @param {Object} box The box to fill {x, y, width, height}
8746 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8747 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8748 * @return {Roo.Element} this
8750 setBox : function(box, adjust, animate){
8751 var w = box.width, h = box.height;
8752 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8753 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8754 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8756 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8761 * Forces the browser to repaint this element
8762 * @return {Roo.Element} this
8764 repaint : function(){
8766 this.addClass("x-repaint");
8767 setTimeout(function(){
8768 Roo.get(dom).removeClass("x-repaint");
8774 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8775 * then it returns the calculated width of the sides (see getPadding)
8776 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8777 * @return {Object/Number}
8779 getMargins : function(side){
8782 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8783 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8784 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8785 right: parseInt(this.getStyle("margin-right"), 10) || 0
8788 return this.addStyles(side, El.margins);
8793 addStyles : function(sides, styles){
8795 for(var i = 0, len = sides.length; i < len; i++){
8796 v = this.getStyle(styles[sides.charAt(i)]);
8798 w = parseInt(v, 10);
8806 * Creates a proxy element of this element
8807 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8808 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8809 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8810 * @return {Roo.Element} The new proxy element
8812 createProxy : function(config, renderTo, matchBox){
8814 renderTo = Roo.getDom(renderTo);
8816 renderTo = document.body;
8818 config = typeof config == "object" ?
8819 config : {tag : "div", cls: config};
8820 var proxy = Roo.DomHelper.append(renderTo, config, true);
8822 proxy.setBox(this.getBox());
8828 * Puts a mask over this element to disable user interaction. Requires core.css.
8829 * This method can only be applied to elements which accept child nodes.
8830 * @param {String} msg (optional) A message to display in the mask
8831 * @param {String} msgCls (optional) A css class to apply to the msg element
8832 * @return {Element} The mask element
8834 mask : function(msg, msgCls){
8835 if(this.getStyle("position") == "static"){
8836 this.setStyle("position", "relative");
8839 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8841 this.addClass("x-masked");
8842 this._mask.setDisplayed(true);
8843 if(typeof msg == 'string'){
8845 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8847 var mm = this._maskMsg;
8848 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8849 mm.dom.firstChild.innerHTML = msg;
8850 mm.setDisplayed(true);
8853 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8854 this._mask.setHeight(this.getHeight());
8860 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8861 * it is cached for reuse.
8863 unmask : function(removeEl){
8865 if(removeEl === true){
8866 this._mask.remove();
8869 this._maskMsg.remove();
8870 delete this._maskMsg;
8873 this._mask.setDisplayed(false);
8875 this._maskMsg.setDisplayed(false);
8879 this.removeClass("x-masked");
8883 * Returns true if this element is masked
8886 isMasked : function(){
8887 return this._mask && this._mask.isVisible();
8891 * Creates an iframe shim for this element to keep selects and other windowed objects from
8893 * @return {Roo.Element} The new shim element
8895 createShim : function(){
8896 var el = document.createElement('iframe');
8897 el.frameBorder = 'no';
8898 el.className = 'roo-shim';
8899 if(Roo.isIE && Roo.isSecure){
8900 el.src = Roo.SSL_SECURE_URL;
8902 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8903 shim.autoBoxAdjust = false;
8908 * Removes this element from the DOM and deletes it from the cache
8910 remove : function(){
8911 if(this.dom.parentNode){
8912 this.dom.parentNode.removeChild(this.dom);
8914 delete El.cache[this.dom.id];
8918 * Sets up event handlers to add and remove a css class when the mouse is over this element
8919 * @param {String} className
8920 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8921 * mouseout events for children elements
8922 * @return {Roo.Element} this
8924 addClassOnOver : function(className, preventFlicker){
8925 this.on("mouseover", function(){
8926 Roo.fly(this, '_internal').addClass(className);
8928 var removeFn = function(e){
8929 if(preventFlicker !== true || !e.within(this, true)){
8930 Roo.fly(this, '_internal').removeClass(className);
8933 this.on("mouseout", removeFn, this.dom);
8938 * Sets up event handlers to add and remove a css class when this element has the focus
8939 * @param {String} className
8940 * @return {Roo.Element} this
8942 addClassOnFocus : function(className){
8943 this.on("focus", function(){
8944 Roo.fly(this, '_internal').addClass(className);
8946 this.on("blur", function(){
8947 Roo.fly(this, '_internal').removeClass(className);
8952 * 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)
8953 * @param {String} className
8954 * @return {Roo.Element} this
8956 addClassOnClick : function(className){
8958 this.on("mousedown", function(){
8959 Roo.fly(dom, '_internal').addClass(className);
8960 var d = Roo.get(document);
8961 var fn = function(){
8962 Roo.fly(dom, '_internal').removeClass(className);
8963 d.removeListener("mouseup", fn);
8965 d.on("mouseup", fn);
8971 * Stops the specified event from bubbling and optionally prevents the default action
8972 * @param {String} eventName
8973 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8974 * @return {Roo.Element} this
8976 swallowEvent : function(eventName, preventDefault){
8977 var fn = function(e){
8978 e.stopPropagation();
8983 if(eventName instanceof Array){
8984 for(var i = 0, len = eventName.length; i < len; i++){
8985 this.on(eventName[i], fn);
8989 this.on(eventName, fn);
8996 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8999 * Sizes this element to its parent element's dimensions performing
9000 * neccessary box adjustments.
9001 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
9002 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
9003 * @return {Roo.Element} this
9005 fitToParent : function(monitorResize, targetParent) {
9006 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
9007 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
9008 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
9011 var p = Roo.get(targetParent || this.dom.parentNode);
9012 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
9013 if (monitorResize === true) {
9014 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
9015 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9021 * Gets the next sibling, skipping text nodes
9022 * @return {HTMLElement} The next sibling or null
9024 getNextSibling : function(){
9025 var n = this.dom.nextSibling;
9026 while(n && n.nodeType != 1){
9033 * Gets the previous sibling, skipping text nodes
9034 * @return {HTMLElement} The previous sibling or null
9036 getPrevSibling : function(){
9037 var n = this.dom.previousSibling;
9038 while(n && n.nodeType != 1){
9039 n = n.previousSibling;
9046 * Appends the passed element(s) to this element
9047 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9048 * @return {Roo.Element} this
9050 appendChild: function(el){
9057 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9058 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9059 * automatically generated with the specified attributes.
9060 * @param {HTMLElement} insertBefore (optional) a child element of this element
9061 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9062 * @return {Roo.Element} The new child element
9064 createChild: function(config, insertBefore, returnDom){
9065 config = config || {tag:'div'};
9067 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9069 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9073 * Appends this element to the passed element
9074 * @param {String/HTMLElement/Element} el The new parent element
9075 * @return {Roo.Element} this
9077 appendTo: function(el){
9078 el = Roo.getDom(el);
9079 el.appendChild(this.dom);
9084 * Inserts this element before the passed element in the DOM
9085 * @param {String/HTMLElement/Element} el The element to insert before
9086 * @return {Roo.Element} this
9088 insertBefore: function(el){
9089 el = Roo.getDom(el);
9090 el.parentNode.insertBefore(this.dom, el);
9095 * Inserts this element after the passed element in the DOM
9096 * @param {String/HTMLElement/Element} el The element to insert after
9097 * @return {Roo.Element} this
9099 insertAfter: function(el){
9100 el = Roo.getDom(el);
9101 el.parentNode.insertBefore(this.dom, el.nextSibling);
9106 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9107 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9108 * @return {Roo.Element} The new child
9110 insertFirst: function(el, returnDom){
9112 if(typeof el == 'object' && !el.nodeType){ // dh config
9113 return this.createChild(el, this.dom.firstChild, returnDom);
9115 el = Roo.getDom(el);
9116 this.dom.insertBefore(el, this.dom.firstChild);
9117 return !returnDom ? Roo.get(el) : el;
9122 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9123 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9124 * @param {String} where (optional) 'before' or 'after' defaults to before
9125 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9126 * @return {Roo.Element} the inserted Element
9128 insertSibling: function(el, where, returnDom){
9129 where = where ? where.toLowerCase() : 'before';
9131 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9133 if(typeof el == 'object' && !el.nodeType){ // dh config
9134 if(where == 'after' && !this.dom.nextSibling){
9135 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9137 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9141 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9142 where == 'before' ? this.dom : this.dom.nextSibling);
9151 * Creates and wraps this element with another element
9152 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9153 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9154 * @return {HTMLElement/Element} The newly created wrapper element
9156 wrap: function(config, returnDom){
9158 config = {tag: "div"};
9160 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9161 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9166 * Replaces the passed element with this element
9167 * @param {String/HTMLElement/Element} el The element to replace
9168 * @return {Roo.Element} this
9170 replace: function(el){
9172 this.insertBefore(el);
9178 * Inserts an html fragment into this element
9179 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9180 * @param {String} html The HTML fragment
9181 * @param {Boolean} returnEl True to return an Roo.Element
9182 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9184 insertHtml : function(where, html, returnEl){
9185 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9186 return returnEl ? Roo.get(el) : el;
9190 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9191 * @param {Object} o The object with the attributes
9192 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9193 * @return {Roo.Element} this
9195 set : function(o, useSet){
9197 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9199 if(attr == "style" || typeof o[attr] == "function") continue;
9201 el.className = o["cls"];
9203 if(useSet) el.setAttribute(attr, o[attr]);
9204 else el[attr] = o[attr];
9208 Roo.DomHelper.applyStyles(el, o.style);
9214 * Convenience method for constructing a KeyMap
9215 * @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:
9216 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9217 * @param {Function} fn The function to call
9218 * @param {Object} scope (optional) The scope of the function
9219 * @return {Roo.KeyMap} The KeyMap created
9221 addKeyListener : function(key, fn, scope){
9223 if(typeof key != "object" || key instanceof Array){
9239 return new Roo.KeyMap(this, config);
9243 * Creates a KeyMap for this element
9244 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9245 * @return {Roo.KeyMap} The KeyMap created
9247 addKeyMap : function(config){
9248 return new Roo.KeyMap(this, config);
9252 * Returns true if this element is scrollable.
9255 isScrollable : function(){
9257 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9261 * 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().
9262 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9263 * @param {Number} value The new scroll value
9264 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9265 * @return {Element} this
9268 scrollTo : function(side, value, animate){
9269 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9271 this.dom[prop] = value;
9273 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9274 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9280 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9281 * within this element's scrollable range.
9282 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9283 * @param {Number} distance How far to scroll the element in pixels
9284 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9285 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9286 * was scrolled as far as it could go.
9288 scroll : function(direction, distance, animate){
9289 if(!this.isScrollable()){
9293 var l = el.scrollLeft, t = el.scrollTop;
9294 var w = el.scrollWidth, h = el.scrollHeight;
9295 var cw = el.clientWidth, ch = el.clientHeight;
9296 direction = direction.toLowerCase();
9297 var scrolled = false;
9298 var a = this.preanim(arguments, 2);
9303 var v = Math.min(l + distance, w-cw);
9304 this.scrollTo("left", v, a);
9311 var v = Math.max(l - distance, 0);
9312 this.scrollTo("left", v, a);
9320 var v = Math.max(t - distance, 0);
9321 this.scrollTo("top", v, a);
9329 var v = Math.min(t + distance, h-ch);
9330 this.scrollTo("top", v, a);
9339 * Translates the passed page coordinates into left/top css values for this element
9340 * @param {Number/Array} x The page x or an array containing [x, y]
9341 * @param {Number} y The page y
9342 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9344 translatePoints : function(x, y){
9345 if(typeof x == 'object' || x instanceof Array){
9348 var p = this.getStyle('position');
9349 var o = this.getXY();
9351 var l = parseInt(this.getStyle('left'), 10);
9352 var t = parseInt(this.getStyle('top'), 10);
9355 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9358 t = (p == "relative") ? 0 : this.dom.offsetTop;
9361 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9365 * Returns the current scroll position of the element.
9366 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9368 getScroll : function(){
9369 var d = this.dom, doc = document;
9370 if(d == doc || d == doc.body){
9371 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9372 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9373 return {left: l, top: t};
9375 return {left: d.scrollLeft, top: d.scrollTop};
9380 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9381 * are convert to standard 6 digit hex color.
9382 * @param {String} attr The css attribute
9383 * @param {String} defaultValue The default value to use when a valid color isn't found
9384 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9387 getColor : function(attr, defaultValue, prefix){
9388 var v = this.getStyle(attr);
9389 if(!v || v == "transparent" || v == "inherit") {
9390 return defaultValue;
9392 var color = typeof prefix == "undefined" ? "#" : prefix;
9393 if(v.substr(0, 4) == "rgb("){
9394 var rvs = v.slice(4, v.length -1).split(",");
9395 for(var i = 0; i < 3; i++){
9396 var h = parseInt(rvs[i]).toString(16);
9403 if(v.substr(0, 1) == "#"){
9405 for(var i = 1; i < 4; i++){
9406 var c = v.charAt(i);
9409 }else if(v.length == 7){
9410 color += v.substr(1);
9414 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9418 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9419 * gradient background, rounded corners and a 4-way shadow.
9420 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9421 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9422 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9423 * @return {Roo.Element} this
9425 boxWrap : function(cls){
9426 cls = cls || 'x-box';
9427 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9428 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9433 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9434 * @param {String} namespace The namespace in which to look for the attribute
9435 * @param {String} name The attribute name
9436 * @return {String} The attribute value
9438 getAttributeNS : Roo.isIE ? function(ns, name){
9440 var type = typeof d[ns+":"+name];
9441 if(type != 'undefined' && type != 'unknown'){
9442 return d[ns+":"+name];
9445 } : function(ns, name){
9447 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9451 var ep = El.prototype;
9454 * Appends an event handler (Shorthand for addListener)
9455 * @param {String} eventName The type of event to append
9456 * @param {Function} fn The method the event invokes
9457 * @param {Object} scope (optional) The scope (this object) of the fn
9458 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9461 ep.on = ep.addListener;
9463 ep.mon = ep.addListener;
9466 * Removes an event handler from this element (shorthand for removeListener)
9467 * @param {String} eventName the type of event to remove
9468 * @param {Function} fn the method the event invokes
9469 * @return {Roo.Element} this
9472 ep.un = ep.removeListener;
9475 * true to automatically adjust width and height settings for box-model issues (default to true)
9477 ep.autoBoxAdjust = true;
9480 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9483 El.addUnits = function(v, defaultUnit){
9484 if(v === "" || v == "auto"){
9487 if(v === undefined){
9490 if(typeof v == "number" || !El.unitPattern.test(v)){
9491 return v + (defaultUnit || 'px');
9496 // special markup used throughout Roo when box wrapping elements
9497 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>';
9499 * Visibility mode constant - Use visibility to hide element
9505 * Visibility mode constant - Use display to hide element
9511 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9512 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9513 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9525 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9526 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9527 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9528 * @return {Element} The Element object
9531 El.get = function(el){
9533 if(!el){ return null; }
9534 if(typeof el == "string"){ // element id
9535 if(!(elm = document.getElementById(el))){
9538 if(ex = El.cache[el]){
9541 ex = El.cache[el] = new El(elm);
9544 }else if(el.tagName){ // dom element
9548 if(ex = El.cache[id]){
9551 ex = El.cache[id] = new El(el);
9554 }else if(el instanceof El){
9556 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9557 // catch case where it hasn't been appended
9558 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9561 }else if(el.isComposite){
9563 }else if(el instanceof Array){
9564 return El.select(el);
9565 }else if(el == document){
9566 // create a bogus element object representing the document object
9568 var f = function(){};
9569 f.prototype = El.prototype;
9571 docEl.dom = document;
9579 El.uncache = function(el){
9580 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9582 delete El.cache[a[i].id || a[i]];
9588 // Garbage collection - uncache elements/purge listeners on orphaned elements
9589 // so we don't hold a reference and cause the browser to retain them
9590 El.garbageCollect = function(){
9591 if(!Roo.enableGarbageCollector){
9592 clearInterval(El.collectorThread);
9595 for(var eid in El.cache){
9596 var el = El.cache[eid], d = el.dom;
9597 // -------------------------------------------------------
9598 // Determining what is garbage:
9599 // -------------------------------------------------------
9601 // dom node is null, definitely garbage
9602 // -------------------------------------------------------
9604 // no parentNode == direct orphan, definitely garbage
9605 // -------------------------------------------------------
9606 // !d.offsetParent && !document.getElementById(eid)
9607 // display none elements have no offsetParent so we will
9608 // also try to look it up by it's id. However, check
9609 // offsetParent first so we don't do unneeded lookups.
9610 // This enables collection of elements that are not orphans
9611 // directly, but somewhere up the line they have an orphan
9613 // -------------------------------------------------------
9614 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9615 delete El.cache[eid];
9616 if(d && Roo.enableListenerCollection){
9622 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9626 El.Flyweight = function(dom){
9629 El.Flyweight.prototype = El.prototype;
9631 El._flyweights = {};
9633 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9634 * the dom node can be overwritten by other code.
9635 * @param {String/HTMLElement} el The dom node or id
9636 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9637 * prevent conflicts (e.g. internally Roo uses "_internal")
9639 * @return {Element} The shared Element object
9641 El.fly = function(el, named){
9642 named = named || '_global';
9643 el = Roo.getDom(el);
9647 if(!El._flyweights[named]){
9648 El._flyweights[named] = new El.Flyweight();
9650 El._flyweights[named].dom = el;
9651 return El._flyweights[named];
9655 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9656 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9657 * Shorthand of {@link Roo.Element#get}
9658 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9659 * @return {Element} The Element object
9665 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9666 * the dom node can be overwritten by other code.
9667 * Shorthand of {@link Roo.Element#fly}
9668 * @param {String/HTMLElement} el The dom node or id
9669 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9670 * prevent conflicts (e.g. internally Roo uses "_internal")
9672 * @return {Element} The shared Element object
9678 // speedy lookup for elements never to box adjust
9679 var noBoxAdjust = Roo.isStrict ? {
9682 input:1, select:1, textarea:1
9684 if(Roo.isIE || Roo.isGecko){
9685 noBoxAdjust['button'] = 1;
9689 Roo.EventManager.on(window, 'unload', function(){
9691 delete El._flyweights;
9699 Roo.Element.selectorFunction = Roo.DomQuery.select;
9702 Roo.Element.select = function(selector, unique, root){
9704 if(typeof selector == "string"){
9705 els = Roo.Element.selectorFunction(selector, root);
9706 }else if(selector.length !== undefined){
9709 throw "Invalid selector";
9711 if(unique === true){
9712 return new Roo.CompositeElement(els);
9714 return new Roo.CompositeElementLite(els);
9718 * Selects elements based on the passed CSS selector to enable working on them as 1.
9719 * @param {String/Array} selector The CSS selector or an array of elements
9720 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9721 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9722 * @return {CompositeElementLite/CompositeElement}
9726 Roo.select = Roo.Element.select;
9743 * Ext JS Library 1.1.1
9744 * Copyright(c) 2006-2007, Ext JS, LLC.
9746 * Originally Released Under LGPL - original licence link has changed is not relivant.
9749 * <script type="text/javascript">
9754 //Notifies Element that fx methods are available
9755 Roo.enableFx = true;
9759 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9760 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9761 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9762 * Element effects to work.</p><br/>
9764 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9765 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9766 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9767 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9768 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9769 * expected results and should be done with care.</p><br/>
9771 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9772 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9775 ----- -----------------------------
9776 tl The top left corner
9777 t The center of the top edge
9778 tr The top right corner
9779 l The center of the left edge
9780 r The center of the right edge
9781 bl The bottom left corner
9782 b The center of the bottom edge
9783 br The bottom right corner
9785 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9786 * below are common options that can be passed to any Fx method.</b>
9787 * @cfg {Function} callback A function called when the effect is finished
9788 * @cfg {Object} scope The scope of the effect function
9789 * @cfg {String} easing A valid Easing value for the effect
9790 * @cfg {String} afterCls A css class to apply after the effect
9791 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9792 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9793 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9794 * effects that end with the element being visually hidden, ignored otherwise)
9795 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9796 * a function which returns such a specification that will be applied to the Element after the effect finishes
9797 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9798 * @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
9799 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9803 * Slides the element into view. An anchor point can be optionally passed to set the point of
9804 * origin for the slide effect. This function automatically handles wrapping the element with
9805 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9808 // default: slide the element in from the top
9811 // custom: slide the element in from the right with a 2-second duration
9812 el.slideIn('r', { duration: 2 });
9814 // common config options shown with default values
9820 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9821 * @param {Object} options (optional) Object literal with any of the Fx config options
9822 * @return {Roo.Element} The Element
9824 slideIn : function(anchor, o){
9825 var el = this.getFxEl();
9828 el.queueFx(o, function(){
9830 anchor = anchor || "t";
9832 // fix display to visibility
9835 // restore values after effect
9836 var r = this.getFxRestore();
9837 var b = this.getBox();
9838 // fixed size for slide
9842 var wrap = this.fxWrap(r.pos, o, "hidden");
9844 var st = this.dom.style;
9845 st.visibility = "visible";
9846 st.position = "absolute";
9848 // clear out temp styles after slide and unwrap
9849 var after = function(){
9850 el.fxUnwrap(wrap, r.pos, o);
9852 st.height = r.height;
9855 // time to calc the positions
9856 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9858 switch(anchor.toLowerCase()){
9860 wrap.setSize(b.width, 0);
9861 st.left = st.bottom = "0";
9865 wrap.setSize(0, b.height);
9866 st.right = st.top = "0";
9870 wrap.setSize(0, b.height);
9872 st.left = st.top = "0";
9873 a = {width: bw, points: pt};
9876 wrap.setSize(b.width, 0);
9877 wrap.setY(b.bottom);
9878 st.left = st.top = "0";
9879 a = {height: bh, points: pt};
9883 st.right = st.bottom = "0";
9884 a = {width: bw, height: bh};
9888 wrap.setY(b.y+b.height);
9889 st.right = st.top = "0";
9890 a = {width: bw, height: bh, points: pt};
9894 wrap.setXY([b.right, b.bottom]);
9895 st.left = st.top = "0";
9896 a = {width: bw, height: bh, points: pt};
9900 wrap.setX(b.x+b.width);
9901 st.left = st.bottom = "0";
9902 a = {width: bw, height: bh, points: pt};
9905 this.dom.style.visibility = "visible";
9908 arguments.callee.anim = wrap.fxanim(a,
9918 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9919 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9920 * 'hidden') but block elements will still take up space in the document. The element must be removed
9921 * from the DOM using the 'remove' config option if desired. This function automatically handles
9922 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9925 // default: slide the element out to the top
9928 // custom: slide the element out to the right with a 2-second duration
9929 el.slideOut('r', { duration: 2 });
9931 // common config options shown with default values
9939 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9940 * @param {Object} options (optional) Object literal with any of the Fx config options
9941 * @return {Roo.Element} The Element
9943 slideOut : function(anchor, o){
9944 var el = this.getFxEl();
9947 el.queueFx(o, function(){
9949 anchor = anchor || "t";
9951 // restore values after effect
9952 var r = this.getFxRestore();
9954 var b = this.getBox();
9955 // fixed size for slide
9959 var wrap = this.fxWrap(r.pos, o, "visible");
9961 var st = this.dom.style;
9962 st.visibility = "visible";
9963 st.position = "absolute";
9967 var after = function(){
9969 el.setDisplayed(false);
9974 el.fxUnwrap(wrap, r.pos, o);
9977 st.height = r.height;
9982 var a, zero = {to: 0};
9983 switch(anchor.toLowerCase()){
9985 st.left = st.bottom = "0";
9989 st.right = st.top = "0";
9993 st.left = st.top = "0";
9994 a = {width: zero, points: {to:[b.right, b.y]}};
9997 st.left = st.top = "0";
9998 a = {height: zero, points: {to:[b.x, b.bottom]}};
10001 st.right = st.bottom = "0";
10002 a = {width: zero, height: zero};
10005 st.right = st.top = "0";
10006 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
10009 st.left = st.top = "0";
10010 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
10013 st.left = st.bottom = "0";
10014 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
10018 arguments.callee.anim = wrap.fxanim(a,
10028 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10029 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10030 * The element must be removed from the DOM using the 'remove' config option if desired.
10036 // common config options shown with default values
10044 * @param {Object} options (optional) Object literal with any of the Fx config options
10045 * @return {Roo.Element} The Element
10047 puff : function(o){
10048 var el = this.getFxEl();
10051 el.queueFx(o, function(){
10052 this.clearOpacity();
10055 // restore values after effect
10056 var r = this.getFxRestore();
10057 var st = this.dom.style;
10059 var after = function(){
10061 el.setDisplayed(false);
10068 el.setPositioning(r.pos);
10069 st.width = r.width;
10070 st.height = r.height;
10075 var width = this.getWidth();
10076 var height = this.getHeight();
10078 arguments.callee.anim = this.fxanim({
10079 width : {to: this.adjustWidth(width * 2)},
10080 height : {to: this.adjustHeight(height * 2)},
10081 points : {by: [-(width * .5), -(height * .5)]},
10083 fontSize: {to:200, unit: "%"}
10094 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10095 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10096 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10102 // all config options shown with default values
10110 * @param {Object} options (optional) Object literal with any of the Fx config options
10111 * @return {Roo.Element} The Element
10113 switchOff : function(o){
10114 var el = this.getFxEl();
10117 el.queueFx(o, function(){
10118 this.clearOpacity();
10121 // restore values after effect
10122 var r = this.getFxRestore();
10123 var st = this.dom.style;
10125 var after = function(){
10127 el.setDisplayed(false);
10133 el.setPositioning(r.pos);
10134 st.width = r.width;
10135 st.height = r.height;
10140 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10141 this.clearOpacity();
10145 points:{by:[0, this.getHeight() * .5]}
10146 }, o, 'motion', 0.3, 'easeIn', after);
10147 }).defer(100, this);
10154 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10155 * changed using the "attr" config option) and then fading back to the original color. If no original
10156 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10159 // default: highlight background to yellow
10162 // custom: highlight foreground text to blue for 2 seconds
10163 el.highlight("0000ff", { attr: 'color', duration: 2 });
10165 // common config options shown with default values
10166 el.highlight("ffff9c", {
10167 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10168 endColor: (current color) or "ffffff",
10173 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10174 * @param {Object} options (optional) Object literal with any of the Fx config options
10175 * @return {Roo.Element} The Element
10177 highlight : function(color, o){
10178 var el = this.getFxEl();
10181 el.queueFx(o, function(){
10182 color = color || "ffff9c";
10183 attr = o.attr || "backgroundColor";
10185 this.clearOpacity();
10188 var origColor = this.getColor(attr);
10189 var restoreColor = this.dom.style[attr];
10190 endColor = (o.endColor || origColor) || "ffffff";
10192 var after = function(){
10193 el.dom.style[attr] = restoreColor;
10198 a[attr] = {from: color, to: endColor};
10199 arguments.callee.anim = this.fxanim(a,
10209 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10212 // default: a single light blue ripple
10215 // custom: 3 red ripples lasting 3 seconds total
10216 el.frame("ff0000", 3, { duration: 3 });
10218 // common config options shown with default values
10219 el.frame("C3DAF9", 1, {
10220 duration: 1 //duration of entire animation (not each individual ripple)
10221 // Note: Easing is not configurable and will be ignored if included
10224 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10225 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10226 * @param {Object} options (optional) Object literal with any of the Fx config options
10227 * @return {Roo.Element} The Element
10229 frame : function(color, count, o){
10230 var el = this.getFxEl();
10233 el.queueFx(o, function(){
10234 color = color || "#C3DAF9";
10235 if(color.length == 6){
10236 color = "#" + color;
10238 count = count || 1;
10239 duration = o.duration || 1;
10242 var b = this.getBox();
10243 var animFn = function(){
10244 var proxy = this.createProxy({
10247 visbility:"hidden",
10248 position:"absolute",
10249 "z-index":"35000", // yee haw
10250 border:"0px solid " + color
10253 var scale = Roo.isBorderBox ? 2 : 1;
10255 top:{from:b.y, to:b.y - 20},
10256 left:{from:b.x, to:b.x - 20},
10257 borderWidth:{from:0, to:10},
10258 opacity:{from:1, to:0},
10259 height:{from:b.height, to:(b.height + (20*scale))},
10260 width:{from:b.width, to:(b.width + (20*scale))}
10261 }, duration, function(){
10265 animFn.defer((duration/2)*1000, this);
10276 * Creates a pause before any subsequent queued effects begin. If there are
10277 * no effects queued after the pause it will have no effect.
10282 * @param {Number} seconds The length of time to pause (in seconds)
10283 * @return {Roo.Element} The Element
10285 pause : function(seconds){
10286 var el = this.getFxEl();
10289 el.queueFx(o, function(){
10290 setTimeout(function(){
10292 }, seconds * 1000);
10298 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10299 * using the "endOpacity" config option.
10302 // default: fade in from opacity 0 to 100%
10305 // custom: fade in from opacity 0 to 75% over 2 seconds
10306 el.fadeIn({ endOpacity: .75, duration: 2});
10308 // common config options shown with default values
10310 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10315 * @param {Object} options (optional) Object literal with any of the Fx config options
10316 * @return {Roo.Element} The Element
10318 fadeIn : function(o){
10319 var el = this.getFxEl();
10321 el.queueFx(o, function(){
10322 this.setOpacity(0);
10324 this.dom.style.visibility = 'visible';
10325 var to = o.endOpacity || 1;
10326 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10327 o, null, .5, "easeOut", function(){
10329 this.clearOpacity();
10338 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10339 * using the "endOpacity" config option.
10342 // default: fade out from the element's current opacity to 0
10345 // custom: fade out from the element's current opacity to 25% over 2 seconds
10346 el.fadeOut({ endOpacity: .25, duration: 2});
10348 // common config options shown with default values
10350 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10357 * @param {Object} options (optional) Object literal with any of the Fx config options
10358 * @return {Roo.Element} The Element
10360 fadeOut : function(o){
10361 var el = this.getFxEl();
10363 el.queueFx(o, function(){
10364 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10365 o, null, .5, "easeOut", function(){
10366 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10367 this.dom.style.display = "none";
10369 this.dom.style.visibility = "hidden";
10371 this.clearOpacity();
10379 * Animates the transition of an element's dimensions from a starting height/width
10380 * to an ending height/width.
10383 // change height and width to 100x100 pixels
10384 el.scale(100, 100);
10386 // common config options shown with default values. The height and width will default to
10387 // the element's existing values if passed as null.
10390 [element's height], {
10395 * @param {Number} width The new width (pass undefined to keep the original width)
10396 * @param {Number} height The new height (pass undefined to keep the original height)
10397 * @param {Object} options (optional) Object literal with any of the Fx config options
10398 * @return {Roo.Element} The Element
10400 scale : function(w, h, o){
10401 this.shift(Roo.apply({}, o, {
10409 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10410 * Any of these properties not specified in the config object will not be changed. This effect
10411 * requires that at least one new dimension, position or opacity setting must be passed in on
10412 * the config object in order for the function to have any effect.
10415 // slide the element horizontally to x position 200 while changing the height and opacity
10416 el.shift({ x: 200, height: 50, opacity: .8 });
10418 // common config options shown with default values.
10420 width: [element's width],
10421 height: [element's height],
10422 x: [element's x position],
10423 y: [element's y position],
10424 opacity: [element's opacity],
10429 * @param {Object} options Object literal with any of the Fx config options
10430 * @return {Roo.Element} The Element
10432 shift : function(o){
10433 var el = this.getFxEl();
10435 el.queueFx(o, function(){
10436 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10437 if(w !== undefined){
10438 a.width = {to: this.adjustWidth(w)};
10440 if(h !== undefined){
10441 a.height = {to: this.adjustHeight(h)};
10443 if(x !== undefined || y !== undefined){
10445 x !== undefined ? x : this.getX(),
10446 y !== undefined ? y : this.getY()
10449 if(op !== undefined){
10450 a.opacity = {to: op};
10452 if(o.xy !== undefined){
10453 a.points = {to: o.xy};
10455 arguments.callee.anim = this.fxanim(a,
10456 o, 'motion', .35, "easeOut", function(){
10464 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10465 * ending point of the effect.
10468 // default: slide the element downward while fading out
10471 // custom: slide the element out to the right with a 2-second duration
10472 el.ghost('r', { duration: 2 });
10474 // common config options shown with default values
10482 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10483 * @param {Object} options (optional) Object literal with any of the Fx config options
10484 * @return {Roo.Element} The Element
10486 ghost : function(anchor, o){
10487 var el = this.getFxEl();
10490 el.queueFx(o, function(){
10491 anchor = anchor || "b";
10493 // restore values after effect
10494 var r = this.getFxRestore();
10495 var w = this.getWidth(),
10496 h = this.getHeight();
10498 var st = this.dom.style;
10500 var after = function(){
10502 el.setDisplayed(false);
10508 el.setPositioning(r.pos);
10509 st.width = r.width;
10510 st.height = r.height;
10515 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10516 switch(anchor.toLowerCase()){
10543 arguments.callee.anim = this.fxanim(a,
10553 * Ensures that all effects queued after syncFx is called on the element are
10554 * run concurrently. This is the opposite of {@link #sequenceFx}.
10555 * @return {Roo.Element} The Element
10557 syncFx : function(){
10558 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10567 * Ensures that all effects queued after sequenceFx is called on the element are
10568 * run in sequence. This is the opposite of {@link #syncFx}.
10569 * @return {Roo.Element} The Element
10571 sequenceFx : function(){
10572 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10574 concurrent : false,
10581 nextFx : function(){
10582 var ef = this.fxQueue[0];
10589 * Returns true if the element has any effects actively running or queued, else returns false.
10590 * @return {Boolean} True if element has active effects, else false
10592 hasActiveFx : function(){
10593 return this.fxQueue && this.fxQueue[0];
10597 * Stops any running effects and clears the element's internal effects queue if it contains
10598 * any additional effects that haven't started yet.
10599 * @return {Roo.Element} The Element
10601 stopFx : function(){
10602 if(this.hasActiveFx()){
10603 var cur = this.fxQueue[0];
10604 if(cur && cur.anim && cur.anim.isAnimated()){
10605 this.fxQueue = [cur]; // clear out others
10606 cur.anim.stop(true);
10613 beforeFx : function(o){
10614 if(this.hasActiveFx() && !o.concurrent){
10625 * Returns true if the element is currently blocking so that no other effect can be queued
10626 * until this effect is finished, else returns false if blocking is not set. This is commonly
10627 * used to ensure that an effect initiated by a user action runs to completion prior to the
10628 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10629 * @return {Boolean} True if blocking, else false
10631 hasFxBlock : function(){
10632 var q = this.fxQueue;
10633 return q && q[0] && q[0].block;
10637 queueFx : function(o, fn){
10641 if(!this.hasFxBlock()){
10642 Roo.applyIf(o, this.fxDefaults);
10644 var run = this.beforeFx(o);
10645 fn.block = o.block;
10646 this.fxQueue.push(fn);
10658 fxWrap : function(pos, o, vis){
10660 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10663 wrapXY = this.getXY();
10665 var div = document.createElement("div");
10666 div.style.visibility = vis;
10667 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10668 wrap.setPositioning(pos);
10669 if(wrap.getStyle("position") == "static"){
10670 wrap.position("relative");
10672 this.clearPositioning('auto');
10674 wrap.dom.appendChild(this.dom);
10676 wrap.setXY(wrapXY);
10683 fxUnwrap : function(wrap, pos, o){
10684 this.clearPositioning();
10685 this.setPositioning(pos);
10687 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10693 getFxRestore : function(){
10694 var st = this.dom.style;
10695 return {pos: this.getPositioning(), width: st.width, height : st.height};
10699 afterFx : function(o){
10701 this.applyStyles(o.afterStyle);
10704 this.addClass(o.afterCls);
10706 if(o.remove === true){
10709 Roo.callback(o.callback, o.scope, [this]);
10711 this.fxQueue.shift();
10717 getFxEl : function(){ // support for composite element fx
10718 return Roo.get(this.dom);
10722 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10723 animType = animType || 'run';
10725 var anim = Roo.lib.Anim[animType](
10727 (opt.duration || defaultDur) || .35,
10728 (opt.easing || defaultEase) || 'easeOut',
10730 Roo.callback(cb, this);
10739 // backwords compat
10740 Roo.Fx.resize = Roo.Fx.scale;
10742 //When included, Roo.Fx is automatically applied to Element so that all basic
10743 //effects are available directly via the Element API
10744 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10746 * Ext JS Library 1.1.1
10747 * Copyright(c) 2006-2007, Ext JS, LLC.
10749 * Originally Released Under LGPL - original licence link has changed is not relivant.
10752 * <script type="text/javascript">
10757 * @class Roo.CompositeElement
10758 * Standard composite class. Creates a Roo.Element for every element in the collection.
10760 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10761 * actions will be performed on all the elements in this collection.</b>
10763 * All methods return <i>this</i> and can be chained.
10765 var els = Roo.select("#some-el div.some-class", true);
10766 // or select directly from an existing element
10767 var el = Roo.get('some-el');
10768 el.select('div.some-class', true);
10770 els.setWidth(100); // all elements become 100 width
10771 els.hide(true); // all elements fade out and hide
10773 els.setWidth(100).hide(true);
10776 Roo.CompositeElement = function(els){
10777 this.elements = [];
10778 this.addElements(els);
10780 Roo.CompositeElement.prototype = {
10782 addElements : function(els){
10783 if(!els) return this;
10784 if(typeof els == "string"){
10785 els = Roo.Element.selectorFunction(els);
10787 var yels = this.elements;
10788 var index = yels.length-1;
10789 for(var i = 0, len = els.length; i < len; i++) {
10790 yels[++index] = Roo.get(els[i]);
10796 * Clears this composite and adds the elements returned by the passed selector.
10797 * @param {String/Array} els A string CSS selector, an array of elements or an element
10798 * @return {CompositeElement} this
10800 fill : function(els){
10801 this.elements = [];
10807 * Filters this composite to only elements that match the passed selector.
10808 * @param {String} selector A string CSS selector
10809 * @return {CompositeElement} this
10811 filter : function(selector){
10813 this.each(function(el){
10814 if(el.is(selector)){
10815 els[els.length] = el.dom;
10822 invoke : function(fn, args){
10823 var els = this.elements;
10824 for(var i = 0, len = els.length; i < len; i++) {
10825 Roo.Element.prototype[fn].apply(els[i], args);
10830 * Adds elements to this composite.
10831 * @param {String/Array} els A string CSS selector, an array of elements or an element
10832 * @return {CompositeElement} this
10834 add : function(els){
10835 if(typeof els == "string"){
10836 this.addElements(Roo.Element.selectorFunction(els));
10837 }else if(els.length !== undefined){
10838 this.addElements(els);
10840 this.addElements([els]);
10845 * Calls the passed function passing (el, this, index) for each element in this composite.
10846 * @param {Function} fn The function to call
10847 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10848 * @return {CompositeElement} this
10850 each : function(fn, scope){
10851 var els = this.elements;
10852 for(var i = 0, len = els.length; i < len; i++){
10853 if(fn.call(scope || els[i], els[i], this, i) === false) {
10861 * Returns the Element object at the specified index
10862 * @param {Number} index
10863 * @return {Roo.Element}
10865 item : function(index){
10866 return this.elements[index] || null;
10870 * Returns the first Element
10871 * @return {Roo.Element}
10873 first : function(){
10874 return this.item(0);
10878 * Returns the last Element
10879 * @return {Roo.Element}
10882 return this.item(this.elements.length-1);
10886 * Returns the number of elements in this composite
10889 getCount : function(){
10890 return this.elements.length;
10894 * Returns true if this composite contains the passed element
10897 contains : function(el){
10898 return this.indexOf(el) !== -1;
10902 * Returns true if this composite contains the passed element
10905 indexOf : function(el){
10906 return this.elements.indexOf(Roo.get(el));
10911 * Removes the specified element(s).
10912 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10913 * or an array of any of those.
10914 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10915 * @return {CompositeElement} this
10917 removeElement : function(el, removeDom){
10918 if(el instanceof Array){
10919 for(var i = 0, len = el.length; i < len; i++){
10920 this.removeElement(el[i]);
10924 var index = typeof el == 'number' ? el : this.indexOf(el);
10927 var d = this.elements[index];
10931 d.parentNode.removeChild(d);
10934 this.elements.splice(index, 1);
10940 * Replaces the specified element with the passed element.
10941 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10943 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10944 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10945 * @return {CompositeElement} this
10947 replaceElement : function(el, replacement, domReplace){
10948 var index = typeof el == 'number' ? el : this.indexOf(el);
10951 this.elements[index].replaceWith(replacement);
10953 this.elements.splice(index, 1, Roo.get(replacement))
10960 * Removes all elements.
10962 clear : function(){
10963 this.elements = [];
10967 Roo.CompositeElement.createCall = function(proto, fnName){
10968 if(!proto[fnName]){
10969 proto[fnName] = function(){
10970 return this.invoke(fnName, arguments);
10974 for(var fnName in Roo.Element.prototype){
10975 if(typeof Roo.Element.prototype[fnName] == "function"){
10976 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10982 * Ext JS Library 1.1.1
10983 * Copyright(c) 2006-2007, Ext JS, LLC.
10985 * Originally Released Under LGPL - original licence link has changed is not relivant.
10988 * <script type="text/javascript">
10992 * @class Roo.CompositeElementLite
10993 * @extends Roo.CompositeElement
10994 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10996 var els = Roo.select("#some-el div.some-class");
10997 // or select directly from an existing element
10998 var el = Roo.get('some-el');
10999 el.select('div.some-class');
11001 els.setWidth(100); // all elements become 100 width
11002 els.hide(true); // all elements fade out and hide
11004 els.setWidth(100).hide(true);
11005 </code></pre><br><br>
11006 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
11007 * actions will be performed on all the elements in this collection.</b>
11009 Roo.CompositeElementLite = function(els){
11010 Roo.CompositeElementLite.superclass.constructor.call(this, els);
11011 this.el = new Roo.Element.Flyweight();
11013 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
11014 addElements : function(els){
11016 if(els instanceof Array){
11017 this.elements = this.elements.concat(els);
11019 var yels = this.elements;
11020 var index = yels.length-1;
11021 for(var i = 0, len = els.length; i < len; i++) {
11022 yels[++index] = els[i];
11028 invoke : function(fn, args){
11029 var els = this.elements;
11031 for(var i = 0, len = els.length; i < len; i++) {
11033 Roo.Element.prototype[fn].apply(el, args);
11038 * Returns a flyweight Element of the dom element object at the specified index
11039 * @param {Number} index
11040 * @return {Roo.Element}
11042 item : function(index){
11043 if(!this.elements[index]){
11046 this.el.dom = this.elements[index];
11050 // fixes scope with flyweight
11051 addListener : function(eventName, handler, scope, opt){
11052 var els = this.elements;
11053 for(var i = 0, len = els.length; i < len; i++) {
11054 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11060 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11061 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11062 * a reference to the dom node, use el.dom.</b>
11063 * @param {Function} fn The function to call
11064 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11065 * @return {CompositeElement} this
11067 each : function(fn, scope){
11068 var els = this.elements;
11070 for(var i = 0, len = els.length; i < len; i++){
11072 if(fn.call(scope || el, el, this, i) === false){
11079 indexOf : function(el){
11080 return this.elements.indexOf(Roo.getDom(el));
11083 replaceElement : function(el, replacement, domReplace){
11084 var index = typeof el == 'number' ? el : this.indexOf(el);
11086 replacement = Roo.getDom(replacement);
11088 var d = this.elements[index];
11089 d.parentNode.insertBefore(replacement, d);
11090 d.parentNode.removeChild(d);
11092 this.elements.splice(index, 1, replacement);
11097 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11101 * Ext JS Library 1.1.1
11102 * Copyright(c) 2006-2007, Ext JS, LLC.
11104 * Originally Released Under LGPL - original licence link has changed is not relivant.
11107 * <script type="text/javascript">
11113 * @class Roo.data.Connection
11114 * @extends Roo.util.Observable
11115 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11116 * either to a configured URL, or to a URL specified at request time.<br><br>
11118 * Requests made by this class are asynchronous, and will return immediately. No data from
11119 * the server will be available to the statement immediately following the {@link #request} call.
11120 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11122 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11123 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11124 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11125 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11126 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11127 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11128 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11129 * standard DOM methods.
11131 * @param {Object} config a configuration object.
11133 Roo.data.Connection = function(config){
11134 Roo.apply(this, config);
11137 * @event beforerequest
11138 * Fires before a network request is made to retrieve a data object.
11139 * @param {Connection} conn This Connection object.
11140 * @param {Object} options The options config object passed to the {@link #request} method.
11142 "beforerequest" : true,
11144 * @event requestcomplete
11145 * Fires if the request was successfully completed.
11146 * @param {Connection} conn This Connection object.
11147 * @param {Object} response The XHR object containing the response data.
11148 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11149 * @param {Object} options The options config object passed to the {@link #request} method.
11151 "requestcomplete" : true,
11153 * @event requestexception
11154 * Fires if an error HTTP status was returned from the server.
11155 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11156 * @param {Connection} conn This Connection object.
11157 * @param {Object} response The XHR object containing the response data.
11158 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11159 * @param {Object} options The options config object passed to the {@link #request} method.
11161 "requestexception" : true
11163 Roo.data.Connection.superclass.constructor.call(this);
11166 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11168 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11171 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11172 * extra parameters to each request made by this object. (defaults to undefined)
11175 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11176 * to each request made by this object. (defaults to undefined)
11179 * @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)
11182 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11186 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11192 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11195 disableCaching: true,
11198 * Sends an HTTP request to a remote server.
11199 * @param {Object} options An object which may contain the following properties:<ul>
11200 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11201 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11202 * request, a url encoded string or a function to call to get either.</li>
11203 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11204 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11205 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11206 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11207 * <li>options {Object} The parameter to the request call.</li>
11208 * <li>success {Boolean} True if the request succeeded.</li>
11209 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11211 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11212 * The callback is passed the following parameters:<ul>
11213 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11214 * <li>options {Object} The parameter to the request call.</li>
11216 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11217 * The callback is passed the following parameters:<ul>
11218 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11219 * <li>options {Object} The parameter to the request call.</li>
11221 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11222 * for the callback function. Defaults to the browser window.</li>
11223 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11224 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11225 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11226 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11227 * params for the post data. Any params will be appended to the URL.</li>
11228 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11230 * @return {Number} transactionId
11232 request : function(o){
11233 if(this.fireEvent("beforerequest", this, o) !== false){
11236 if(typeof p == "function"){
11237 p = p.call(o.scope||window, o);
11239 if(typeof p == "object"){
11240 p = Roo.urlEncode(o.params);
11242 if(this.extraParams){
11243 var extras = Roo.urlEncode(this.extraParams);
11244 p = p ? (p + '&' + extras) : extras;
11247 var url = o.url || this.url;
11248 if(typeof url == 'function'){
11249 url = url.call(o.scope||window, o);
11253 var form = Roo.getDom(o.form);
11254 url = url || form.action;
11256 var enctype = form.getAttribute("enctype");
11257 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11258 return this.doFormUpload(o, p, url);
11260 var f = Roo.lib.Ajax.serializeForm(form);
11261 p = p ? (p + '&' + f) : f;
11264 var hs = o.headers;
11265 if(this.defaultHeaders){
11266 hs = Roo.apply(hs || {}, this.defaultHeaders);
11273 success: this.handleResponse,
11274 failure: this.handleFailure,
11276 argument: {options: o},
11277 timeout : this.timeout
11280 var method = o.method||this.method||(p ? "POST" : "GET");
11282 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11283 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11286 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11290 }else if(this.autoAbort !== false){
11294 if((method == 'GET' && p) || o.xmlData){
11295 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11298 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11299 return this.transId;
11301 Roo.callback(o.callback, o.scope, [o, null, null]);
11307 * Determine whether this object has a request outstanding.
11308 * @param {Number} transactionId (Optional) defaults to the last transaction
11309 * @return {Boolean} True if there is an outstanding request.
11311 isLoading : function(transId){
11313 return Roo.lib.Ajax.isCallInProgress(transId);
11315 return this.transId ? true : false;
11320 * Aborts any outstanding request.
11321 * @param {Number} transactionId (Optional) defaults to the last transaction
11323 abort : function(transId){
11324 if(transId || this.isLoading()){
11325 Roo.lib.Ajax.abort(transId || this.transId);
11330 handleResponse : function(response){
11331 this.transId = false;
11332 var options = response.argument.options;
11333 response.argument = options ? options.argument : null;
11334 this.fireEvent("requestcomplete", this, response, options);
11335 Roo.callback(options.success, options.scope, [response, options]);
11336 Roo.callback(options.callback, options.scope, [options, true, response]);
11340 handleFailure : function(response, e){
11341 this.transId = false;
11342 var options = response.argument.options;
11343 response.argument = options ? options.argument : null;
11344 this.fireEvent("requestexception", this, response, options, e);
11345 Roo.callback(options.failure, options.scope, [response, options]);
11346 Roo.callback(options.callback, options.scope, [options, false, response]);
11350 doFormUpload : function(o, ps, url){
11352 var frame = document.createElement('iframe');
11355 frame.className = 'x-hidden';
11357 frame.src = Roo.SSL_SECURE_URL;
11359 document.body.appendChild(frame);
11362 document.frames[id].name = id;
11365 var form = Roo.getDom(o.form);
11367 form.method = 'POST';
11368 form.enctype = form.encoding = 'multipart/form-data';
11374 if(ps){ // add dynamic params
11376 ps = Roo.urlDecode(ps, false);
11378 if(ps.hasOwnProperty(k)){
11379 hd = document.createElement('input');
11380 hd.type = 'hidden';
11383 form.appendChild(hd);
11390 var r = { // bogus response object
11395 r.argument = o ? o.argument : null;
11400 doc = frame.contentWindow.document;
11402 doc = (frame.contentDocument || window.frames[id].document);
11404 if(doc && doc.body){
11405 r.responseText = doc.body.innerHTML;
11407 if(doc && doc.XMLDocument){
11408 r.responseXML = doc.XMLDocument;
11410 r.responseXML = doc;
11417 Roo.EventManager.removeListener(frame, 'load', cb, this);
11419 this.fireEvent("requestcomplete", this, r, o);
11420 Roo.callback(o.success, o.scope, [r, o]);
11421 Roo.callback(o.callback, o.scope, [o, true, r]);
11423 setTimeout(function(){document.body.removeChild(frame);}, 100);
11426 Roo.EventManager.on(frame, 'load', cb, this);
11429 if(hiddens){ // remove dynamic params
11430 for(var i = 0, len = hiddens.length; i < len; i++){
11431 form.removeChild(hiddens[i]);
11439 * @extends Roo.data.Connection
11440 * Global Ajax request class.
11444 Roo.Ajax = new Roo.data.Connection({
11447 * @cfg {String} url @hide
11450 * @cfg {Object} extraParams @hide
11453 * @cfg {Object} defaultHeaders @hide
11456 * @cfg {String} method (Optional) @hide
11459 * @cfg {Number} timeout (Optional) @hide
11462 * @cfg {Boolean} autoAbort (Optional) @hide
11466 * @cfg {Boolean} disableCaching (Optional) @hide
11470 * @property disableCaching
11471 * True to add a unique cache-buster param to GET requests. (defaults to true)
11476 * The default URL to be used for requests to the server. (defaults to undefined)
11480 * @property extraParams
11481 * An object containing properties which are used as
11482 * extra parameters to each request made by this object. (defaults to undefined)
11486 * @property defaultHeaders
11487 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11492 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11496 * @property timeout
11497 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11502 * @property autoAbort
11503 * Whether a new request should abort any pending requests. (defaults to false)
11509 * Serialize the passed form into a url encoded string
11510 * @param {String/HTMLElement} form
11513 serializeForm : function(form){
11514 return Roo.lib.Ajax.serializeForm(form);
11518 * Ext JS Library 1.1.1
11519 * Copyright(c) 2006-2007, Ext JS, LLC.
11521 * Originally Released Under LGPL - original licence link has changed is not relivant.
11524 * <script type="text/javascript">
11529 * @extends Roo.data.Connection
11530 * Global Ajax request class.
11532 * @instanceOf Roo.data.Connection
11534 Roo.Ajax = new Roo.data.Connection({
11543 * @cfg {String} url @hide
11546 * @cfg {Object} extraParams @hide
11549 * @cfg {Object} defaultHeaders @hide
11552 * @cfg {String} method (Optional) @hide
11555 * @cfg {Number} timeout (Optional) @hide
11558 * @cfg {Boolean} autoAbort (Optional) @hide
11562 * @cfg {Boolean} disableCaching (Optional) @hide
11566 * @property disableCaching
11567 * True to add a unique cache-buster param to GET requests. (defaults to true)
11572 * The default URL to be used for requests to the server. (defaults to undefined)
11576 * @property extraParams
11577 * An object containing properties which are used as
11578 * extra parameters to each request made by this object. (defaults to undefined)
11582 * @property defaultHeaders
11583 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11588 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11592 * @property timeout
11593 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11598 * @property autoAbort
11599 * Whether a new request should abort any pending requests. (defaults to false)
11605 * Serialize the passed form into a url encoded string
11606 * @param {String/HTMLElement} form
11609 serializeForm : function(form){
11610 return Roo.lib.Ajax.serializeForm(form);
11614 * Ext JS Library 1.1.1
11615 * Copyright(c) 2006-2007, Ext JS, LLC.
11617 * Originally Released Under LGPL - original licence link has changed is not relivant.
11620 * <script type="text/javascript">
11625 * @class Roo.UpdateManager
11626 * @extends Roo.util.Observable
11627 * Provides AJAX-style update for Element object.<br><br>
11630 * // Get it from a Roo.Element object
11631 * var el = Roo.get("foo");
11632 * var mgr = el.getUpdateManager();
11633 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11635 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11637 * // or directly (returns the same UpdateManager instance)
11638 * var mgr = new Roo.UpdateManager("myElementId");
11639 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11640 * mgr.on("update", myFcnNeedsToKnow);
11642 // short handed call directly from the element object
11643 Roo.get("foo").load({
11647 text: "Loading Foo..."
11651 * Create new UpdateManager directly.
11652 * @param {String/HTMLElement/Roo.Element} el The element to update
11653 * @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).
11655 Roo.UpdateManager = function(el, forceNew){
11657 if(!forceNew && el.updateManager){
11658 return el.updateManager;
11661 * The Element object
11662 * @type Roo.Element
11666 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11669 this.defaultUrl = null;
11673 * @event beforeupdate
11674 * Fired before an update is made, return false from your handler and the update is cancelled.
11675 * @param {Roo.Element} el
11676 * @param {String/Object/Function} url
11677 * @param {String/Object} params
11679 "beforeupdate": true,
11682 * Fired after successful update is made.
11683 * @param {Roo.Element} el
11684 * @param {Object} oResponseObject The response Object
11689 * Fired on update failure.
11690 * @param {Roo.Element} el
11691 * @param {Object} oResponseObject The response Object
11695 var d = Roo.UpdateManager.defaults;
11697 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11700 this.sslBlankUrl = d.sslBlankUrl;
11702 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11705 this.disableCaching = d.disableCaching;
11707 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11710 this.indicatorText = d.indicatorText;
11712 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11715 this.showLoadIndicator = d.showLoadIndicator;
11717 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11720 this.timeout = d.timeout;
11723 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11726 this.loadScripts = d.loadScripts;
11729 * Transaction object of current executing transaction
11731 this.transaction = null;
11736 this.autoRefreshProcId = null;
11738 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11741 this.refreshDelegate = this.refresh.createDelegate(this);
11743 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11746 this.updateDelegate = this.update.createDelegate(this);
11748 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11751 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11755 this.successDelegate = this.processSuccess.createDelegate(this);
11759 this.failureDelegate = this.processFailure.createDelegate(this);
11761 if(!this.renderer){
11763 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11765 this.renderer = new Roo.UpdateManager.BasicRenderer();
11768 Roo.UpdateManager.superclass.constructor.call(this);
11771 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11773 * Get the Element this UpdateManager is bound to
11774 * @return {Roo.Element} The element
11776 getEl : function(){
11780 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11781 * @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:
11784 url: "your-url.php",<br/>
11785 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11786 callback: yourFunction,<br/>
11787 scope: yourObject, //(optional scope) <br/>
11788 discardUrl: false, <br/>
11789 nocache: false,<br/>
11790 text: "Loading...",<br/>
11792 scripts: false<br/>
11795 * The only required property is url. The optional properties nocache, text and scripts
11796 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11797 * @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}
11798 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11799 * @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.
11801 update : function(url, params, callback, discardUrl){
11802 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11803 var method = this.method, cfg;
11804 if(typeof url == "object"){ // must be config object
11807 params = params || cfg.params;
11808 callback = callback || cfg.callback;
11809 discardUrl = discardUrl || cfg.discardUrl;
11810 if(callback && cfg.scope){
11811 callback = callback.createDelegate(cfg.scope);
11813 if(typeof cfg.method != "undefined"){method = cfg.method;};
11814 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11815 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11816 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11817 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11819 this.showLoading();
11821 this.defaultUrl = url;
11823 if(typeof url == "function"){
11824 url = url.call(this);
11827 method = method || (params ? "POST" : "GET");
11828 if(method == "GET"){
11829 url = this.prepareUrl(url);
11832 var o = Roo.apply(cfg ||{}, {
11835 success: this.successDelegate,
11836 failure: this.failureDelegate,
11837 callback: undefined,
11838 timeout: (this.timeout*1000),
11839 argument: {"url": url, "form": null, "callback": callback, "params": params}
11842 this.transaction = Roo.Ajax.request(o);
11847 * 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.
11848 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11849 * @param {String/HTMLElement} form The form Id or form element
11850 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11851 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11852 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11854 formUpdate : function(form, url, reset, callback){
11855 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11856 if(typeof url == "function"){
11857 url = url.call(this);
11859 form = Roo.getDom(form);
11860 this.transaction = Roo.Ajax.request({
11863 success: this.successDelegate,
11864 failure: this.failureDelegate,
11865 timeout: (this.timeout*1000),
11866 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11868 this.showLoading.defer(1, this);
11873 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11874 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11876 refresh : function(callback){
11877 if(this.defaultUrl == null){
11880 this.update(this.defaultUrl, null, callback, true);
11884 * Set this element to auto refresh.
11885 * @param {Number} interval How often to update (in seconds).
11886 * @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)
11887 * @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}
11888 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11889 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11891 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11893 this.update(url || this.defaultUrl, params, callback, true);
11895 if(this.autoRefreshProcId){
11896 clearInterval(this.autoRefreshProcId);
11898 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11902 * Stop auto refresh on this element.
11904 stopAutoRefresh : function(){
11905 if(this.autoRefreshProcId){
11906 clearInterval(this.autoRefreshProcId);
11907 delete this.autoRefreshProcId;
11911 isAutoRefreshing : function(){
11912 return this.autoRefreshProcId ? true : false;
11915 * Called to update the element to "Loading" state. Override to perform custom action.
11917 showLoading : function(){
11918 if(this.showLoadIndicator){
11919 this.el.update(this.indicatorText);
11924 * Adds unique parameter to query string if disableCaching = true
11927 prepareUrl : function(url){
11928 if(this.disableCaching){
11929 var append = "_dc=" + (new Date().getTime());
11930 if(url.indexOf("?") !== -1){
11931 url += "&" + append;
11933 url += "?" + append;
11942 processSuccess : function(response){
11943 this.transaction = null;
11944 if(response.argument.form && response.argument.reset){
11945 try{ // put in try/catch since some older FF releases had problems with this
11946 response.argument.form.reset();
11949 if(this.loadScripts){
11950 this.renderer.render(this.el, response, this,
11951 this.updateComplete.createDelegate(this, [response]));
11953 this.renderer.render(this.el, response, this);
11954 this.updateComplete(response);
11958 updateComplete : function(response){
11959 this.fireEvent("update", this.el, response);
11960 if(typeof response.argument.callback == "function"){
11961 response.argument.callback(this.el, true, response);
11968 processFailure : function(response){
11969 this.transaction = null;
11970 this.fireEvent("failure", this.el, response);
11971 if(typeof response.argument.callback == "function"){
11972 response.argument.callback(this.el, false, response);
11977 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11978 * @param {Object} renderer The object implementing the render() method
11980 setRenderer : function(renderer){
11981 this.renderer = renderer;
11984 getRenderer : function(){
11985 return this.renderer;
11989 * Set the defaultUrl used for updates
11990 * @param {String/Function} defaultUrl The url or a function to call to get the url
11992 setDefaultUrl : function(defaultUrl){
11993 this.defaultUrl = defaultUrl;
11997 * Aborts the executing transaction
11999 abort : function(){
12000 if(this.transaction){
12001 Roo.Ajax.abort(this.transaction);
12006 * Returns true if an update is in progress
12007 * @return {Boolean}
12009 isUpdating : function(){
12010 if(this.transaction){
12011 return Roo.Ajax.isLoading(this.transaction);
12018 * @class Roo.UpdateManager.defaults
12019 * @static (not really - but it helps the doc tool)
12020 * The defaults collection enables customizing the default properties of UpdateManager
12022 Roo.UpdateManager.defaults = {
12024 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12030 * True to process scripts by default (Defaults to false).
12033 loadScripts : false,
12036 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12039 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12041 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12044 disableCaching : false,
12046 * Whether to show indicatorText when loading (Defaults to true).
12049 showLoadIndicator : true,
12051 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12054 indicatorText : '<div class="loading-indicator">Loading...</div>'
12058 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12060 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12061 * @param {String/HTMLElement/Roo.Element} el The element to update
12062 * @param {String} url The url
12063 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12064 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12067 * @member Roo.UpdateManager
12069 Roo.UpdateManager.updateElement = function(el, url, params, options){
12070 var um = Roo.get(el, true).getUpdateManager();
12071 Roo.apply(um, options);
12072 um.update(url, params, options ? options.callback : null);
12074 // alias for backwards compat
12075 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12077 * @class Roo.UpdateManager.BasicRenderer
12078 * Default Content renderer. Updates the elements innerHTML with the responseText.
12080 Roo.UpdateManager.BasicRenderer = function(){};
12082 Roo.UpdateManager.BasicRenderer.prototype = {
12084 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12085 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12086 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12087 * @param {Roo.Element} el The element being rendered
12088 * @param {Object} response The YUI Connect response object
12089 * @param {UpdateManager} updateManager The calling update manager
12090 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12092 render : function(el, response, updateManager, callback){
12093 el.update(response.responseText, updateManager.loadScripts, callback);
12098 * Ext JS Library 1.1.1
12099 * Copyright(c) 2006-2007, Ext JS, LLC.
12101 * Originally Released Under LGPL - original licence link has changed is not relivant.
12104 * <script type="text/javascript">
12108 * @class Roo.util.DelayedTask
12109 * Provides a convenient method of performing setTimeout where a new
12110 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12111 * You can use this class to buffer
12112 * the keypress events for a certain number of milliseconds, and perform only if they stop
12113 * for that amount of time.
12114 * @constructor The parameters to this constructor serve as defaults and are not required.
12115 * @param {Function} fn (optional) The default function to timeout
12116 * @param {Object} scope (optional) The default scope of that timeout
12117 * @param {Array} args (optional) The default Array of arguments
12119 Roo.util.DelayedTask = function(fn, scope, args){
12120 var id = null, d, t;
12122 var call = function(){
12123 var now = new Date().getTime();
12127 fn.apply(scope, args || []);
12131 * Cancels any pending timeout and queues a new one
12132 * @param {Number} delay The milliseconds to delay
12133 * @param {Function} newFn (optional) Overrides function passed to constructor
12134 * @param {Object} newScope (optional) Overrides scope passed to constructor
12135 * @param {Array} newArgs (optional) Overrides args passed to constructor
12137 this.delay = function(delay, newFn, newScope, newArgs){
12138 if(id && delay != d){
12142 t = new Date().getTime();
12144 scope = newScope || scope;
12145 args = newArgs || args;
12147 id = setInterval(call, d);
12152 * Cancel the last queued timeout
12154 this.cancel = function(){
12162 * Ext JS Library 1.1.1
12163 * Copyright(c) 2006-2007, Ext JS, LLC.
12165 * Originally Released Under LGPL - original licence link has changed is not relivant.
12168 * <script type="text/javascript">
12172 Roo.util.TaskRunner = function(interval){
12173 interval = interval || 10;
12174 var tasks = [], removeQueue = [];
12176 var running = false;
12178 var stopThread = function(){
12184 var startThread = function(){
12187 id = setInterval(runTasks, interval);
12191 var removeTask = function(task){
12192 removeQueue.push(task);
12198 var runTasks = function(){
12199 if(removeQueue.length > 0){
12200 for(var i = 0, len = removeQueue.length; i < len; i++){
12201 tasks.remove(removeQueue[i]);
12204 if(tasks.length < 1){
12209 var now = new Date().getTime();
12210 for(var i = 0, len = tasks.length; i < len; ++i){
12212 var itime = now - t.taskRunTime;
12213 if(t.interval <= itime){
12214 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12215 t.taskRunTime = now;
12216 if(rt === false || t.taskRunCount === t.repeat){
12221 if(t.duration && t.duration <= (now - t.taskStartTime)){
12228 * Queues a new task.
12229 * @param {Object} task
12231 this.start = function(task){
12233 task.taskStartTime = new Date().getTime();
12234 task.taskRunTime = 0;
12235 task.taskRunCount = 0;
12240 this.stop = function(task){
12245 this.stopAll = function(){
12247 for(var i = 0, len = tasks.length; i < len; i++){
12248 if(tasks[i].onStop){
12257 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12259 * Ext JS Library 1.1.1
12260 * Copyright(c) 2006-2007, Ext JS, LLC.
12262 * Originally Released Under LGPL - original licence link has changed is not relivant.
12265 * <script type="text/javascript">
12270 * @class Roo.util.MixedCollection
12271 * @extends Roo.util.Observable
12272 * A Collection class that maintains both numeric indexes and keys and exposes events.
12274 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12275 * collection (defaults to false)
12276 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12277 * and return the key value for that item. This is used when available to look up the key on items that
12278 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12279 * equivalent to providing an implementation for the {@link #getKey} method.
12281 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12289 * Fires when the collection is cleared.
12294 * Fires when an item is added to the collection.
12295 * @param {Number} index The index at which the item was added.
12296 * @param {Object} o The item added.
12297 * @param {String} key The key associated with the added item.
12302 * Fires when an item is replaced in the collection.
12303 * @param {String} key he key associated with the new added.
12304 * @param {Object} old The item being replaced.
12305 * @param {Object} new The new item.
12310 * Fires when an item is removed from the collection.
12311 * @param {Object} o The item being removed.
12312 * @param {String} key (optional) The key associated with the removed item.
12317 this.allowFunctions = allowFunctions === true;
12319 this.getKey = keyFn;
12321 Roo.util.MixedCollection.superclass.constructor.call(this);
12324 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12325 allowFunctions : false,
12328 * Adds an item to the collection.
12329 * @param {String} key The key to associate with the item
12330 * @param {Object} o The item to add.
12331 * @return {Object} The item added.
12333 add : function(key, o){
12334 if(arguments.length == 1){
12336 key = this.getKey(o);
12338 if(typeof key == "undefined" || key === null){
12340 this.items.push(o);
12341 this.keys.push(null);
12343 var old = this.map[key];
12345 return this.replace(key, o);
12348 this.items.push(o);
12350 this.keys.push(key);
12352 this.fireEvent("add", this.length-1, o, key);
12357 * MixedCollection has a generic way to fetch keys if you implement getKey.
12360 var mc = new Roo.util.MixedCollection();
12361 mc.add(someEl.dom.id, someEl);
12362 mc.add(otherEl.dom.id, otherEl);
12366 var mc = new Roo.util.MixedCollection();
12367 mc.getKey = function(el){
12373 // or via the constructor
12374 var mc = new Roo.util.MixedCollection(false, function(el){
12380 * @param o {Object} The item for which to find the key.
12381 * @return {Object} The key for the passed item.
12383 getKey : function(o){
12388 * Replaces an item in the collection.
12389 * @param {String} key The key associated with the item to replace, or the item to replace.
12390 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12391 * @return {Object} The new item.
12393 replace : function(key, o){
12394 if(arguments.length == 1){
12396 key = this.getKey(o);
12398 var old = this.item(key);
12399 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12400 return this.add(key, o);
12402 var index = this.indexOfKey(key);
12403 this.items[index] = o;
12405 this.fireEvent("replace", key, old, o);
12410 * Adds all elements of an Array or an Object to the collection.
12411 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12412 * an Array of values, each of which are added to the collection.
12414 addAll : function(objs){
12415 if(arguments.length > 1 || objs instanceof Array){
12416 var args = arguments.length > 1 ? arguments : objs;
12417 for(var i = 0, len = args.length; i < len; i++){
12421 for(var key in objs){
12422 if(this.allowFunctions || typeof objs[key] != "function"){
12423 this.add(key, objs[key]);
12430 * Executes the specified function once for every item in the collection, passing each
12431 * item as the first and only parameter. returning false from the function will stop the iteration.
12432 * @param {Function} fn The function to execute for each item.
12433 * @param {Object} scope (optional) The scope in which to execute the function.
12435 each : function(fn, scope){
12436 var items = [].concat(this.items); // each safe for removal
12437 for(var i = 0, len = items.length; i < len; i++){
12438 if(fn.call(scope || items[i], items[i], i, len) === false){
12445 * Executes the specified function once for every key in the collection, passing each
12446 * key, and its associated item as the first two parameters.
12447 * @param {Function} fn The function to execute for each item.
12448 * @param {Object} scope (optional) The scope in which to execute the function.
12450 eachKey : function(fn, scope){
12451 for(var i = 0, len = this.keys.length; i < len; i++){
12452 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12457 * Returns the first item in the collection which elicits a true return value from the
12458 * passed selection function.
12459 * @param {Function} fn The selection function to execute for each item.
12460 * @param {Object} scope (optional) The scope in which to execute the function.
12461 * @return {Object} The first item in the collection which returned true from the selection function.
12463 find : function(fn, scope){
12464 for(var i = 0, len = this.items.length; i < len; i++){
12465 if(fn.call(scope || window, this.items[i], this.keys[i])){
12466 return this.items[i];
12473 * Inserts an item at the specified index in the collection.
12474 * @param {Number} index The index to insert the item at.
12475 * @param {String} key The key to associate with the new item, or the item itself.
12476 * @param {Object} o (optional) If the second parameter was a key, the new item.
12477 * @return {Object} The item inserted.
12479 insert : function(index, key, o){
12480 if(arguments.length == 2){
12482 key = this.getKey(o);
12484 if(index >= this.length){
12485 return this.add(key, o);
12488 this.items.splice(index, 0, o);
12489 if(typeof key != "undefined" && key != null){
12492 this.keys.splice(index, 0, key);
12493 this.fireEvent("add", index, o, key);
12498 * Removed an item from the collection.
12499 * @param {Object} o The item to remove.
12500 * @return {Object} The item removed.
12502 remove : function(o){
12503 return this.removeAt(this.indexOf(o));
12507 * Remove an item from a specified index in the collection.
12508 * @param {Number} index The index within the collection of the item to remove.
12510 removeAt : function(index){
12511 if(index < this.length && index >= 0){
12513 var o = this.items[index];
12514 this.items.splice(index, 1);
12515 var key = this.keys[index];
12516 if(typeof key != "undefined"){
12517 delete this.map[key];
12519 this.keys.splice(index, 1);
12520 this.fireEvent("remove", o, key);
12525 * Removed an item associated with the passed key fom the collection.
12526 * @param {String} key The key of the item to remove.
12528 removeKey : function(key){
12529 return this.removeAt(this.indexOfKey(key));
12533 * Returns the number of items in the collection.
12534 * @return {Number} the number of items in the collection.
12536 getCount : function(){
12537 return this.length;
12541 * Returns index within the collection of the passed Object.
12542 * @param {Object} o The item to find the index of.
12543 * @return {Number} index of the item.
12545 indexOf : function(o){
12546 if(!this.items.indexOf){
12547 for(var i = 0, len = this.items.length; i < len; i++){
12548 if(this.items[i] == o) return i;
12552 return this.items.indexOf(o);
12557 * Returns index within the collection of the passed key.
12558 * @param {String} key The key to find the index of.
12559 * @return {Number} index of the key.
12561 indexOfKey : function(key){
12562 if(!this.keys.indexOf){
12563 for(var i = 0, len = this.keys.length; i < len; i++){
12564 if(this.keys[i] == key) return i;
12568 return this.keys.indexOf(key);
12573 * Returns the item associated with the passed key OR index. Key has priority over index.
12574 * @param {String/Number} key The key or index of the item.
12575 * @return {Object} The item associated with the passed key.
12577 item : function(key){
12578 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12579 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12583 * Returns the item at the specified index.
12584 * @param {Number} index The index of the item.
12587 itemAt : function(index){
12588 return this.items[index];
12592 * Returns the item associated with the passed key.
12593 * @param {String/Number} key The key of the item.
12594 * @return {Object} The item associated with the passed key.
12596 key : function(key){
12597 return this.map[key];
12601 * Returns true if the collection contains the passed Object as an item.
12602 * @param {Object} o The Object to look for in the collection.
12603 * @return {Boolean} True if the collection contains the Object as an item.
12605 contains : function(o){
12606 return this.indexOf(o) != -1;
12610 * Returns true if the collection contains the passed Object as a key.
12611 * @param {String} key The key to look for in the collection.
12612 * @return {Boolean} True if the collection contains the Object as a key.
12614 containsKey : function(key){
12615 return typeof this.map[key] != "undefined";
12619 * Removes all items from the collection.
12621 clear : function(){
12626 this.fireEvent("clear");
12630 * Returns the first item in the collection.
12631 * @return {Object} the first item in the collection..
12633 first : function(){
12634 return this.items[0];
12638 * Returns the last item in the collection.
12639 * @return {Object} the last item in the collection..
12642 return this.items[this.length-1];
12645 _sort : function(property, dir, fn){
12646 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12647 fn = fn || function(a, b){
12650 var c = [], k = this.keys, items = this.items;
12651 for(var i = 0, len = items.length; i < len; i++){
12652 c[c.length] = {key: k[i], value: items[i], index: i};
12654 c.sort(function(a, b){
12655 var v = fn(a[property], b[property]) * dsc;
12657 v = (a.index < b.index ? -1 : 1);
12661 for(var i = 0, len = c.length; i < len; i++){
12662 items[i] = c[i].value;
12665 this.fireEvent("sort", this);
12669 * Sorts this collection with the passed comparison function
12670 * @param {String} direction (optional) "ASC" or "DESC"
12671 * @param {Function} fn (optional) comparison function
12673 sort : function(dir, fn){
12674 this._sort("value", dir, fn);
12678 * Sorts this collection by keys
12679 * @param {String} direction (optional) "ASC" or "DESC"
12680 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12682 keySort : function(dir, fn){
12683 this._sort("key", dir, fn || function(a, b){
12684 return String(a).toUpperCase()-String(b).toUpperCase();
12689 * Returns a range of items in this collection
12690 * @param {Number} startIndex (optional) defaults to 0
12691 * @param {Number} endIndex (optional) default to the last item
12692 * @return {Array} An array of items
12694 getRange : function(start, end){
12695 var items = this.items;
12696 if(items.length < 1){
12699 start = start || 0;
12700 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12703 for(var i = start; i <= end; i++) {
12704 r[r.length] = items[i];
12707 for(var i = start; i >= end; i--) {
12708 r[r.length] = items[i];
12715 * Filter the <i>objects</i> in this collection by a specific property.
12716 * Returns a new collection that has been filtered.
12717 * @param {String} property A property on your objects
12718 * @param {String/RegExp} value Either string that the property values
12719 * should start with or a RegExp to test against the property
12720 * @return {MixedCollection} The new filtered collection
12722 filter : function(property, value){
12723 if(!value.exec){ // not a regex
12724 value = String(value);
12725 if(value.length == 0){
12726 return this.clone();
12728 value = new RegExp("^" + Roo.escapeRe(value), "i");
12730 return this.filterBy(function(o){
12731 return o && value.test(o[property]);
12736 * Filter by a function. * Returns a new collection that has been filtered.
12737 * The passed function will be called with each
12738 * object in the collection. If the function returns true, the value is included
12739 * otherwise it is filtered.
12740 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12741 * @param {Object} scope (optional) The scope of the function (defaults to this)
12742 * @return {MixedCollection} The new filtered collection
12744 filterBy : function(fn, scope){
12745 var r = new Roo.util.MixedCollection();
12746 r.getKey = this.getKey;
12747 var k = this.keys, it = this.items;
12748 for(var i = 0, len = it.length; i < len; i++){
12749 if(fn.call(scope||this, it[i], k[i])){
12750 r.add(k[i], it[i]);
12757 * Creates a duplicate of this collection
12758 * @return {MixedCollection}
12760 clone : function(){
12761 var r = new Roo.util.MixedCollection();
12762 var k = this.keys, it = this.items;
12763 for(var i = 0, len = it.length; i < len; i++){
12764 r.add(k[i], it[i]);
12766 r.getKey = this.getKey;
12771 * Returns the item associated with the passed key or index.
12773 * @param {String/Number} key The key or index of the item.
12774 * @return {Object} The item associated with the passed key.
12776 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12778 * Ext JS Library 1.1.1
12779 * Copyright(c) 2006-2007, Ext JS, LLC.
12781 * Originally Released Under LGPL - original licence link has changed is not relivant.
12784 * <script type="text/javascript">
12787 * @class Roo.util.JSON
12788 * Modified version of Douglas Crockford"s json.js that doesn"t
12789 * mess with the Object prototype
12790 * http://www.json.org/js.html
12793 Roo.util.JSON = new (function(){
12794 var useHasOwn = {}.hasOwnProperty ? true : false;
12796 // crashes Safari in some instances
12797 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12799 var pad = function(n) {
12800 return n < 10 ? "0" + n : n;
12813 var encodeString = function(s){
12814 if (/["\\\x00-\x1f]/.test(s)) {
12815 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12820 c = b.charCodeAt();
12822 Math.floor(c / 16).toString(16) +
12823 (c % 16).toString(16);
12826 return '"' + s + '"';
12829 var encodeArray = function(o){
12830 var a = ["["], b, i, l = o.length, v;
12831 for (i = 0; i < l; i += 1) {
12833 switch (typeof v) {
12842 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12850 var encodeDate = function(o){
12851 return '"' + o.getFullYear() + "-" +
12852 pad(o.getMonth() + 1) + "-" +
12853 pad(o.getDate()) + "T" +
12854 pad(o.getHours()) + ":" +
12855 pad(o.getMinutes()) + ":" +
12856 pad(o.getSeconds()) + '"';
12860 * Encodes an Object, Array or other value
12861 * @param {Mixed} o The variable to encode
12862 * @return {String} The JSON string
12864 this.encode = function(o)
12866 // should this be extended to fully wrap stringify..
12868 if(typeof o == "undefined" || o === null){
12870 }else if(o instanceof Array){
12871 return encodeArray(o);
12872 }else if(o instanceof Date){
12873 return encodeDate(o);
12874 }else if(typeof o == "string"){
12875 return encodeString(o);
12876 }else if(typeof o == "number"){
12877 return isFinite(o) ? String(o) : "null";
12878 }else if(typeof o == "boolean"){
12881 var a = ["{"], b, i, v;
12883 if(!useHasOwn || o.hasOwnProperty(i)) {
12885 switch (typeof v) {
12894 a.push(this.encode(i), ":",
12895 v === null ? "null" : this.encode(v));
12906 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12907 * @param {String} json The JSON string
12908 * @return {Object} The resulting object
12910 this.decode = function(json){
12912 return /** eval:var:json */ eval("(" + json + ')');
12916 * Shorthand for {@link Roo.util.JSON#encode}
12917 * @member Roo encode
12919 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
12921 * Shorthand for {@link Roo.util.JSON#decode}
12922 * @member Roo decode
12924 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
12927 * Ext JS Library 1.1.1
12928 * Copyright(c) 2006-2007, Ext JS, LLC.
12930 * Originally Released Under LGPL - original licence link has changed is not relivant.
12933 * <script type="text/javascript">
12937 * @class Roo.util.Format
12938 * Reusable data formatting functions
12941 Roo.util.Format = function(){
12942 var trimRe = /^\s+|\s+$/g;
12945 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12946 * @param {String} value The string to truncate
12947 * @param {Number} length The maximum length to allow before truncating
12948 * @return {String} The converted text
12950 ellipsis : function(value, len){
12951 if(value && value.length > len){
12952 return value.substr(0, len-3)+"...";
12958 * Checks a reference and converts it to empty string if it is undefined
12959 * @param {Mixed} value Reference to check
12960 * @return {Mixed} Empty string if converted, otherwise the original value
12962 undef : function(value){
12963 return typeof value != "undefined" ? value : "";
12967 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12968 * @param {String} value The string to encode
12969 * @return {String} The encoded text
12971 htmlEncode : function(value){
12972 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12976 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12977 * @param {String} value The string to decode
12978 * @return {String} The decoded text
12980 htmlDecode : function(value){
12981 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12985 * Trims any whitespace from either side of a string
12986 * @param {String} value The text to trim
12987 * @return {String} The trimmed text
12989 trim : function(value){
12990 return String(value).replace(trimRe, "");
12994 * Returns a substring from within an original string
12995 * @param {String} value The original text
12996 * @param {Number} start The start index of the substring
12997 * @param {Number} length The length of the substring
12998 * @return {String} The substring
13000 substr : function(value, start, length){
13001 return String(value).substr(start, length);
13005 * Converts a string to all lower case letters
13006 * @param {String} value The text to convert
13007 * @return {String} The converted text
13009 lowercase : function(value){
13010 return String(value).toLowerCase();
13014 * Converts a string to all upper case letters
13015 * @param {String} value The text to convert
13016 * @return {String} The converted text
13018 uppercase : function(value){
13019 return String(value).toUpperCase();
13023 * Converts the first character only of a string to upper case
13024 * @param {String} value The text to convert
13025 * @return {String} The converted text
13027 capitalize : function(value){
13028 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13032 call : function(value, fn){
13033 if(arguments.length > 2){
13034 var args = Array.prototype.slice.call(arguments, 2);
13035 args.unshift(value);
13037 return /** eval:var:value */ eval(fn).apply(window, args);
13039 /** eval:var:value */
13040 return /** eval:var:value */ eval(fn).call(window, value);
13046 * safer version of Math.toFixed..??/
13047 * @param {Number/String} value The numeric value to format
13048 * @param {Number/String} value Decimal places
13049 * @return {String} The formatted currency string
13051 toFixed : function(v, n)
13053 // why not use to fixed - precision is buggered???
13055 return Math.round(v-0);
13057 var fact = Math.pow(10,n+1);
13058 v = (Math.round((v-0)*fact))/fact;
13059 var z = (''+fact).substring(2);
13060 if (v == Math.floor(v)) {
13061 return Math.floor(v) + '.' + z;
13064 // now just padd decimals..
13065 var ps = String(v).split('.');
13066 var fd = (ps[1] + z);
13067 var r = fd.substring(0,n);
13068 var rm = fd.substring(n);
13070 return ps[0] + '.' + r;
13072 r*=1; // turn it into a number;
13074 if (String(r).length != n) {
13077 r = String(r).substring(1); // chop the end off.
13080 return ps[0] + '.' + r;
13085 * Format a number as US currency
13086 * @param {Number/String} value The numeric value to format
13087 * @return {String} The formatted currency string
13089 usMoney : function(v){
13090 v = (Math.round((v-0)*100))/100;
13091 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13093 var ps = v.split('.');
13095 var sub = ps[1] ? '.'+ ps[1] : '.00';
13096 var r = /(\d+)(\d{3})/;
13097 while (r.test(whole)) {
13098 whole = whole.replace(r, '$1' + ',' + '$2');
13100 return "$" + whole + sub ;
13104 * Parse a value into a formatted date using the specified format pattern.
13105 * @param {Mixed} value The value to format
13106 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13107 * @return {String} The formatted date string
13109 date : function(v, format){
13113 if(!(v instanceof Date)){
13114 v = new Date(Date.parse(v));
13116 return v.dateFormat(format || "m/d/Y");
13120 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13121 * @param {String} format Any valid date format string
13122 * @return {Function} The date formatting function
13124 dateRenderer : function(format){
13125 return function(v){
13126 return Roo.util.Format.date(v, format);
13131 stripTagsRE : /<\/?[^>]+>/gi,
13134 * Strips all HTML tags
13135 * @param {Mixed} value The text from which to strip tags
13136 * @return {String} The stripped text
13138 stripTags : function(v){
13139 return !v ? v : String(v).replace(this.stripTagsRE, "");
13144 * Ext JS Library 1.1.1
13145 * Copyright(c) 2006-2007, Ext JS, LLC.
13147 * Originally Released Under LGPL - original licence link has changed is not relivant.
13150 * <script type="text/javascript">
13157 * @class Roo.MasterTemplate
13158 * @extends Roo.Template
13159 * Provides a template that can have child templates. The syntax is:
13161 var t = new Roo.MasterTemplate(
13162 '<select name="{name}">',
13163 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13166 t.add('options', {value: 'foo', text: 'bar'});
13167 // or you can add multiple child elements in one shot
13168 t.addAll('options', [
13169 {value: 'foo', text: 'bar'},
13170 {value: 'foo2', text: 'bar2'},
13171 {value: 'foo3', text: 'bar3'}
13173 // then append, applying the master template values
13174 t.append('my-form', {name: 'my-select'});
13176 * A name attribute for the child template is not required if you have only one child
13177 * template or you want to refer to them by index.
13179 Roo.MasterTemplate = function(){
13180 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13181 this.originalHtml = this.html;
13183 var m, re = this.subTemplateRe;
13186 while(m = re.exec(this.html)){
13187 var name = m[1], content = m[2];
13192 tpl : new Roo.Template(content)
13195 st[name] = st[subIndex];
13197 st[subIndex].tpl.compile();
13198 st[subIndex].tpl.call = this.call.createDelegate(this);
13201 this.subCount = subIndex;
13204 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13206 * The regular expression used to match sub templates
13210 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13213 * Applies the passed values to a child template.
13214 * @param {String/Number} name (optional) The name or index of the child template
13215 * @param {Array/Object} values The values to be applied to the template
13216 * @return {MasterTemplate} this
13218 add : function(name, values){
13219 if(arguments.length == 1){
13220 values = arguments[0];
13223 var s = this.subs[name];
13224 s.buffer[s.buffer.length] = s.tpl.apply(values);
13229 * Applies all the passed values to a child template.
13230 * @param {String/Number} name (optional) The name or index of the child template
13231 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13232 * @param {Boolean} reset (optional) True to reset the template first
13233 * @return {MasterTemplate} this
13235 fill : function(name, values, reset){
13237 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13245 for(var i = 0, len = values.length; i < len; i++){
13246 this.add(name, values[i]);
13252 * Resets the template for reuse
13253 * @return {MasterTemplate} this
13255 reset : function(){
13257 for(var i = 0; i < this.subCount; i++){
13263 applyTemplate : function(values){
13265 var replaceIndex = -1;
13266 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13267 return s[++replaceIndex].buffer.join("");
13269 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13272 apply : function(){
13273 return this.applyTemplate.apply(this, arguments);
13276 compile : function(){return this;}
13280 * Alias for fill().
13283 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13285 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13286 * var tpl = Roo.MasterTemplate.from('element-id');
13287 * @param {String/HTMLElement} el
13288 * @param {Object} config
13291 Roo.MasterTemplate.from = function(el, config){
13292 el = Roo.getDom(el);
13293 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13296 * Ext JS Library 1.1.1
13297 * Copyright(c) 2006-2007, Ext JS, LLC.
13299 * Originally Released Under LGPL - original licence link has changed is not relivant.
13302 * <script type="text/javascript">
13307 * @class Roo.util.CSS
13308 * Utility class for manipulating CSS rules
13311 Roo.util.CSS = function(){
13313 var doc = document;
13315 var camelRe = /(-[a-z])/gi;
13316 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13320 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13321 * tag and appended to the HEAD of the document.
13322 * @param {String|Object} cssText The text containing the css rules
13323 * @param {String} id An id to add to the stylesheet for later removal
13324 * @return {StyleSheet}
13326 createStyleSheet : function(cssText, id){
13328 var head = doc.getElementsByTagName("head")[0];
13329 var nrules = doc.createElement("style");
13330 nrules.setAttribute("type", "text/css");
13332 nrules.setAttribute("id", id);
13334 if (typeof(cssText) != 'string') {
13335 // support object maps..
13336 // not sure if this a good idea..
13337 // perhaps it should be merged with the general css handling
13338 // and handle js style props.
13339 var cssTextNew = [];
13340 for(var n in cssText) {
13342 for(var k in cssText[n]) {
13343 citems.push( k + ' : ' +cssText[n][k] + ';' );
13345 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13348 cssText = cssTextNew.join("\n");
13354 head.appendChild(nrules);
13355 ss = nrules.styleSheet;
13356 ss.cssText = cssText;
13359 nrules.appendChild(doc.createTextNode(cssText));
13361 nrules.cssText = cssText;
13363 head.appendChild(nrules);
13364 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13366 this.cacheStyleSheet(ss);
13371 * Removes a style or link tag by id
13372 * @param {String} id The id of the tag
13374 removeStyleSheet : function(id){
13375 var existing = doc.getElementById(id);
13377 existing.parentNode.removeChild(existing);
13382 * Dynamically swaps an existing stylesheet reference for a new one
13383 * @param {String} id The id of an existing link tag to remove
13384 * @param {String} url The href of the new stylesheet to include
13386 swapStyleSheet : function(id, url){
13387 this.removeStyleSheet(id);
13388 var ss = doc.createElement("link");
13389 ss.setAttribute("rel", "stylesheet");
13390 ss.setAttribute("type", "text/css");
13391 ss.setAttribute("id", id);
13392 ss.setAttribute("href", url);
13393 doc.getElementsByTagName("head")[0].appendChild(ss);
13397 * Refresh the rule cache if you have dynamically added stylesheets
13398 * @return {Object} An object (hash) of rules indexed by selector
13400 refreshCache : function(){
13401 return this.getRules(true);
13405 cacheStyleSheet : function(stylesheet){
13409 try{// try catch for cross domain access issue
13410 var ssRules = stylesheet.cssRules || stylesheet.rules;
13411 for(var j = ssRules.length-1; j >= 0; --j){
13412 rules[ssRules[j].selectorText] = ssRules[j];
13418 * Gets all css rules for the document
13419 * @param {Boolean} refreshCache true to refresh the internal cache
13420 * @return {Object} An object (hash) of rules indexed by selector
13422 getRules : function(refreshCache){
13423 if(rules == null || refreshCache){
13425 var ds = doc.styleSheets;
13426 for(var i =0, len = ds.length; i < len; i++){
13428 this.cacheStyleSheet(ds[i]);
13436 * Gets an an individual CSS rule by selector(s)
13437 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13438 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13439 * @return {CSSRule} The CSS rule or null if one is not found
13441 getRule : function(selector, refreshCache){
13442 var rs = this.getRules(refreshCache);
13443 if(!(selector instanceof Array)){
13444 return rs[selector];
13446 for(var i = 0; i < selector.length; i++){
13447 if(rs[selector[i]]){
13448 return rs[selector[i]];
13456 * Updates a rule property
13457 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13458 * @param {String} property The css property
13459 * @param {String} value The new value for the property
13460 * @return {Boolean} true If a rule was found and updated
13462 updateRule : function(selector, property, value){
13463 if(!(selector instanceof Array)){
13464 var rule = this.getRule(selector);
13466 rule.style[property.replace(camelRe, camelFn)] = value;
13470 for(var i = 0; i < selector.length; i++){
13471 if(this.updateRule(selector[i], property, value)){
13481 * Ext JS Library 1.1.1
13482 * Copyright(c) 2006-2007, Ext JS, LLC.
13484 * Originally Released Under LGPL - original licence link has changed is not relivant.
13487 * <script type="text/javascript">
13493 * @class Roo.util.ClickRepeater
13494 * @extends Roo.util.Observable
13496 * A wrapper class which can be applied to any element. Fires a "click" event while the
13497 * mouse is pressed. The interval between firings may be specified in the config but
13498 * defaults to 10 milliseconds.
13500 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13502 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13503 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13504 * Similar to an autorepeat key delay.
13505 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13506 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13507 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13508 * "interval" and "delay" are ignored. "immediate" is honored.
13509 * @cfg {Boolean} preventDefault True to prevent the default click event
13510 * @cfg {Boolean} stopDefault True to stop the default click event
13513 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13514 * 2007-02-02 jvs Renamed to ClickRepeater
13515 * 2007-02-03 jvs Modifications for FF Mac and Safari
13518 * @param {String/HTMLElement/Element} el The element to listen on
13519 * @param {Object} config
13521 Roo.util.ClickRepeater = function(el, config)
13523 this.el = Roo.get(el);
13524 this.el.unselectable();
13526 Roo.apply(this, config);
13531 * Fires when the mouse button is depressed.
13532 * @param {Roo.util.ClickRepeater} this
13534 "mousedown" : true,
13537 * Fires on a specified interval during the time the element is pressed.
13538 * @param {Roo.util.ClickRepeater} this
13543 * Fires when the mouse key is released.
13544 * @param {Roo.util.ClickRepeater} this
13549 this.el.on("mousedown", this.handleMouseDown, this);
13550 if(this.preventDefault || this.stopDefault){
13551 this.el.on("click", function(e){
13552 if(this.preventDefault){
13553 e.preventDefault();
13555 if(this.stopDefault){
13561 // allow inline handler
13563 this.on("click", this.handler, this.scope || this);
13566 Roo.util.ClickRepeater.superclass.constructor.call(this);
13569 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13572 preventDefault : true,
13573 stopDefault : false,
13577 handleMouseDown : function(){
13578 clearTimeout(this.timer);
13580 if(this.pressClass){
13581 this.el.addClass(this.pressClass);
13583 this.mousedownTime = new Date();
13585 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13586 this.el.on("mouseout", this.handleMouseOut, this);
13588 this.fireEvent("mousedown", this);
13589 this.fireEvent("click", this);
13591 this.timer = this.click.defer(this.delay || this.interval, this);
13595 click : function(){
13596 this.fireEvent("click", this);
13597 this.timer = this.click.defer(this.getInterval(), this);
13601 getInterval: function(){
13602 if(!this.accelerate){
13603 return this.interval;
13605 var pressTime = this.mousedownTime.getElapsed();
13606 if(pressTime < 500){
13608 }else if(pressTime < 1700){
13610 }else if(pressTime < 2600){
13612 }else if(pressTime < 3500){
13614 }else if(pressTime < 4400){
13616 }else if(pressTime < 5300){
13618 }else if(pressTime < 6200){
13626 handleMouseOut : function(){
13627 clearTimeout(this.timer);
13628 if(this.pressClass){
13629 this.el.removeClass(this.pressClass);
13631 this.el.on("mouseover", this.handleMouseReturn, this);
13635 handleMouseReturn : function(){
13636 this.el.un("mouseover", this.handleMouseReturn);
13637 if(this.pressClass){
13638 this.el.addClass(this.pressClass);
13644 handleMouseUp : function(){
13645 clearTimeout(this.timer);
13646 this.el.un("mouseover", this.handleMouseReturn);
13647 this.el.un("mouseout", this.handleMouseOut);
13648 Roo.get(document).un("mouseup", this.handleMouseUp);
13649 this.el.removeClass(this.pressClass);
13650 this.fireEvent("mouseup", this);
13654 * Ext JS Library 1.1.1
13655 * Copyright(c) 2006-2007, Ext JS, LLC.
13657 * Originally Released Under LGPL - original licence link has changed is not relivant.
13660 * <script type="text/javascript">
13665 * @class Roo.KeyNav
13666 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13667 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13668 * way to implement custom navigation schemes for any UI component.</p>
13669 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13670 * pageUp, pageDown, del, home, end. Usage:</p>
13672 var nav = new Roo.KeyNav("my-element", {
13673 "left" : function(e){
13674 this.moveLeft(e.ctrlKey);
13676 "right" : function(e){
13677 this.moveRight(e.ctrlKey);
13679 "enter" : function(e){
13686 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13687 * @param {Object} config The config
13689 Roo.KeyNav = function(el, config){
13690 this.el = Roo.get(el);
13691 Roo.apply(this, config);
13692 if(!this.disabled){
13693 this.disabled = true;
13698 Roo.KeyNav.prototype = {
13700 * @cfg {Boolean} disabled
13701 * True to disable this KeyNav instance (defaults to false)
13705 * @cfg {String} defaultEventAction
13706 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13707 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13708 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13710 defaultEventAction: "stopEvent",
13712 * @cfg {Boolean} forceKeyDown
13713 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13714 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13715 * handle keydown instead of keypress.
13717 forceKeyDown : false,
13720 prepareEvent : function(e){
13721 var k = e.getKey();
13722 var h = this.keyToHandler[k];
13723 //if(h && this[h]){
13724 // e.stopPropagation();
13726 if(Roo.isSafari && h && k >= 37 && k <= 40){
13732 relay : function(e){
13733 var k = e.getKey();
13734 var h = this.keyToHandler[k];
13736 if(this.doRelay(e, this[h], h) !== true){
13737 e[this.defaultEventAction]();
13743 doRelay : function(e, h, hname){
13744 return h.call(this.scope || this, e);
13747 // possible handlers
13761 // quick lookup hash
13778 * Enable this KeyNav
13780 enable: function(){
13782 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13783 // the EventObject will normalize Safari automatically
13784 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13785 this.el.on("keydown", this.relay, this);
13787 this.el.on("keydown", this.prepareEvent, this);
13788 this.el.on("keypress", this.relay, this);
13790 this.disabled = false;
13795 * Disable this KeyNav
13797 disable: function(){
13798 if(!this.disabled){
13799 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13800 this.el.un("keydown", this.relay);
13802 this.el.un("keydown", this.prepareEvent);
13803 this.el.un("keypress", this.relay);
13805 this.disabled = true;
13810 * Ext JS Library 1.1.1
13811 * Copyright(c) 2006-2007, Ext JS, LLC.
13813 * Originally Released Under LGPL - original licence link has changed is not relivant.
13816 * <script type="text/javascript">
13821 * @class Roo.KeyMap
13822 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13823 * The constructor accepts the same config object as defined by {@link #addBinding}.
13824 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13825 * combination it will call the function with this signature (if the match is a multi-key
13826 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13827 * A KeyMap can also handle a string representation of keys.<br />
13830 // map one key by key code
13831 var map = new Roo.KeyMap("my-element", {
13832 key: 13, // or Roo.EventObject.ENTER
13837 // map multiple keys to one action by string
13838 var map = new Roo.KeyMap("my-element", {
13844 // map multiple keys to multiple actions by strings and array of codes
13845 var map = new Roo.KeyMap("my-element", [
13848 fn: function(){ alert("Return was pressed"); }
13851 fn: function(){ alert('a, b or c was pressed'); }
13856 fn: function(){ alert('Control + shift + tab was pressed.'); }
13860 * <b>Note: A KeyMap starts enabled</b>
13862 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13863 * @param {Object} config The config (see {@link #addBinding})
13864 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13866 Roo.KeyMap = function(el, config, eventName){
13867 this.el = Roo.get(el);
13868 this.eventName = eventName || "keydown";
13869 this.bindings = [];
13871 this.addBinding(config);
13876 Roo.KeyMap.prototype = {
13878 * True to stop the event from bubbling and prevent the default browser action if the
13879 * key was handled by the KeyMap (defaults to false)
13885 * Add a new binding to this KeyMap. The following config object properties are supported:
13887 Property Type Description
13888 ---------- --------------- ----------------------------------------------------------------------
13889 key String/Array A single keycode or an array of keycodes to handle
13890 shift Boolean True to handle key only when shift is pressed (defaults to false)
13891 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13892 alt Boolean True to handle key only when alt is pressed (defaults to false)
13893 fn Function The function to call when KeyMap finds the expected key combination
13894 scope Object The scope of the callback function
13900 var map = new Roo.KeyMap(document, {
13901 key: Roo.EventObject.ENTER,
13906 //Add a new binding to the existing KeyMap later
13914 * @param {Object/Array} config A single KeyMap config or an array of configs
13916 addBinding : function(config){
13917 if(config instanceof Array){
13918 for(var i = 0, len = config.length; i < len; i++){
13919 this.addBinding(config[i]);
13923 var keyCode = config.key,
13924 shift = config.shift,
13925 ctrl = config.ctrl,
13928 scope = config.scope;
13929 if(typeof keyCode == "string"){
13931 var keyString = keyCode.toUpperCase();
13932 for(var j = 0, len = keyString.length; j < len; j++){
13933 ks.push(keyString.charCodeAt(j));
13937 var keyArray = keyCode instanceof Array;
13938 var handler = function(e){
13939 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13940 var k = e.getKey();
13942 for(var i = 0, len = keyCode.length; i < len; i++){
13943 if(keyCode[i] == k){
13944 if(this.stopEvent){
13947 fn.call(scope || window, k, e);
13953 if(this.stopEvent){
13956 fn.call(scope || window, k, e);
13961 this.bindings.push(handler);
13965 * Shorthand for adding a single key listener
13966 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13967 * following options:
13968 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13969 * @param {Function} fn The function to call
13970 * @param {Object} scope (optional) The scope of the function
13972 on : function(key, fn, scope){
13973 var keyCode, shift, ctrl, alt;
13974 if(typeof key == "object" && !(key instanceof Array)){
13993 handleKeyDown : function(e){
13994 if(this.enabled){ //just in case
13995 var b = this.bindings;
13996 for(var i = 0, len = b.length; i < len; i++){
13997 b[i].call(this, e);
14003 * Returns true if this KeyMap is enabled
14004 * @return {Boolean}
14006 isEnabled : function(){
14007 return this.enabled;
14011 * Enables this KeyMap
14013 enable: function(){
14015 this.el.on(this.eventName, this.handleKeyDown, this);
14016 this.enabled = true;
14021 * Disable this KeyMap
14023 disable: function(){
14025 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14026 this.enabled = false;
14031 * Ext JS Library 1.1.1
14032 * Copyright(c) 2006-2007, Ext JS, LLC.
14034 * Originally Released Under LGPL - original licence link has changed is not relivant.
14037 * <script type="text/javascript">
14042 * @class Roo.util.TextMetrics
14043 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14044 * wide, in pixels, a given block of text will be.
14047 Roo.util.TextMetrics = function(){
14051 * Measures the size of the specified text
14052 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14053 * that can affect the size of the rendered text
14054 * @param {String} text The text to measure
14055 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14056 * in order to accurately measure the text height
14057 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14059 measure : function(el, text, fixedWidth){
14061 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14064 shared.setFixedWidth(fixedWidth || 'auto');
14065 return shared.getSize(text);
14069 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14070 * the overhead of multiple calls to initialize the style properties on each measurement.
14071 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14072 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14073 * in order to accurately measure the text height
14074 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14076 createInstance : function(el, fixedWidth){
14077 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14084 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14085 var ml = new Roo.Element(document.createElement('div'));
14086 document.body.appendChild(ml.dom);
14087 ml.position('absolute');
14088 ml.setLeftTop(-1000, -1000);
14092 ml.setWidth(fixedWidth);
14097 * Returns the size of the specified text based on the internal element's style and width properties
14098 * @memberOf Roo.util.TextMetrics.Instance#
14099 * @param {String} text The text to measure
14100 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14102 getSize : function(text){
14104 var s = ml.getSize();
14110 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14111 * that can affect the size of the rendered text
14112 * @memberOf Roo.util.TextMetrics.Instance#
14113 * @param {String/HTMLElement} el The element, dom node or id
14115 bind : function(el){
14117 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14122 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14123 * to set a fixed width in order to accurately measure the text height.
14124 * @memberOf Roo.util.TextMetrics.Instance#
14125 * @param {Number} width The width to set on the element
14127 setFixedWidth : function(width){
14128 ml.setWidth(width);
14132 * Returns the measured width of the specified text
14133 * @memberOf Roo.util.TextMetrics.Instance#
14134 * @param {String} text The text to measure
14135 * @return {Number} width The width in pixels
14137 getWidth : function(text){
14138 ml.dom.style.width = 'auto';
14139 return this.getSize(text).width;
14143 * Returns the measured height of the specified text. For multiline text, be sure to call
14144 * {@link #setFixedWidth} if necessary.
14145 * @memberOf Roo.util.TextMetrics.Instance#
14146 * @param {String} text The text to measure
14147 * @return {Number} height The height in pixels
14149 getHeight : function(text){
14150 return this.getSize(text).height;
14154 instance.bind(bindTo);
14159 // backwards compat
14160 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14162 * Ext JS Library 1.1.1
14163 * Copyright(c) 2006-2007, Ext JS, LLC.
14165 * Originally Released Under LGPL - original licence link has changed is not relivant.
14168 * <script type="text/javascript">
14172 * @class Roo.state.Provider
14173 * Abstract base class for state provider implementations. This class provides methods
14174 * for encoding and decoding <b>typed</b> variables including dates and defines the
14175 * Provider interface.
14177 Roo.state.Provider = function(){
14179 * @event statechange
14180 * Fires when a state change occurs.
14181 * @param {Provider} this This state provider
14182 * @param {String} key The state key which was changed
14183 * @param {String} value The encoded value for the state
14186 "statechange": true
14189 Roo.state.Provider.superclass.constructor.call(this);
14191 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14193 * Returns the current value for a key
14194 * @param {String} name The key name
14195 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14196 * @return {Mixed} The state data
14198 get : function(name, defaultValue){
14199 return typeof this.state[name] == "undefined" ?
14200 defaultValue : this.state[name];
14204 * Clears a value from the state
14205 * @param {String} name The key name
14207 clear : function(name){
14208 delete this.state[name];
14209 this.fireEvent("statechange", this, name, null);
14213 * Sets the value for a key
14214 * @param {String} name The key name
14215 * @param {Mixed} value The value to set
14217 set : function(name, value){
14218 this.state[name] = value;
14219 this.fireEvent("statechange", this, name, value);
14223 * Decodes a string previously encoded with {@link #encodeValue}.
14224 * @param {String} value The value to decode
14225 * @return {Mixed} The decoded value
14227 decodeValue : function(cookie){
14228 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14229 var matches = re.exec(unescape(cookie));
14230 if(!matches || !matches[1]) return; // non state cookie
14231 var type = matches[1];
14232 var v = matches[2];
14235 return parseFloat(v);
14237 return new Date(Date.parse(v));
14242 var values = v.split("^");
14243 for(var i = 0, len = values.length; i < len; i++){
14244 all.push(this.decodeValue(values[i]));
14249 var values = v.split("^");
14250 for(var i = 0, len = values.length; i < len; i++){
14251 var kv = values[i].split("=");
14252 all[kv[0]] = this.decodeValue(kv[1]);
14261 * Encodes a value including type information. Decode with {@link #decodeValue}.
14262 * @param {Mixed} value The value to encode
14263 * @return {String} The encoded value
14265 encodeValue : function(v){
14267 if(typeof v == "number"){
14269 }else if(typeof v == "boolean"){
14270 enc = "b:" + (v ? "1" : "0");
14271 }else if(v instanceof Date){
14272 enc = "d:" + v.toGMTString();
14273 }else if(v instanceof Array){
14275 for(var i = 0, len = v.length; i < len; i++){
14276 flat += this.encodeValue(v[i]);
14277 if(i != len-1) flat += "^";
14280 }else if(typeof v == "object"){
14283 if(typeof v[key] != "function"){
14284 flat += key + "=" + this.encodeValue(v[key]) + "^";
14287 enc = "o:" + flat.substring(0, flat.length-1);
14291 return escape(enc);
14297 * Ext JS Library 1.1.1
14298 * Copyright(c) 2006-2007, Ext JS, LLC.
14300 * Originally Released Under LGPL - original licence link has changed is not relivant.
14303 * <script type="text/javascript">
14306 * @class Roo.state.Manager
14307 * This is the global state manager. By default all components that are "state aware" check this class
14308 * for state information if you don't pass them a custom state provider. In order for this class
14309 * to be useful, it must be initialized with a provider when your application initializes.
14311 // in your initialization function
14313 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14315 // supposed you have a {@link Roo.BorderLayout}
14316 var layout = new Roo.BorderLayout(...);
14317 layout.restoreState();
14318 // or a {Roo.BasicDialog}
14319 var dialog = new Roo.BasicDialog(...);
14320 dialog.restoreState();
14324 Roo.state.Manager = function(){
14325 var provider = new Roo.state.Provider();
14329 * Configures the default state provider for your application
14330 * @param {Provider} stateProvider The state provider to set
14332 setProvider : function(stateProvider){
14333 provider = stateProvider;
14337 * Returns the current value for a key
14338 * @param {String} name The key name
14339 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14340 * @return {Mixed} The state data
14342 get : function(key, defaultValue){
14343 return provider.get(key, defaultValue);
14347 * Sets the value for a key
14348 * @param {String} name The key name
14349 * @param {Mixed} value The state data
14351 set : function(key, value){
14352 provider.set(key, value);
14356 * Clears a value from the state
14357 * @param {String} name The key name
14359 clear : function(key){
14360 provider.clear(key);
14364 * Gets the currently configured state provider
14365 * @return {Provider} The state provider
14367 getProvider : function(){
14374 * Ext JS Library 1.1.1
14375 * Copyright(c) 2006-2007, Ext JS, LLC.
14377 * Originally Released Under LGPL - original licence link has changed is not relivant.
14380 * <script type="text/javascript">
14383 * @class Roo.state.CookieProvider
14384 * @extends Roo.state.Provider
14385 * The default Provider implementation which saves state via cookies.
14388 var cp = new Roo.state.CookieProvider({
14390 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14391 domain: "roojs.com"
14393 Roo.state.Manager.setProvider(cp);
14395 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14396 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14397 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14398 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14399 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14400 * domain the page is running on including the 'www' like 'www.roojs.com')
14401 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14403 * Create a new CookieProvider
14404 * @param {Object} config The configuration object
14406 Roo.state.CookieProvider = function(config){
14407 Roo.state.CookieProvider.superclass.constructor.call(this);
14409 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14410 this.domain = null;
14411 this.secure = false;
14412 Roo.apply(this, config);
14413 this.state = this.readCookies();
14416 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14418 set : function(name, value){
14419 if(typeof value == "undefined" || value === null){
14423 this.setCookie(name, value);
14424 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14428 clear : function(name){
14429 this.clearCookie(name);
14430 Roo.state.CookieProvider.superclass.clear.call(this, name);
14434 readCookies : function(){
14436 var c = document.cookie + ";";
14437 var re = /\s?(.*?)=(.*?);/g;
14439 while((matches = re.exec(c)) != null){
14440 var name = matches[1];
14441 var value = matches[2];
14442 if(name && name.substring(0,3) == "ys-"){
14443 cookies[name.substr(3)] = this.decodeValue(value);
14450 setCookie : function(name, value){
14451 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14452 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14453 ((this.path == null) ? "" : ("; path=" + this.path)) +
14454 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14455 ((this.secure == true) ? "; secure" : "");
14459 clearCookie : function(name){
14460 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14461 ((this.path == null) ? "" : ("; path=" + this.path)) +
14462 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14463 ((this.secure == true) ? "; secure" : "");