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">
4031 * @class Roo.DomHelper
4032 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
4033 * 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>.
4036 Roo.DomHelper = function(){
4037 var tempTableEl = null;
4038 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
4039 var tableRe = /^table|tbody|tr|td$/i;
4041 // build as innerHTML where available
4043 var createHtml = function(o){
4044 if(typeof o == 'string'){
4053 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4054 if(attr == "style"){
4056 if(typeof s == "function"){
4059 if(typeof s == "string"){
4060 b += ' style="' + s + '"';
4061 }else if(typeof s == "object"){
4064 if(typeof s[key] != "function"){
4065 b += key + ":" + s[key] + ";";
4072 b += ' class="' + o["cls"] + '"';
4073 }else if(attr == "htmlFor"){
4074 b += ' for="' + o["htmlFor"] + '"';
4076 b += " " + attr + '="' + o[attr] + '"';
4080 if(emptyTags.test(o.tag)){
4084 var cn = o.children || o.cn;
4086 //http://bugs.kde.org/show_bug.cgi?id=71506
4087 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4088 for(var i = 0, len = cn.length; i < len; i++) {
4089 b += createHtml(cn[i], b);
4092 b += createHtml(cn, b);
4098 b += "</" + o.tag + ">";
4105 var createDom = function(o, parentNode){
4107 // defininition craeted..
4109 if (o.ns && o.ns != 'html') {
4111 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4112 xmlns[o.ns] = o.xmlns;
4115 if (typeof(xmlns[o.ns]) == 'undefined') {
4116 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4122 if (typeof(o) == 'string') {
4123 return parentNode.appendChild(document.createTextNode(o));
4125 o.tag = o.tag || div;
4126 if (o.ns && Roo.isIE) {
4128 o.tag = o.ns + ':' + o.tag;
4131 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4132 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4135 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4136 attr == "style" || typeof o[attr] == "function") continue;
4138 if(attr=="cls" && Roo.isIE){
4139 el.className = o["cls"];
4141 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4142 else el[attr] = o[attr];
4145 Roo.DomHelper.applyStyles(el, o.style);
4146 var cn = o.children || o.cn;
4148 //http://bugs.kde.org/show_bug.cgi?id=71506
4149 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4150 for(var i = 0, len = cn.length; i < len; i++) {
4151 createDom(cn[i], el);
4158 el.innerHTML = o.html;
4161 parentNode.appendChild(el);
4166 var ieTable = function(depth, s, h, e){
4167 tempTableEl.innerHTML = [s, h, e].join('');
4168 var i = -1, el = tempTableEl;
4175 // kill repeat to save bytes
4179 tbe = '</tbody>'+te,
4185 * Nasty code for IE's broken table implementation
4187 var insertIntoTable = function(tag, where, el, html){
4189 tempTableEl = document.createElement('div');
4194 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4197 if(where == 'beforebegin'){
4201 before = el.nextSibling;
4204 node = ieTable(4, trs, html, tre);
4206 else if(tag == 'tr'){
4207 if(where == 'beforebegin'){
4210 node = ieTable(3, tbs, html, tbe);
4211 } else if(where == 'afterend'){
4212 before = el.nextSibling;
4214 node = ieTable(3, tbs, html, tbe);
4215 } else{ // INTO a TR
4216 if(where == 'afterbegin'){
4217 before = el.firstChild;
4219 node = ieTable(4, trs, html, tre);
4221 } else if(tag == 'tbody'){
4222 if(where == 'beforebegin'){
4225 node = ieTable(2, ts, html, te);
4226 } else if(where == 'afterend'){
4227 before = el.nextSibling;
4229 node = ieTable(2, ts, html, te);
4231 if(where == 'afterbegin'){
4232 before = el.firstChild;
4234 node = ieTable(3, tbs, html, tbe);
4237 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4240 if(where == 'afterbegin'){
4241 before = el.firstChild;
4243 node = ieTable(2, ts, html, te);
4245 el.insertBefore(node, before);
4250 /** True to force the use of DOM instead of html fragments @type Boolean */
4254 * Returns the markup for the passed Element(s) config
4255 * @param {Object} o The Dom object spec (and children)
4258 markup : function(o){
4259 return createHtml(o);
4263 * Applies a style specification to an element
4264 * @param {String/HTMLElement} el The element to apply styles to
4265 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4266 * a function which returns such a specification.
4268 applyStyles : function(el, styles){
4271 if(typeof styles == "string"){
4272 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4274 while ((matches = re.exec(styles)) != null){
4275 el.setStyle(matches[1], matches[2]);
4277 }else if (typeof styles == "object"){
4278 for (var style in styles){
4279 el.setStyle(style, styles[style]);
4281 }else if (typeof styles == "function"){
4282 Roo.DomHelper.applyStyles(el, styles.call());
4288 * Inserts an HTML fragment into the Dom
4289 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4290 * @param {HTMLElement} el The context element
4291 * @param {String} html The HTML fragmenet
4292 * @return {HTMLElement} The new node
4294 insertHtml : function(where, el, html){
4295 where = where.toLowerCase();
4296 if(el.insertAdjacentHTML){
4297 if(tableRe.test(el.tagName)){
4299 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4305 el.insertAdjacentHTML('BeforeBegin', html);
4306 return el.previousSibling;
4308 el.insertAdjacentHTML('AfterBegin', html);
4309 return el.firstChild;
4311 el.insertAdjacentHTML('BeforeEnd', html);
4312 return el.lastChild;
4314 el.insertAdjacentHTML('AfterEnd', html);
4315 return el.nextSibling;
4317 throw 'Illegal insertion point -> "' + where + '"';
4319 var range = el.ownerDocument.createRange();
4323 range.setStartBefore(el);
4324 frag = range.createContextualFragment(html);
4325 el.parentNode.insertBefore(frag, el);
4326 return el.previousSibling;
4329 range.setStartBefore(el.firstChild);
4330 frag = range.createContextualFragment(html);
4331 el.insertBefore(frag, el.firstChild);
4332 return el.firstChild;
4334 el.innerHTML = html;
4335 return el.firstChild;
4339 range.setStartAfter(el.lastChild);
4340 frag = range.createContextualFragment(html);
4341 el.appendChild(frag);
4342 return el.lastChild;
4344 el.innerHTML = html;
4345 return el.lastChild;
4348 range.setStartAfter(el);
4349 frag = range.createContextualFragment(html);
4350 el.parentNode.insertBefore(frag, el.nextSibling);
4351 return el.nextSibling;
4353 throw 'Illegal insertion point -> "' + where + '"';
4357 * Creates new Dom element(s) and inserts them before el
4358 * @param {String/HTMLElement/Element} el The context element
4359 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4360 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4361 * @return {HTMLElement/Roo.Element} The new node
4363 insertBefore : function(el, o, returnElement){
4364 return this.doInsert(el, o, returnElement, "beforeBegin");
4368 * Creates new Dom element(s) and inserts them after el
4369 * @param {String/HTMLElement/Element} el The context element
4370 * @param {Object} o The Dom object spec (and children)
4371 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4372 * @return {HTMLElement/Roo.Element} The new node
4374 insertAfter : function(el, o, returnElement){
4375 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4379 * Creates new Dom element(s) and inserts them as the first child of el
4380 * @param {String/HTMLElement/Element} el The context element
4381 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4382 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4383 * @return {HTMLElement/Roo.Element} The new node
4385 insertFirst : function(el, o, returnElement){
4386 return this.doInsert(el, o, returnElement, "afterBegin");
4390 doInsert : function(el, o, returnElement, pos, sibling){
4391 el = Roo.getDom(el);
4393 if(this.useDom || o.ns){
4394 newNode = createDom(o, null);
4395 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4397 var html = createHtml(o);
4398 newNode = this.insertHtml(pos, el, html);
4400 return returnElement ? Roo.get(newNode, true) : newNode;
4404 * Creates new Dom element(s) and appends them to el
4405 * @param {String/HTMLElement/Element} el The context element
4406 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4407 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4408 * @return {HTMLElement/Roo.Element} The new node
4410 append : function(el, o, returnElement){
4411 el = Roo.getDom(el);
4413 if(this.useDom || o.ns){
4414 newNode = createDom(o, null);
4415 el.appendChild(newNode);
4417 var html = createHtml(o);
4418 newNode = this.insertHtml("beforeEnd", el, html);
4420 return returnElement ? Roo.get(newNode, true) : newNode;
4424 * Creates new Dom element(s) and overwrites the contents of el with them
4425 * @param {String/HTMLElement/Element} el The context element
4426 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4427 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4428 * @return {HTMLElement/Roo.Element} The new node
4430 overwrite : function(el, o, returnElement){
4431 el = Roo.getDom(el);
4434 while (el.childNodes.length) {
4435 el.removeChild(el.firstChild);
4439 el.innerHTML = createHtml(o);
4442 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4446 * Creates a new Roo.DomHelper.Template from the Dom object spec
4447 * @param {Object} o The Dom object spec (and children)
4448 * @return {Roo.DomHelper.Template} The new template
4450 createTemplate : function(o){
4451 var html = createHtml(o);
4452 return new Roo.Template(html);
4458 * Ext JS Library 1.1.1
4459 * Copyright(c) 2006-2007, Ext JS, LLC.
4461 * Originally Released Under LGPL - original licence link has changed is not relivant.
4464 * <script type="text/javascript">
4468 * @class Roo.Template
4469 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4470 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4473 var t = new Roo.Template({
4474 html : '<div name="{id}">' +
4475 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4477 myformat: function (value, allValues) {
4478 return 'XX' + value;
4481 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4483 * 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>.
4485 * @param {Object} cfg - Configuration object.
4487 Roo.Template = function(cfg){
4489 if(cfg instanceof Array){
4491 }else if(arguments.length > 1){
4492 cfg = Array.prototype.join.call(arguments, "");
4496 if (typeof(cfg) == 'object') {
4505 Roo.Template.prototype = {
4508 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4512 * Returns an HTML fragment of this template with the specified values applied.
4513 * @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'})
4514 * @return {String} The HTML fragment
4516 applyTemplate : function(values){
4520 return this.compiled(values);
4522 var useF = this.disableFormats !== true;
4523 var fm = Roo.util.Format, tpl = this;
4524 var fn = function(m, name, format, args){
4526 if(format.substr(0, 5) == "this."){
4527 return tpl.call(format.substr(5), values[name], values);
4530 // quoted values are required for strings in compiled templates,
4531 // but for non compiled we need to strip them
4532 // quoted reversed for jsmin
4533 var re = /^\s*['"](.*)["']\s*$/;
4534 args = args.split(',');
4535 for(var i = 0, len = args.length; i < len; i++){
4536 args[i] = args[i].replace(re, "$1");
4538 args = [values[name]].concat(args);
4540 args = [values[name]];
4542 return fm[format].apply(fm, args);
4545 return values[name] !== undefined ? values[name] : "";
4548 return this.html.replace(this.re, fn);
4557 * Sets the HTML used as the template and optionally compiles it.
4558 * @param {String} html
4559 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4560 * @return {Roo.Template} this
4562 set : function(html, compile){
4564 this.compiled = null;
4572 * True to disable format functions (defaults to false)
4575 disableFormats : false,
4578 * The regular expression used to match template variables
4582 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4585 * Compiles the template into an internal function, eliminating the RegEx overhead.
4586 * @return {Roo.Template} this
4588 compile : function(){
4589 var fm = Roo.util.Format;
4590 var useF = this.disableFormats !== true;
4591 var sep = Roo.isGecko ? "+" : ",";
4592 var fn = function(m, name, format, args){
4594 args = args ? ',' + args : "";
4595 if(format.substr(0, 5) != "this."){
4596 format = "fm." + format + '(';
4598 format = 'this.call("'+ format.substr(5) + '", ';
4602 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4604 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4607 // branched to use + in gecko and [].join() in others
4609 body = "this.compiled = function(values){ return '" +
4610 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4613 body = ["this.compiled = function(values){ return ['"];
4614 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4615 body.push("'].join('');};");
4616 body = body.join('');
4626 // private function used to call members
4627 call : function(fnName, value, allValues){
4628 return this[fnName](value, allValues);
4632 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4633 * @param {String/HTMLElement/Roo.Element} el The context element
4634 * @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'})
4635 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4636 * @return {HTMLElement/Roo.Element} The new node or Element
4638 insertFirst: function(el, values, returnElement){
4639 return this.doInsert('afterBegin', el, values, returnElement);
4643 * Applies the supplied values to the template and inserts the new node(s) before el.
4644 * @param {String/HTMLElement/Roo.Element} el The context element
4645 * @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'})
4646 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4647 * @return {HTMLElement/Roo.Element} The new node or Element
4649 insertBefore: function(el, values, returnElement){
4650 return this.doInsert('beforeBegin', el, values, returnElement);
4654 * Applies the supplied values to the template and inserts the new node(s) after el.
4655 * @param {String/HTMLElement/Roo.Element} el The context element
4656 * @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'})
4657 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4658 * @return {HTMLElement/Roo.Element} The new node or Element
4660 insertAfter : function(el, values, returnElement){
4661 return this.doInsert('afterEnd', el, values, returnElement);
4665 * Applies the supplied values to the template and appends the new node(s) to el.
4666 * @param {String/HTMLElement/Roo.Element} el The context element
4667 * @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'})
4668 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4669 * @return {HTMLElement/Roo.Element} The new node or Element
4671 append : function(el, values, returnElement){
4672 return this.doInsert('beforeEnd', el, values, returnElement);
4675 doInsert : function(where, el, values, returnEl){
4676 el = Roo.getDom(el);
4677 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4678 return returnEl ? Roo.get(newNode, true) : newNode;
4682 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4683 * @param {String/HTMLElement/Roo.Element} el The context element
4684 * @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'})
4685 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4686 * @return {HTMLElement/Roo.Element} The new node or Element
4688 overwrite : function(el, values, returnElement){
4689 el = Roo.getDom(el);
4690 el.innerHTML = this.applyTemplate(values);
4691 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4695 * Alias for {@link #applyTemplate}
4698 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4701 Roo.DomHelper.Template = Roo.Template;
4704 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4705 * @param {String/HTMLElement} el A DOM element or its id
4706 * @returns {Roo.Template} The created template
4709 Roo.Template.from = function(el){
4710 el = Roo.getDom(el);
4711 return new Roo.Template(el.value || el.innerHTML);
4714 * Ext JS Library 1.1.1
4715 * Copyright(c) 2006-2007, Ext JS, LLC.
4717 * Originally Released Under LGPL - original licence link has changed is not relivant.
4720 * <script type="text/javascript">
4725 * This is code is also distributed under MIT license for use
4726 * with jQuery and prototype JavaScript libraries.
4729 * @class Roo.DomQuery
4730 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).
4732 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>
4735 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.
4737 <h4>Element Selectors:</h4>
4739 <li> <b>*</b> any element</li>
4740 <li> <b>E</b> an element with the tag E</li>
4741 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4742 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4743 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4744 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4746 <h4>Attribute Selectors:</h4>
4747 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4749 <li> <b>E[foo]</b> has an attribute "foo"</li>
4750 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4751 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4752 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4753 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4754 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4755 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4757 <h4>Pseudo Classes:</h4>
4759 <li> <b>E:first-child</b> E is the first child of its parent</li>
4760 <li> <b>E:last-child</b> E is the last child of its parent</li>
4761 <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>
4762 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4763 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4764 <li> <b>E:only-child</b> E is the only child of its parent</li>
4765 <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>
4766 <li> <b>E:first</b> the first E in the resultset</li>
4767 <li> <b>E:last</b> the last E in the resultset</li>
4768 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4769 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4770 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4771 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4772 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4773 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4774 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4775 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4776 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4778 <h4>CSS Value Selectors:</h4>
4780 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4781 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4782 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4783 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4784 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4785 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4789 Roo.DomQuery = function(){
4790 var cache = {}, simpleCache = {}, valueCache = {};
4791 var nonSpace = /\S/;
4792 var trimRe = /^\s+|\s+$/g;
4793 var tplRe = /\{(\d+)\}/g;
4794 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4795 var tagTokenRe = /^(#)?([\w-\*]+)/;
4796 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4798 function child(p, index){
4800 var n = p.firstChild;
4802 if(n.nodeType == 1){
4813 while((n = n.nextSibling) && n.nodeType != 1);
4818 while((n = n.previousSibling) && n.nodeType != 1);
4822 function children(d){
4823 var n = d.firstChild, ni = -1;
4825 var nx = n.nextSibling;
4826 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4836 function byClassName(c, a, v){
4840 var r = [], ri = -1, cn;
4841 for(var i = 0, ci; ci = c[i]; i++){
4842 if((' '+ci.className+' ').indexOf(v) != -1){
4849 function attrValue(n, attr){
4850 if(!n.tagName && typeof n.length != "undefined"){
4859 if(attr == "class" || attr == "className"){
4862 return n.getAttribute(attr) || n[attr];
4866 function getNodes(ns, mode, tagName){
4867 var result = [], ri = -1, cs;
4871 tagName = tagName || "*";
4872 if(typeof ns.getElementsByTagName != "undefined"){
4876 for(var i = 0, ni; ni = ns[i]; i++){
4877 cs = ni.getElementsByTagName(tagName);
4878 for(var j = 0, ci; ci = cs[j]; j++){
4882 }else if(mode == "/" || mode == ">"){
4883 var utag = tagName.toUpperCase();
4884 for(var i = 0, ni, cn; ni = ns[i]; i++){
4885 cn = ni.children || ni.childNodes;
4886 for(var j = 0, cj; cj = cn[j]; j++){
4887 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4892 }else if(mode == "+"){
4893 var utag = tagName.toUpperCase();
4894 for(var i = 0, n; n = ns[i]; i++){
4895 while((n = n.nextSibling) && n.nodeType != 1);
4896 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4900 }else if(mode == "~"){
4901 for(var i = 0, n; n = ns[i]; i++){
4902 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4911 function concat(a, b){
4915 for(var i = 0, l = b.length; i < l; i++){
4921 function byTag(cs, tagName){
4922 if(cs.tagName || cs == document){
4928 var r = [], ri = -1;
4929 tagName = tagName.toLowerCase();
4930 for(var i = 0, ci; ci = cs[i]; i++){
4931 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4938 function byId(cs, attr, id){
4939 if(cs.tagName || cs == document){
4945 var r = [], ri = -1;
4946 for(var i = 0,ci; ci = cs[i]; i++){
4947 if(ci && ci.id == id){
4955 function byAttribute(cs, attr, value, op, custom){
4956 var r = [], ri = -1, st = custom=="{";
4957 var f = Roo.DomQuery.operators[op];
4958 for(var i = 0, ci; ci = cs[i]; i++){
4961 a = Roo.DomQuery.getStyle(ci, attr);
4963 else if(attr == "class" || attr == "className"){
4965 }else if(attr == "for"){
4967 }else if(attr == "href"){
4968 a = ci.getAttribute("href", 2);
4970 a = ci.getAttribute(attr);
4972 if((f && f(a, value)) || (!f && a)){
4979 function byPseudo(cs, name, value){
4980 return Roo.DomQuery.pseudos[name](cs, value);
4983 // This is for IE MSXML which does not support expandos.
4984 // IE runs the same speed using setAttribute, however FF slows way down
4985 // and Safari completely fails so they need to continue to use expandos.
4986 var isIE = window.ActiveXObject ? true : false;
4988 // this eval is stop the compressor from
4989 // renaming the variable to something shorter
4991 /** eval:var:batch */
4996 function nodupIEXml(cs){
4998 cs[0].setAttribute("_nodup", d);
5000 for(var i = 1, len = cs.length; i < len; i++){
5002 if(!c.getAttribute("_nodup") != d){
5003 c.setAttribute("_nodup", d);
5007 for(var i = 0, len = cs.length; i < len; i++){
5008 cs[i].removeAttribute("_nodup");
5017 var len = cs.length, c, i, r = cs, cj, ri = -1;
5018 if(!len || typeof cs.nodeType != "undefined" || len == 1){
5021 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
5022 return nodupIEXml(cs);
5026 for(i = 1; c = cs[i]; i++){
5031 for(var j = 0; j < i; j++){
5034 for(j = i+1; cj = cs[j]; j++){
5046 function quickDiffIEXml(c1, c2){
5048 for(var i = 0, len = c1.length; i < len; i++){
5049 c1[i].setAttribute("_qdiff", d);
5052 for(var i = 0, len = c2.length; i < len; i++){
5053 if(c2[i].getAttribute("_qdiff") != d){
5054 r[r.length] = c2[i];
5057 for(var i = 0, len = c1.length; i < len; i++){
5058 c1[i].removeAttribute("_qdiff");
5063 function quickDiff(c1, c2){
5064 var len1 = c1.length;
5068 if(isIE && c1[0].selectSingleNode){
5069 return quickDiffIEXml(c1, c2);
5072 for(var i = 0; i < len1; i++){
5076 for(var i = 0, len = c2.length; i < len; i++){
5077 if(c2[i]._qdiff != d){
5078 r[r.length] = c2[i];
5084 function quickId(ns, mode, root, id){
5086 var d = root.ownerDocument || root;
5087 return d.getElementById(id);
5089 ns = getNodes(ns, mode, "*");
5090 return byId(ns, null, id);
5094 getStyle : function(el, name){
5095 return Roo.fly(el).getStyle(name);
5098 * Compiles a selector/xpath query into a reusable function. The returned function
5099 * takes one parameter "root" (optional), which is the context node from where the query should start.
5100 * @param {String} selector The selector/xpath query
5101 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5102 * @return {Function}
5104 compile : function(path, type){
5105 type = type || "select";
5107 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5108 var q = path, mode, lq;
5109 var tk = Roo.DomQuery.matchers;
5110 var tklen = tk.length;
5113 // accept leading mode switch
5114 var lmode = q.match(modeRe);
5115 if(lmode && lmode[1]){
5116 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5117 q = q.replace(lmode[1], "");
5119 // strip leading slashes
5120 while(path.substr(0, 1)=="/"){
5121 path = path.substr(1);
5124 while(q && lq != q){
5126 var tm = q.match(tagTokenRe);
5127 if(type == "select"){
5130 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5132 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5134 q = q.replace(tm[0], "");
5135 }else if(q.substr(0, 1) != '@'){
5136 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5141 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5143 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5145 q = q.replace(tm[0], "");
5148 while(!(mm = q.match(modeRe))){
5149 var matched = false;
5150 for(var j = 0; j < tklen; j++){
5152 var m = q.match(t.re);
5154 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5157 q = q.replace(m[0], "");
5162 // prevent infinite loop on bad selector
5164 throw 'Error parsing selector, parsing failed at "' + q + '"';
5168 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5169 q = q.replace(mm[1], "");
5172 fn[fn.length] = "return nodup(n);\n}";
5175 * list of variables that need from compression as they are used by eval.
5185 * eval:var:byClassName
5187 * eval:var:byAttribute
5188 * eval:var:attrValue
5196 * Selects a group of elements.
5197 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5198 * @param {Node} root (optional) The start of the query (defaults to document).
5201 select : function(path, root, type){
5202 if(!root || root == document){
5205 if(typeof root == "string"){
5206 root = document.getElementById(root);
5208 var paths = path.split(",");
5210 for(var i = 0, len = paths.length; i < len; i++){
5211 var p = paths[i].replace(trimRe, "");
5213 cache[p] = Roo.DomQuery.compile(p);
5215 throw p + " is not a valid selector";
5218 var result = cache[p](root);
5219 if(result && result != document){
5220 results = results.concat(result);
5223 if(paths.length > 1){
5224 return nodup(results);
5230 * Selects a single element.
5231 * @param {String} selector The selector/xpath query
5232 * @param {Node} root (optional) The start of the query (defaults to document).
5235 selectNode : function(path, root){
5236 return Roo.DomQuery.select(path, root)[0];
5240 * Selects the value of a node, optionally replacing null with the defaultValue.
5241 * @param {String} selector The selector/xpath query
5242 * @param {Node} root (optional) The start of the query (defaults to document).
5243 * @param {String} defaultValue
5245 selectValue : function(path, root, defaultValue){
5246 path = path.replace(trimRe, "");
5247 if(!valueCache[path]){
5248 valueCache[path] = Roo.DomQuery.compile(path, "select");
5250 var n = valueCache[path](root);
5251 n = n[0] ? n[0] : n;
5252 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5253 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5257 * Selects the value of a node, parsing integers and floats.
5258 * @param {String} selector The selector/xpath query
5259 * @param {Node} root (optional) The start of the query (defaults to document).
5260 * @param {Number} defaultValue
5263 selectNumber : function(path, root, defaultValue){
5264 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5265 return parseFloat(v);
5269 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5270 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5271 * @param {String} selector The simple selector to test
5274 is : function(el, ss){
5275 if(typeof el == "string"){
5276 el = document.getElementById(el);
5278 var isArray = (el instanceof Array);
5279 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5280 return isArray ? (result.length == el.length) : (result.length > 0);
5284 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5285 * @param {Array} el An array of elements to filter
5286 * @param {String} selector The simple selector to test
5287 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5288 * the selector instead of the ones that match
5291 filter : function(els, ss, nonMatches){
5292 ss = ss.replace(trimRe, "");
5293 if(!simpleCache[ss]){
5294 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5296 var result = simpleCache[ss](els);
5297 return nonMatches ? quickDiff(result, els) : result;
5301 * Collection of matching regular expressions and code snippets.
5305 select: 'n = byClassName(n, null, " {1} ");'
5307 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5308 select: 'n = byPseudo(n, "{1}", "{2}");'
5310 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5311 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5314 select: 'n = byId(n, null, "{1}");'
5317 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5322 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5323 * 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, > <.
5326 "=" : function(a, v){
5329 "!=" : function(a, v){
5332 "^=" : function(a, v){
5333 return a && a.substr(0, v.length) == v;
5335 "$=" : function(a, v){
5336 return a && a.substr(a.length-v.length) == v;
5338 "*=" : function(a, v){
5339 return a && a.indexOf(v) !== -1;
5341 "%=" : function(a, v){
5342 return (a % v) == 0;
5344 "|=" : function(a, v){
5345 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5347 "~=" : function(a, v){
5348 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5353 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5354 * and the argument (if any) supplied in the selector.
5357 "first-child" : function(c){
5358 var r = [], ri = -1, n;
5359 for(var i = 0, ci; ci = n = c[i]; i++){
5360 while((n = n.previousSibling) && n.nodeType != 1);
5368 "last-child" : function(c){
5369 var r = [], ri = -1, n;
5370 for(var i = 0, ci; ci = n = c[i]; i++){
5371 while((n = n.nextSibling) && n.nodeType != 1);
5379 "nth-child" : function(c, a) {
5380 var r = [], ri = -1;
5381 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5382 var f = (m[1] || 1) - 0, l = m[2] - 0;
5383 for(var i = 0, n; n = c[i]; i++){
5384 var pn = n.parentNode;
5385 if (batch != pn._batch) {
5387 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5388 if(cn.nodeType == 1){
5395 if (l == 0 || n.nodeIndex == l){
5398 } else if ((n.nodeIndex + l) % f == 0){
5406 "only-child" : function(c){
5407 var r = [], ri = -1;;
5408 for(var i = 0, ci; ci = c[i]; i++){
5409 if(!prev(ci) && !next(ci)){
5416 "empty" : function(c){
5417 var r = [], ri = -1;
5418 for(var i = 0, ci; ci = c[i]; i++){
5419 var cns = ci.childNodes, j = 0, cn, empty = true;
5422 if(cn.nodeType == 1 || cn.nodeType == 3){
5434 "contains" : function(c, v){
5435 var r = [], ri = -1;
5436 for(var i = 0, ci; ci = c[i]; i++){
5437 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5444 "nodeValue" : function(c, v){
5445 var r = [], ri = -1;
5446 for(var i = 0, ci; ci = c[i]; i++){
5447 if(ci.firstChild && ci.firstChild.nodeValue == v){
5454 "checked" : function(c){
5455 var r = [], ri = -1;
5456 for(var i = 0, ci; ci = c[i]; i++){
5457 if(ci.checked == true){
5464 "not" : function(c, ss){
5465 return Roo.DomQuery.filter(c, ss, true);
5468 "odd" : function(c){
5469 return this["nth-child"](c, "odd");
5472 "even" : function(c){
5473 return this["nth-child"](c, "even");
5476 "nth" : function(c, a){
5477 return c[a-1] || [];
5480 "first" : function(c){
5484 "last" : function(c){
5485 return c[c.length-1] || [];
5488 "has" : function(c, ss){
5489 var s = Roo.DomQuery.select;
5490 var r = [], ri = -1;
5491 for(var i = 0, ci; ci = c[i]; i++){
5492 if(s(ss, ci).length > 0){
5499 "next" : function(c, ss){
5500 var is = Roo.DomQuery.is;
5501 var r = [], ri = -1;
5502 for(var i = 0, ci; ci = c[i]; i++){
5511 "prev" : function(c, ss){
5512 var is = Roo.DomQuery.is;
5513 var r = [], ri = -1;
5514 for(var i = 0, ci; ci = c[i]; i++){
5527 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5528 * @param {String} path The selector/xpath query
5529 * @param {Node} root (optional) The start of the query (defaults to document).
5534 Roo.query = Roo.DomQuery.select;
5537 * Ext JS Library 1.1.1
5538 * Copyright(c) 2006-2007, Ext JS, LLC.
5540 * Originally Released Under LGPL - original licence link has changed is not relivant.
5543 * <script type="text/javascript">
5547 * @class Roo.util.Observable
5548 * Base class that provides a common interface for publishing events. Subclasses are expected to
5549 * to have a property "events" with all the events defined.<br>
5552 Employee = function(name){
5559 Roo.extend(Employee, Roo.util.Observable);
5561 * @param {Object} config properties to use (incuding events / listeners)
5564 Roo.util.Observable = function(cfg){
5567 this.addEvents(cfg.events || {});
5569 delete cfg.events; // make sure
5572 Roo.apply(this, cfg);
5575 this.on(this.listeners);
5576 delete this.listeners;
5579 Roo.util.Observable.prototype = {
5581 * @cfg {Object} listeners list of events and functions to call for this object,
5585 'click' : function(e) {
5595 * Fires the specified event with the passed parameters (minus the event name).
5596 * @param {String} eventName
5597 * @param {Object...} args Variable number of parameters are passed to handlers
5598 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5600 fireEvent : function(){
5601 var ce = this.events[arguments[0].toLowerCase()];
5602 if(typeof ce == "object"){
5603 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5610 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5613 * Appends an event handler to this component
5614 * @param {String} eventName The type of event to listen for
5615 * @param {Function} handler The method the event invokes
5616 * @param {Object} scope (optional) The scope in which to execute the handler
5617 * function. The handler function's "this" context.
5618 * @param {Object} options (optional) An object containing handler configuration
5619 * properties. This may contain any of the following properties:<ul>
5620 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5621 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5622 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5623 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5624 * by the specified number of milliseconds. If the event fires again within that time, the original
5625 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5628 * <b>Combining Options</b><br>
5629 * Using the options argument, it is possible to combine different types of listeners:<br>
5631 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5633 el.on('click', this.onClick, this, {
5640 * <b>Attaching multiple handlers in 1 call</b><br>
5641 * The method also allows for a single argument to be passed which is a config object containing properties
5642 * which specify multiple handlers.
5651 fn: this.onMouseOver,
5655 fn: this.onMouseOut,
5661 * Or a shorthand syntax which passes the same scope object to all handlers:
5664 'click': this.onClick,
5665 'mouseover': this.onMouseOver,
5666 'mouseout': this.onMouseOut,
5671 addListener : function(eventName, fn, scope, o){
5672 if(typeof eventName == "object"){
5675 if(this.filterOptRe.test(e)){
5678 if(typeof o[e] == "function"){
5680 this.addListener(e, o[e], o.scope, o);
5682 // individual options
5683 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5688 o = (!o || typeof o == "boolean") ? {} : o;
5689 eventName = eventName.toLowerCase();
5690 var ce = this.events[eventName] || true;
5691 if(typeof ce == "boolean"){
5692 ce = new Roo.util.Event(this, eventName);
5693 this.events[eventName] = ce;
5695 ce.addListener(fn, scope, o);
5699 * Removes a listener
5700 * @param {String} eventName The type of event to listen for
5701 * @param {Function} handler The handler to remove
5702 * @param {Object} scope (optional) The scope (this object) for the handler
5704 removeListener : function(eventName, fn, scope){
5705 var ce = this.events[eventName.toLowerCase()];
5706 if(typeof ce == "object"){
5707 ce.removeListener(fn, scope);
5712 * Removes all listeners for this object
5714 purgeListeners : function(){
5715 for(var evt in this.events){
5716 if(typeof this.events[evt] == "object"){
5717 this.events[evt].clearListeners();
5722 relayEvents : function(o, events){
5723 var createHandler = function(ename){
5725 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5728 for(var i = 0, len = events.length; i < len; i++){
5729 var ename = events[i];
5730 if(!this.events[ename]){ this.events[ename] = true; };
5731 o.on(ename, createHandler(ename), this);
5736 * Used to define events on this Observable
5737 * @param {Object} object The object with the events defined
5739 addEvents : function(o){
5743 Roo.applyIf(this.events, o);
5747 * Checks to see if this object has any listeners for a specified event
5748 * @param {String} eventName The name of the event to check for
5749 * @return {Boolean} True if the event is being listened for, else false
5751 hasListener : function(eventName){
5752 var e = this.events[eventName];
5753 return typeof e == "object" && e.listeners.length > 0;
5757 * Appends an event handler to this element (shorthand for addListener)
5758 * @param {String} eventName The type of event to listen for
5759 * @param {Function} handler The method the event invokes
5760 * @param {Object} scope (optional) The scope in which to execute the handler
5761 * function. The handler function's "this" context.
5762 * @param {Object} options (optional)
5765 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5767 * Removes a listener (shorthand for removeListener)
5768 * @param {String} eventName The type of event to listen for
5769 * @param {Function} handler The handler to remove
5770 * @param {Object} scope (optional) The scope (this object) for the handler
5773 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5776 * Starts capture on the specified Observable. All events will be passed
5777 * to the supplied function with the event name + standard signature of the event
5778 * <b>before</b> the event is fired. If the supplied function returns false,
5779 * the event will not fire.
5780 * @param {Observable} o The Observable to capture
5781 * @param {Function} fn The function to call
5782 * @param {Object} scope (optional) The scope (this object) for the fn
5785 Roo.util.Observable.capture = function(o, fn, scope){
5786 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5790 * Removes <b>all</b> added captures from the Observable.
5791 * @param {Observable} o The Observable to release
5794 Roo.util.Observable.releaseCapture = function(o){
5795 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5800 var createBuffered = function(h, o, scope){
5801 var task = new Roo.util.DelayedTask();
5803 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5807 var createSingle = function(h, e, fn, scope){
5809 e.removeListener(fn, scope);
5810 return h.apply(scope, arguments);
5814 var createDelayed = function(h, o, scope){
5816 var args = Array.prototype.slice.call(arguments, 0);
5817 setTimeout(function(){
5818 h.apply(scope, args);
5823 Roo.util.Event = function(obj, name){
5826 this.listeners = [];
5829 Roo.util.Event.prototype = {
5830 addListener : function(fn, scope, options){
5831 var o = options || {};
5832 scope = scope || this.obj;
5833 if(!this.isListening(fn, scope)){
5834 var l = {fn: fn, scope: scope, options: o};
5837 h = createDelayed(h, o, scope);
5840 h = createSingle(h, this, fn, scope);
5843 h = createBuffered(h, o, scope);
5846 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5847 this.listeners.push(l);
5849 this.listeners = this.listeners.slice(0);
5850 this.listeners.push(l);
5855 findListener : function(fn, scope){
5856 scope = scope || this.obj;
5857 var ls = this.listeners;
5858 for(var i = 0, len = ls.length; i < len; i++){
5860 if(l.fn == fn && l.scope == scope){
5867 isListening : function(fn, scope){
5868 return this.findListener(fn, scope) != -1;
5871 removeListener : function(fn, scope){
5873 if((index = this.findListener(fn, scope)) != -1){
5875 this.listeners.splice(index, 1);
5877 this.listeners = this.listeners.slice(0);
5878 this.listeners.splice(index, 1);
5885 clearListeners : function(){
5886 this.listeners = [];
5890 var ls = this.listeners, scope, len = ls.length;
5893 var args = Array.prototype.slice.call(arguments, 0);
5894 for(var i = 0; i < len; i++){
5896 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5897 this.firing = false;
5901 this.firing = false;
5908 * Ext JS Library 1.1.1
5909 * Copyright(c) 2006-2007, Ext JS, LLC.
5911 * Originally Released Under LGPL - original licence link has changed is not relivant.
5914 * <script type="text/javascript">
5918 * @class Roo.EventManager
5919 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5920 * several useful events directly.
5921 * See {@link Roo.EventObject} for more details on normalized event objects.
5924 Roo.EventManager = function(){
5925 var docReadyEvent, docReadyProcId, docReadyState = false;
5926 var resizeEvent, resizeTask, textEvent, textSize;
5927 var E = Roo.lib.Event;
5928 var D = Roo.lib.Dom;
5931 var fireDocReady = function(){
5933 docReadyState = true;
5936 clearInterval(docReadyProcId);
5938 if(Roo.isGecko || Roo.isOpera) {
5939 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5942 var defer = document.getElementById("ie-deferred-loader");
5944 defer.onreadystatechange = null;
5945 defer.parentNode.removeChild(defer);
5949 docReadyEvent.fire();
5950 docReadyEvent.clearListeners();
5955 var initDocReady = function(){
5956 docReadyEvent = new Roo.util.Event();
5957 if(Roo.isGecko || Roo.isOpera) {
5958 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5960 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5961 var defer = document.getElementById("ie-deferred-loader");
5962 defer.onreadystatechange = function(){
5963 if(this.readyState == "complete"){
5967 }else if(Roo.isSafari){
5968 docReadyProcId = setInterval(function(){
5969 var rs = document.readyState;
5970 if(rs == "complete") {
5975 // no matter what, make sure it fires on load
5976 E.on(window, "load", fireDocReady);
5979 var createBuffered = function(h, o){
5980 var task = new Roo.util.DelayedTask(h);
5982 // create new event object impl so new events don't wipe out properties
5983 e = new Roo.EventObjectImpl(e);
5984 task.delay(o.buffer, h, null, [e]);
5988 var createSingle = function(h, el, ename, fn){
5990 Roo.EventManager.removeListener(el, ename, fn);
5995 var createDelayed = function(h, o){
5997 // create new event object impl so new events don't wipe out properties
5998 e = new Roo.EventObjectImpl(e);
5999 setTimeout(function(){
6005 var listen = function(element, ename, opt, fn, scope){
6006 var o = (!opt || typeof opt == "boolean") ? {} : opt;
6007 fn = fn || o.fn; scope = scope || o.scope;
6008 var el = Roo.getDom(element);
6010 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
6012 var h = function(e){
6013 e = Roo.EventObject.setEvent(e);
6016 t = e.getTarget(o.delegate, el);
6023 if(o.stopEvent === true){
6026 if(o.preventDefault === true){
6029 if(o.stopPropagation === true){
6030 e.stopPropagation();
6033 if(o.normalized === false){
6037 fn.call(scope || el, e, t, o);
6040 h = createDelayed(h, o);
6043 h = createSingle(h, el, ename, fn);
6046 h = createBuffered(h, o);
6048 fn._handlers = fn._handlers || [];
6049 fn._handlers.push([Roo.id(el), ename, h]);
6052 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
6053 el.addEventListener("DOMMouseScroll", h, false);
6054 E.on(window, 'unload', function(){
6055 el.removeEventListener("DOMMouseScroll", h, false);
6058 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6059 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6064 var stopListening = function(el, ename, fn){
6065 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6067 for(var i = 0, len = hds.length; i < len; i++){
6069 if(h[0] == id && h[1] == ename){
6076 E.un(el, ename, hd);
6077 el = Roo.getDom(el);
6078 if(ename == "mousewheel" && el.addEventListener){
6079 el.removeEventListener("DOMMouseScroll", hd, false);
6081 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6082 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6086 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6093 * @scope Roo.EventManager
6098 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6099 * object with a Roo.EventObject
6100 * @param {Function} fn The method the event invokes
6101 * @param {Object} scope An object that becomes the scope of the handler
6102 * @param {boolean} override If true, the obj passed in becomes
6103 * the execution scope of the listener
6104 * @return {Function} The wrapped function
6107 wrap : function(fn, scope, override){
6109 Roo.EventObject.setEvent(e);
6110 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6115 * Appends an event handler to an element (shorthand for addListener)
6116 * @param {String/HTMLElement} element The html element or id to assign the
6117 * @param {String} eventName The type of event to listen for
6118 * @param {Function} handler The method the event invokes
6119 * @param {Object} scope (optional) The scope in which to execute the handler
6120 * function. The handler function's "this" context.
6121 * @param {Object} options (optional) An object containing handler configuration
6122 * properties. This may contain any of the following properties:<ul>
6123 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6124 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6125 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6126 * <li>preventDefault {Boolean} True to prevent the default action</li>
6127 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6128 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6129 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6130 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6131 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6132 * by the specified number of milliseconds. If the event fires again within that time, the original
6133 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6136 * <b>Combining Options</b><br>
6137 * Using the options argument, it is possible to combine different types of listeners:<br>
6139 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6141 el.on('click', this.onClick, this, {
6148 * <b>Attaching multiple handlers in 1 call</b><br>
6149 * The method also allows for a single argument to be passed which is a config object containing properties
6150 * which specify multiple handlers.
6160 fn: this.onMouseOver
6169 * Or a shorthand syntax:<br>
6172 'click' : this.onClick,
6173 'mouseover' : this.onMouseOver,
6174 'mouseout' : this.onMouseOut
6178 addListener : function(element, eventName, fn, scope, options){
6179 if(typeof eventName == "object"){
6185 if(typeof o[e] == "function"){
6187 listen(element, e, o, o[e], o.scope);
6189 // individual options
6190 listen(element, e, o[e]);
6195 return listen(element, eventName, options, fn, scope);
6199 * Removes an event handler
6201 * @param {String/HTMLElement} element The id or html element to remove the
6203 * @param {String} eventName The type of event
6204 * @param {Function} fn
6205 * @return {Boolean} True if a listener was actually removed
6207 removeListener : function(element, eventName, fn){
6208 return stopListening(element, eventName, fn);
6212 * Fires when the document is ready (before onload and before images are loaded). Can be
6213 * accessed shorthanded Roo.onReady().
6214 * @param {Function} fn The method the event invokes
6215 * @param {Object} scope An object that becomes the scope of the handler
6216 * @param {boolean} options
6218 onDocumentReady : function(fn, scope, options){
6219 if(docReadyState){ // if it already fired
6220 docReadyEvent.addListener(fn, scope, options);
6221 docReadyEvent.fire();
6222 docReadyEvent.clearListeners();
6228 docReadyEvent.addListener(fn, scope, options);
6232 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
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 onWindowResize : function(fn, scope, options){
6239 resizeEvent = new Roo.util.Event();
6240 resizeTask = new Roo.util.DelayedTask(function(){
6241 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6243 E.on(window, "resize", function(){
6245 resizeTask.delay(50);
6247 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6251 resizeEvent.addListener(fn, scope, options);
6255 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6256 * @param {Function} fn The method the event invokes
6257 * @param {Object} scope An object that becomes the scope of the handler
6258 * @param {boolean} options
6260 onTextResize : function(fn, scope, options){
6262 textEvent = new Roo.util.Event();
6263 var textEl = new Roo.Element(document.createElement('div'));
6264 textEl.dom.className = 'x-text-resize';
6265 textEl.dom.innerHTML = 'X';
6266 textEl.appendTo(document.body);
6267 textSize = textEl.dom.offsetHeight;
6268 setInterval(function(){
6269 if(textEl.dom.offsetHeight != textSize){
6270 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6272 }, this.textResizeInterval);
6274 textEvent.addListener(fn, scope, options);
6278 * Removes the passed window resize listener.
6279 * @param {Function} fn The method the event invokes
6280 * @param {Object} scope The scope of handler
6282 removeResizeListener : function(fn, scope){
6284 resizeEvent.removeListener(fn, scope);
6289 fireResize : function(){
6291 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6295 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6299 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6301 textResizeInterval : 50
6306 * @scopeAlias pub=Roo.EventManager
6310 * Appends an event handler to an element (shorthand for addListener)
6311 * @param {String/HTMLElement} element The html element or id to assign the
6312 * @param {String} eventName The type of event to listen for
6313 * @param {Function} handler The method the event invokes
6314 * @param {Object} scope (optional) The scope in which to execute the handler
6315 * function. The handler function's "this" context.
6316 * @param {Object} options (optional) An object containing handler configuration
6317 * properties. This may contain any of the following properties:<ul>
6318 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6319 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6320 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6321 * <li>preventDefault {Boolean} True to prevent the default action</li>
6322 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6323 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6324 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6325 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6326 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6327 * by the specified number of milliseconds. If the event fires again within that time, the original
6328 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6331 * <b>Combining Options</b><br>
6332 * Using the options argument, it is possible to combine different types of listeners:<br>
6334 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6336 el.on('click', this.onClick, this, {
6343 * <b>Attaching multiple handlers in 1 call</b><br>
6344 * The method also allows for a single argument to be passed which is a config object containing properties
6345 * which specify multiple handlers.
6355 fn: this.onMouseOver
6364 * Or a shorthand syntax:<br>
6367 'click' : this.onClick,
6368 'mouseover' : this.onMouseOver,
6369 'mouseout' : this.onMouseOut
6373 pub.on = pub.addListener;
6374 pub.un = pub.removeListener;
6376 pub.stoppedMouseDownEvent = new Roo.util.Event();
6380 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6381 * @param {Function} fn The method the event invokes
6382 * @param {Object} scope An object that becomes the scope of the handler
6383 * @param {boolean} override If true, the obj passed in becomes
6384 * the execution scope of the listener
6388 Roo.onReady = Roo.EventManager.onDocumentReady;
6390 Roo.onReady(function(){
6391 var bd = Roo.get(document.body);
6396 : Roo.isGecko ? "roo-gecko"
6397 : Roo.isOpera ? "roo-opera"
6398 : Roo.isSafari ? "roo-safari" : ""];
6401 cls.push("roo-mac");
6404 cls.push("roo-linux");
6406 if(Roo.isBorderBox){
6407 cls.push('roo-border-box');
6409 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6410 var p = bd.dom.parentNode;
6412 p.className += ' roo-strict';
6415 bd.addClass(cls.join(' '));
6419 * @class Roo.EventObject
6420 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6421 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6424 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6426 var target = e.getTarget();
6429 var myDiv = Roo.get("myDiv");
6430 myDiv.on("click", handleClick);
6432 Roo.EventManager.on("myDiv", 'click', handleClick);
6433 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6437 Roo.EventObject = function(){
6439 var E = Roo.lib.Event;
6441 // safari keypress events for special keys return bad keycodes
6444 63235 : 39, // right
6447 63276 : 33, // page up
6448 63277 : 34, // page down
6449 63272 : 46, // delete
6454 // normalize button clicks
6455 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6456 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6458 Roo.EventObjectImpl = function(e){
6460 this.setEvent(e.browserEvent || e);
6463 Roo.EventObjectImpl.prototype = {
6465 * Used to fix doc tools.
6466 * @scope Roo.EventObject.prototype
6472 /** The normal browser event */
6473 browserEvent : null,
6474 /** The button pressed in a mouse event */
6476 /** True if the shift key was down during the event */
6478 /** True if the control key was down during the event */
6480 /** True if the alt key was down during the event */
6539 setEvent : function(e){
6540 if(e == this || (e && e.browserEvent)){ // already wrapped
6543 this.browserEvent = e;
6545 // normalize buttons
6546 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6547 if(e.type == 'click' && this.button == -1){
6551 this.shiftKey = e.shiftKey;
6552 // mac metaKey behaves like ctrlKey
6553 this.ctrlKey = e.ctrlKey || e.metaKey;
6554 this.altKey = e.altKey;
6555 // in getKey these will be normalized for the mac
6556 this.keyCode = e.keyCode;
6557 // keyup warnings on firefox.
6558 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6559 // cache the target for the delayed and or buffered events
6560 this.target = E.getTarget(e);
6562 this.xy = E.getXY(e);
6565 this.shiftKey = false;
6566 this.ctrlKey = false;
6567 this.altKey = false;
6577 * Stop the event (preventDefault and stopPropagation)
6579 stopEvent : function(){
6580 if(this.browserEvent){
6581 if(this.browserEvent.type == 'mousedown'){
6582 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6584 E.stopEvent(this.browserEvent);
6589 * Prevents the browsers default handling of the event.
6591 preventDefault : function(){
6592 if(this.browserEvent){
6593 E.preventDefault(this.browserEvent);
6598 isNavKeyPress : function(){
6599 var k = this.keyCode;
6600 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6601 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6604 isSpecialKey : function(){
6605 var k = this.keyCode;
6606 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6607 (k == 16) || (k == 17) ||
6608 (k >= 18 && k <= 20) ||
6609 (k >= 33 && k <= 35) ||
6610 (k >= 36 && k <= 39) ||
6611 (k >= 44 && k <= 45);
6614 * Cancels bubbling of the event.
6616 stopPropagation : function(){
6617 if(this.browserEvent){
6618 if(this.type == 'mousedown'){
6619 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6621 E.stopPropagation(this.browserEvent);
6626 * Gets the key code for the event.
6629 getCharCode : function(){
6630 return this.charCode || this.keyCode;
6634 * Returns a normalized keyCode for the event.
6635 * @return {Number} The key code
6637 getKey : function(){
6638 var k = this.keyCode || this.charCode;
6639 return Roo.isSafari ? (safariKeys[k] || k) : k;
6643 * Gets the x coordinate of the event.
6646 getPageX : function(){
6651 * Gets the y coordinate of the event.
6654 getPageY : function(){
6659 * Gets the time of the event.
6662 getTime : function(){
6663 if(this.browserEvent){
6664 return E.getTime(this.browserEvent);
6670 * Gets the page coordinates of the event.
6671 * @return {Array} The xy values like [x, y]
6678 * Gets the target for the event.
6679 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6680 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6681 search as a number or element (defaults to 10 || document.body)
6682 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6683 * @return {HTMLelement}
6685 getTarget : function(selector, maxDepth, returnEl){
6686 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6689 * Gets the related target.
6690 * @return {HTMLElement}
6692 getRelatedTarget : function(){
6693 if(this.browserEvent){
6694 return E.getRelatedTarget(this.browserEvent);
6700 * Normalizes mouse wheel delta across browsers
6701 * @return {Number} The delta
6703 getWheelDelta : function(){
6704 var e = this.browserEvent;
6706 if(e.wheelDelta){ /* IE/Opera. */
6707 delta = e.wheelDelta/120;
6708 }else if(e.detail){ /* Mozilla case. */
6709 delta = -e.detail/3;
6715 * Returns true if the control, meta, shift or alt key was pressed during this event.
6718 hasModifier : function(){
6719 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6723 * Returns true if the target of this event equals el or is a child of el
6724 * @param {String/HTMLElement/Element} el
6725 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6728 within : function(el, related){
6729 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6730 return t && Roo.fly(el).contains(t);
6733 getPoint : function(){
6734 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6738 return new Roo.EventObjectImpl();
6743 * Ext JS Library 1.1.1
6744 * Copyright(c) 2006-2007, Ext JS, LLC.
6746 * Originally Released Under LGPL - original licence link has changed is not relivant.
6749 * <script type="text/javascript">
6753 // was in Composite Element!??!?!
6756 var D = Roo.lib.Dom;
6757 var E = Roo.lib.Event;
6758 var A = Roo.lib.Anim;
6760 // local style camelizing for speed
6762 var camelRe = /(-[a-z])/gi;
6763 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6764 var view = document.defaultView;
6767 * @class Roo.Element
6768 * Represents an Element in the DOM.<br><br>
6771 var el = Roo.get("my-div");
6774 var el = getEl("my-div");
6776 // or with a DOM element
6777 var el = Roo.get(myDivElement);
6779 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6780 * each call instead of constructing a new one.<br><br>
6781 * <b>Animations</b><br />
6782 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6783 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6785 Option Default Description
6786 --------- -------- ---------------------------------------------
6787 duration .35 The duration of the animation in seconds
6788 easing easeOut The YUI easing method
6789 callback none A function to execute when the anim completes
6790 scope this The scope (this) of the callback function
6792 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6793 * manipulate the animation. Here's an example:
6795 var el = Roo.get("my-div");
6800 // default animation
6801 el.setWidth(100, true);
6803 // animation with some options set
6810 // using the "anim" property to get the Anim object
6816 el.setWidth(100, opt);
6818 if(opt.anim.isAnimated()){
6822 * <b> Composite (Collections of) Elements</b><br />
6823 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6824 * @constructor Create a new Element directly.
6825 * @param {String/HTMLElement} element
6826 * @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).
6828 Roo.Element = function(element, forceNew){
6829 var dom = typeof element == "string" ?
6830 document.getElementById(element) : element;
6831 if(!dom){ // invalid id/element
6835 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6836 return Roo.Element.cache[id];
6846 * The DOM element ID
6849 this.id = id || Roo.id(dom);
6852 var El = Roo.Element;
6856 * The element's default display mode (defaults to "")
6859 originalDisplay : "",
6863 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6868 * Sets the element's visibility mode. When setVisible() is called it
6869 * will use this to determine whether to set the visibility or the display property.
6870 * @param visMode Element.VISIBILITY or Element.DISPLAY
6871 * @return {Roo.Element} this
6873 setVisibilityMode : function(visMode){
6874 this.visibilityMode = visMode;
6878 * Convenience method for setVisibilityMode(Element.DISPLAY)
6879 * @param {String} display (optional) What to set display to when visible
6880 * @return {Roo.Element} this
6882 enableDisplayMode : function(display){
6883 this.setVisibilityMode(El.DISPLAY);
6884 if(typeof display != "undefined") this.originalDisplay = display;
6889 * 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)
6890 * @param {String} selector The simple selector to test
6891 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6892 search as a number or element (defaults to 10 || document.body)
6893 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6894 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6896 findParent : function(simpleSelector, maxDepth, returnEl){
6897 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6898 maxDepth = maxDepth || 50;
6899 if(typeof maxDepth != "number"){
6900 stopEl = Roo.getDom(maxDepth);
6903 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6904 if(dq.is(p, simpleSelector)){
6905 return returnEl ? Roo.get(p) : p;
6915 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6916 * @param {String} selector The simple selector to test
6917 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6918 search as a number or element (defaults to 10 || document.body)
6919 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6920 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6922 findParentNode : function(simpleSelector, maxDepth, returnEl){
6923 var p = Roo.fly(this.dom.parentNode, '_internal');
6924 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6928 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6929 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6930 * @param {String} selector The simple selector to test
6931 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6932 search as a number or element (defaults to 10 || document.body)
6933 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6935 up : function(simpleSelector, maxDepth){
6936 return this.findParentNode(simpleSelector, maxDepth, true);
6942 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6943 * @param {String} selector The simple selector to test
6944 * @return {Boolean} True if this element matches the selector, else false
6946 is : function(simpleSelector){
6947 return Roo.DomQuery.is(this.dom, simpleSelector);
6951 * Perform animation on this element.
6952 * @param {Object} args The YUI animation control args
6953 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6954 * @param {Function} onComplete (optional) Function to call when animation completes
6955 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6956 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6957 * @return {Roo.Element} this
6959 animate : function(args, duration, onComplete, easing, animType){
6960 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6965 * @private Internal animation call
6967 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6968 animType = animType || 'run';
6970 var anim = Roo.lib.Anim[animType](
6972 (opt.duration || defaultDur) || .35,
6973 (opt.easing || defaultEase) || 'easeOut',
6975 Roo.callback(cb, this);
6976 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6984 // private legacy anim prep
6985 preanim : function(a, i){
6986 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6990 * Removes worthless text nodes
6991 * @param {Boolean} forceReclean (optional) By default the element
6992 * keeps track if it has been cleaned already so
6993 * you can call this over and over. However, if you update the element and
6994 * need to force a reclean, you can pass true.
6996 clean : function(forceReclean){
6997 if(this.isCleaned && forceReclean !== true){
7001 var d = this.dom, n = d.firstChild, ni = -1;
7003 var nx = n.nextSibling;
7004 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
7011 this.isCleaned = true;
7016 calcOffsetsTo : function(el){
7019 var restorePos = false;
7020 if(el.getStyle('position') == 'static'){
7021 el.position('relative');
7026 while(op && op != d && op.tagName != 'HTML'){
7029 op = op.offsetParent;
7032 el.position('static');
7038 * Scrolls this element into view within the passed container.
7039 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
7040 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
7041 * @return {Roo.Element} this
7043 scrollIntoView : function(container, hscroll){
7044 var c = Roo.getDom(container) || document.body;
7047 var o = this.calcOffsetsTo(c),
7050 b = t+el.offsetHeight,
7051 r = l+el.offsetWidth;
7053 var ch = c.clientHeight;
7054 var ct = parseInt(c.scrollTop, 10);
7055 var cl = parseInt(c.scrollLeft, 10);
7057 var cr = cl + c.clientWidth;
7065 if(hscroll !== false){
7069 c.scrollLeft = r-c.clientWidth;
7076 scrollChildIntoView : function(child, hscroll){
7077 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7081 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7082 * the new height may not be available immediately.
7083 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7084 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7085 * @param {Function} onComplete (optional) Function to call when animation completes
7086 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7087 * @return {Roo.Element} this
7089 autoHeight : function(animate, duration, onComplete, easing){
7090 var oldHeight = this.getHeight();
7092 this.setHeight(1); // force clipping
7093 setTimeout(function(){
7094 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7096 this.setHeight(height);
7098 if(typeof onComplete == "function"){
7102 this.setHeight(oldHeight); // restore original height
7103 this.setHeight(height, animate, duration, function(){
7105 if(typeof onComplete == "function") onComplete();
7106 }.createDelegate(this), easing);
7108 }.createDelegate(this), 0);
7113 * Returns true if this element is an ancestor of the passed element
7114 * @param {HTMLElement/String} el The element to check
7115 * @return {Boolean} True if this element is an ancestor of el, else false
7117 contains : function(el){
7118 if(!el){return false;}
7119 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7123 * Checks whether the element is currently visible using both visibility and display properties.
7124 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7125 * @return {Boolean} True if the element is currently visible, else false
7127 isVisible : function(deep) {
7128 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7129 if(deep !== true || !vis){
7132 var p = this.dom.parentNode;
7133 while(p && p.tagName.toLowerCase() != "body"){
7134 if(!Roo.fly(p, '_isVisible').isVisible()){
7143 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7144 * @param {String} selector The CSS selector
7145 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7146 * @return {CompositeElement/CompositeElementLite} The composite element
7148 select : function(selector, unique){
7149 return El.select(selector, unique, this.dom);
7153 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7154 * @param {String} selector The CSS selector
7155 * @return {Array} An array of the matched nodes
7157 query : function(selector, unique){
7158 return Roo.DomQuery.select(selector, this.dom);
7162 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7163 * @param {String} selector The CSS selector
7164 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7165 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7167 child : function(selector, returnDom){
7168 var n = Roo.DomQuery.selectNode(selector, this.dom);
7169 return returnDom ? n : Roo.get(n);
7173 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7174 * @param {String} selector The CSS selector
7175 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7176 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7178 down : function(selector, returnDom){
7179 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7180 return returnDom ? n : Roo.get(n);
7184 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7185 * @param {String} group The group the DD object is member of
7186 * @param {Object} config The DD config object
7187 * @param {Object} overrides An object containing methods to override/implement on the DD object
7188 * @return {Roo.dd.DD} The DD object
7190 initDD : function(group, config, overrides){
7191 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7192 return Roo.apply(dd, overrides);
7196 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7197 * @param {String} group The group the DDProxy object is member of
7198 * @param {Object} config The DDProxy config object
7199 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7200 * @return {Roo.dd.DDProxy} The DDProxy object
7202 initDDProxy : function(group, config, overrides){
7203 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7204 return Roo.apply(dd, overrides);
7208 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7209 * @param {String} group The group the DDTarget object is member of
7210 * @param {Object} config The DDTarget config object
7211 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7212 * @return {Roo.dd.DDTarget} The DDTarget object
7214 initDDTarget : function(group, config, overrides){
7215 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7216 return Roo.apply(dd, overrides);
7220 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7221 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7222 * @param {Boolean} visible Whether the element is visible
7223 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7224 * @return {Roo.Element} this
7226 setVisible : function(visible, animate){
7228 if(this.visibilityMode == El.DISPLAY){
7229 this.setDisplayed(visible);
7232 this.dom.style.visibility = visible ? "visible" : "hidden";
7235 // closure for composites
7237 var visMode = this.visibilityMode;
7239 this.setOpacity(.01);
7240 this.setVisible(true);
7242 this.anim({opacity: { to: (visible?1:0) }},
7243 this.preanim(arguments, 1),
7244 null, .35, 'easeIn', function(){
7246 if(visMode == El.DISPLAY){
7247 dom.style.display = "none";
7249 dom.style.visibility = "hidden";
7251 Roo.get(dom).setOpacity(1);
7259 * Returns true if display is not "none"
7262 isDisplayed : function() {
7263 return this.getStyle("display") != "none";
7267 * Toggles the element's visibility or display, depending on visibility mode.
7268 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7269 * @return {Roo.Element} this
7271 toggle : function(animate){
7272 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7277 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7278 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7279 * @return {Roo.Element} this
7281 setDisplayed : function(value) {
7282 if(typeof value == "boolean"){
7283 value = value ? this.originalDisplay : "none";
7285 this.setStyle("display", value);
7290 * Tries to focus the element. Any exceptions are caught and ignored.
7291 * @return {Roo.Element} this
7293 focus : function() {
7301 * Tries to blur the element. Any exceptions are caught and ignored.
7302 * @return {Roo.Element} this
7312 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7313 * @param {String/Array} className The CSS class to add, or an array of classes
7314 * @return {Roo.Element} this
7316 addClass : function(className){
7317 if(className instanceof Array){
7318 for(var i = 0, len = className.length; i < len; i++) {
7319 this.addClass(className[i]);
7322 if(className && !this.hasClass(className)){
7323 this.dom.className = this.dom.className + " " + className;
7330 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7331 * @param {String/Array} className The CSS class to add, or an array of classes
7332 * @return {Roo.Element} this
7334 radioClass : function(className){
7335 var siblings = this.dom.parentNode.childNodes;
7336 for(var i = 0; i < siblings.length; i++) {
7337 var s = siblings[i];
7338 if(s.nodeType == 1){
7339 Roo.get(s).removeClass(className);
7342 this.addClass(className);
7347 * Removes one or more CSS classes from the element.
7348 * @param {String/Array} className The CSS class to remove, or an array of classes
7349 * @return {Roo.Element} this
7351 removeClass : function(className){
7352 if(!className || !this.dom.className){
7355 if(className instanceof Array){
7356 for(var i = 0, len = className.length; i < len; i++) {
7357 this.removeClass(className[i]);
7360 if(this.hasClass(className)){
7361 var re = this.classReCache[className];
7363 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7364 this.classReCache[className] = re;
7366 this.dom.className =
7367 this.dom.className.replace(re, " ");
7377 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7378 * @param {String} className The CSS class to toggle
7379 * @return {Roo.Element} this
7381 toggleClass : function(className){
7382 if(this.hasClass(className)){
7383 this.removeClass(className);
7385 this.addClass(className);
7391 * Checks if the specified CSS class exists on this element's DOM node.
7392 * @param {String} className The CSS class to check for
7393 * @return {Boolean} True if the class exists, else false
7395 hasClass : function(className){
7396 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7400 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7401 * @param {String} oldClassName The CSS class to replace
7402 * @param {String} newClassName The replacement CSS class
7403 * @return {Roo.Element} this
7405 replaceClass : function(oldClassName, newClassName){
7406 this.removeClass(oldClassName);
7407 this.addClass(newClassName);
7412 * Returns an object with properties matching the styles requested.
7413 * For example, el.getStyles('color', 'font-size', 'width') might return
7414 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7415 * @param {String} style1 A style name
7416 * @param {String} style2 A style name
7417 * @param {String} etc.
7418 * @return {Object} The style object
7420 getStyles : function(){
7421 var a = arguments, len = a.length, r = {};
7422 for(var i = 0; i < len; i++){
7423 r[a[i]] = this.getStyle(a[i]);
7429 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7430 * @param {String} property The style property whose value is returned.
7431 * @return {String} The current value of the style property for this element.
7433 getStyle : function(){
7434 return view && view.getComputedStyle ?
7436 var el = this.dom, v, cs, camel;
7437 if(prop == 'float'){
7440 if(el.style && (v = el.style[prop])){
7443 if(cs = view.getComputedStyle(el, "")){
7444 if(!(camel = propCache[prop])){
7445 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7452 var el = this.dom, v, cs, camel;
7453 if(prop == 'opacity'){
7454 if(typeof el.style.filter == 'string'){
7455 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7457 var fv = parseFloat(m[1]);
7459 return fv ? fv / 100 : 0;
7464 }else if(prop == 'float'){
7465 prop = "styleFloat";
7467 if(!(camel = propCache[prop])){
7468 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7470 if(v = el.style[camel]){
7473 if(cs = el.currentStyle){
7481 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7482 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7483 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7484 * @return {Roo.Element} this
7486 setStyle : function(prop, value){
7487 if(typeof prop == "string"){
7489 if (prop == 'float') {
7490 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7495 if(!(camel = propCache[prop])){
7496 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7499 if(camel == 'opacity') {
7500 this.setOpacity(value);
7502 this.dom.style[camel] = value;
7505 for(var style in prop){
7506 if(typeof prop[style] != "function"){
7507 this.setStyle(style, prop[style]);
7515 * More flexible version of {@link #setStyle} for setting style properties.
7516 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7517 * a function which returns such a specification.
7518 * @return {Roo.Element} this
7520 applyStyles : function(style){
7521 Roo.DomHelper.applyStyles(this.dom, style);
7526 * 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).
7527 * @return {Number} The X position of the element
7530 return D.getX(this.dom);
7534 * 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).
7535 * @return {Number} The Y position of the element
7538 return D.getY(this.dom);
7542 * 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).
7543 * @return {Array} The XY position of the element
7546 return D.getXY(this.dom);
7550 * 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).
7551 * @param {Number} The X position of the element
7552 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7553 * @return {Roo.Element} this
7555 setX : function(x, animate){
7557 D.setX(this.dom, x);
7559 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7565 * 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).
7566 * @param {Number} The Y position of the element
7567 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7568 * @return {Roo.Element} this
7570 setY : function(y, animate){
7572 D.setY(this.dom, y);
7574 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7580 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7581 * @param {String} left The left CSS property value
7582 * @return {Roo.Element} this
7584 setLeft : function(left){
7585 this.setStyle("left", this.addUnits(left));
7590 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7591 * @param {String} top The top CSS property value
7592 * @return {Roo.Element} this
7594 setTop : function(top){
7595 this.setStyle("top", this.addUnits(top));
7600 * Sets the element's CSS right style.
7601 * @param {String} right The right CSS property value
7602 * @return {Roo.Element} this
7604 setRight : function(right){
7605 this.setStyle("right", this.addUnits(right));
7610 * Sets the element's CSS bottom style.
7611 * @param {String} bottom The bottom CSS property value
7612 * @return {Roo.Element} this
7614 setBottom : function(bottom){
7615 this.setStyle("bottom", this.addUnits(bottom));
7620 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7621 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7622 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7623 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7624 * @return {Roo.Element} this
7626 setXY : function(pos, animate){
7628 D.setXY(this.dom, pos);
7630 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7636 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7637 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7638 * @param {Number} x X value for new position (coordinates are page-based)
7639 * @param {Number} y Y value for new position (coordinates are page-based)
7640 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7641 * @return {Roo.Element} this
7643 setLocation : function(x, y, animate){
7644 this.setXY([x, y], this.preanim(arguments, 2));
7649 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7650 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7651 * @param {Number} x X value for new position (coordinates are page-based)
7652 * @param {Number} y Y value for new position (coordinates are page-based)
7653 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7654 * @return {Roo.Element} this
7656 moveTo : function(x, y, animate){
7657 this.setXY([x, y], this.preanim(arguments, 2));
7662 * Returns the region of the given element.
7663 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7664 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7666 getRegion : function(){
7667 return D.getRegion(this.dom);
7671 * Returns the offset height of the element
7672 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7673 * @return {Number} The element's height
7675 getHeight : function(contentHeight){
7676 var h = this.dom.offsetHeight || 0;
7677 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7681 * Returns the offset width of the element
7682 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7683 * @return {Number} The element's width
7685 getWidth : function(contentWidth){
7686 var w = this.dom.offsetWidth || 0;
7687 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7691 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7692 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7693 * if a height has not been set using CSS.
7696 getComputedHeight : function(){
7697 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7699 h = parseInt(this.getStyle('height'), 10) || 0;
7700 if(!this.isBorderBox()){
7701 h += this.getFrameWidth('tb');
7708 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7709 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7710 * if a width has not been set using CSS.
7713 getComputedWidth : function(){
7714 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7716 w = parseInt(this.getStyle('width'), 10) || 0;
7717 if(!this.isBorderBox()){
7718 w += this.getFrameWidth('lr');
7725 * Returns the size of the element.
7726 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7727 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7729 getSize : function(contentSize){
7730 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7734 * Returns the width and height of the viewport.
7735 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7737 getViewSize : function(){
7738 var d = this.dom, doc = document, aw = 0, ah = 0;
7739 if(d == doc || d == doc.body){
7740 return {width : D.getViewWidth(), height: D.getViewHeight()};
7743 width : d.clientWidth,
7744 height: d.clientHeight
7750 * Returns the value of the "value" attribute
7751 * @param {Boolean} asNumber true to parse the value as a number
7752 * @return {String/Number}
7754 getValue : function(asNumber){
7755 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7759 adjustWidth : function(width){
7760 if(typeof width == "number"){
7761 if(this.autoBoxAdjust && !this.isBorderBox()){
7762 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7772 adjustHeight : function(height){
7773 if(typeof height == "number"){
7774 if(this.autoBoxAdjust && !this.isBorderBox()){
7775 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7785 * Set the width of the element
7786 * @param {Number} width The new width
7787 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7788 * @return {Roo.Element} this
7790 setWidth : function(width, animate){
7791 width = this.adjustWidth(width);
7793 this.dom.style.width = this.addUnits(width);
7795 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7801 * Set the height of the element
7802 * @param {Number} height The new height
7803 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7804 * @return {Roo.Element} this
7806 setHeight : function(height, animate){
7807 height = this.adjustHeight(height);
7809 this.dom.style.height = this.addUnits(height);
7811 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7817 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7818 * @param {Number} width The new width
7819 * @param {Number} height The new height
7820 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7821 * @return {Roo.Element} this
7823 setSize : function(width, height, animate){
7824 if(typeof width == "object"){ // in case of object from getSize()
7825 height = width.height; width = width.width;
7827 width = this.adjustWidth(width); height = this.adjustHeight(height);
7829 this.dom.style.width = this.addUnits(width);
7830 this.dom.style.height = this.addUnits(height);
7832 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7838 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7839 * @param {Number} x X value for new position (coordinates are page-based)
7840 * @param {Number} y Y value for new position (coordinates are page-based)
7841 * @param {Number} width The new width
7842 * @param {Number} height The new height
7843 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7844 * @return {Roo.Element} this
7846 setBounds : function(x, y, width, height, animate){
7848 this.setSize(width, height);
7849 this.setLocation(x, y);
7851 width = this.adjustWidth(width); height = this.adjustHeight(height);
7852 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7853 this.preanim(arguments, 4), 'motion');
7859 * 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.
7860 * @param {Roo.lib.Region} region The region to fill
7861 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7862 * @return {Roo.Element} this
7864 setRegion : function(region, animate){
7865 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7870 * Appends an event handler
7872 * @param {String} eventName The type of event to append
7873 * @param {Function} fn The method the event invokes
7874 * @param {Object} scope (optional) The scope (this object) of the fn
7875 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7877 addListener : function(eventName, fn, scope, options){
7879 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7884 * Removes an event handler from this element
7885 * @param {String} eventName the type of event to remove
7886 * @param {Function} fn the method the event invokes
7887 * @return {Roo.Element} this
7889 removeListener : function(eventName, fn){
7890 Roo.EventManager.removeListener(this.dom, eventName, fn);
7895 * Removes all previous added listeners from this element
7896 * @return {Roo.Element} this
7898 removeAllListeners : function(){
7899 E.purgeElement(this.dom);
7903 relayEvent : function(eventName, observable){
7904 this.on(eventName, function(e){
7905 observable.fireEvent(eventName, e);
7910 * Set the opacity of the element
7911 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7912 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7913 * @return {Roo.Element} this
7915 setOpacity : function(opacity, animate){
7917 var s = this.dom.style;
7920 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7921 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7923 s.opacity = opacity;
7926 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7932 * Gets the left X coordinate
7933 * @param {Boolean} local True to get the local css position instead of page coordinate
7936 getLeft : function(local){
7940 return parseInt(this.getStyle("left"), 10) || 0;
7945 * Gets the right X coordinate of the element (element X position + element width)
7946 * @param {Boolean} local True to get the local css position instead of page coordinate
7949 getRight : function(local){
7951 return this.getX() + this.getWidth();
7953 return (this.getLeft(true) + this.getWidth()) || 0;
7958 * Gets the top Y coordinate
7959 * @param {Boolean} local True to get the local css position instead of page coordinate
7962 getTop : function(local) {
7966 return parseInt(this.getStyle("top"), 10) || 0;
7971 * Gets the bottom Y coordinate of the element (element Y position + element height)
7972 * @param {Boolean} local True to get the local css position instead of page coordinate
7975 getBottom : function(local){
7977 return this.getY() + this.getHeight();
7979 return (this.getTop(true) + this.getHeight()) || 0;
7984 * Initializes positioning on this element. If a desired position is not passed, it will make the
7985 * the element positioned relative IF it is not already positioned.
7986 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7987 * @param {Number} zIndex (optional) The zIndex to apply
7988 * @param {Number} x (optional) Set the page X position
7989 * @param {Number} y (optional) Set the page Y position
7991 position : function(pos, zIndex, x, y){
7993 if(this.getStyle('position') == 'static'){
7994 this.setStyle('position', 'relative');
7997 this.setStyle("position", pos);
8000 this.setStyle("z-index", zIndex);
8002 if(x !== undefined && y !== undefined){
8004 }else if(x !== undefined){
8006 }else if(y !== undefined){
8012 * Clear positioning back to the default when the document was loaded
8013 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
8014 * @return {Roo.Element} this
8016 clearPositioning : function(value){
8024 "position" : "static"
8030 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
8031 * snapshot before performing an update and then restoring the element.
8034 getPositioning : function(){
8035 var l = this.getStyle("left");
8036 var t = this.getStyle("top");
8038 "position" : this.getStyle("position"),
8040 "right" : l ? "" : this.getStyle("right"),
8042 "bottom" : t ? "" : this.getStyle("bottom"),
8043 "z-index" : this.getStyle("z-index")
8048 * Gets the width of the border(s) for the specified side(s)
8049 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8050 * passing lr would get the border (l)eft width + the border (r)ight width.
8051 * @return {Number} The width of the sides passed added together
8053 getBorderWidth : function(side){
8054 return this.addStyles(side, El.borders);
8058 * Gets the width of the padding(s) for the specified side(s)
8059 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8060 * passing lr would get the padding (l)eft + the padding (r)ight.
8061 * @return {Number} The padding of the sides passed added together
8063 getPadding : function(side){
8064 return this.addStyles(side, El.paddings);
8068 * Set positioning with an object returned by getPositioning().
8069 * @param {Object} posCfg
8070 * @return {Roo.Element} this
8072 setPositioning : function(pc){
8073 this.applyStyles(pc);
8074 if(pc.right == "auto"){
8075 this.dom.style.right = "";
8077 if(pc.bottom == "auto"){
8078 this.dom.style.bottom = "";
8084 fixDisplay : function(){
8085 if(this.getStyle("display") == "none"){
8086 this.setStyle("visibility", "hidden");
8087 this.setStyle("display", this.originalDisplay); // first try reverting to default
8088 if(this.getStyle("display") == "none"){ // if that fails, default to block
8089 this.setStyle("display", "block");
8095 * Quick set left and top adding default units
8096 * @param {String} left The left CSS property value
8097 * @param {String} top The top CSS property value
8098 * @return {Roo.Element} this
8100 setLeftTop : function(left, top){
8101 this.dom.style.left = this.addUnits(left);
8102 this.dom.style.top = this.addUnits(top);
8107 * Move this element relative to its current position.
8108 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8109 * @param {Number} distance How far to move the element in pixels
8110 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8111 * @return {Roo.Element} this
8113 move : function(direction, distance, animate){
8114 var xy = this.getXY();
8115 direction = direction.toLowerCase();
8119 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8123 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8128 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8133 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8140 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8141 * @return {Roo.Element} this
8144 if(!this.isClipped){
8145 this.isClipped = true;
8146 this.originalClip = {
8147 "o": this.getStyle("overflow"),
8148 "x": this.getStyle("overflow-x"),
8149 "y": this.getStyle("overflow-y")
8151 this.setStyle("overflow", "hidden");
8152 this.setStyle("overflow-x", "hidden");
8153 this.setStyle("overflow-y", "hidden");
8159 * Return clipping (overflow) to original clipping before clip() was called
8160 * @return {Roo.Element} this
8162 unclip : function(){
8164 this.isClipped = false;
8165 var o = this.originalClip;
8166 if(o.o){this.setStyle("overflow", o.o);}
8167 if(o.x){this.setStyle("overflow-x", o.x);}
8168 if(o.y){this.setStyle("overflow-y", o.y);}
8175 * Gets the x,y coordinates specified by the anchor position on the element.
8176 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8177 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8178 * {width: (target width), height: (target height)} (defaults to the element's current size)
8179 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8180 * @return {Array} [x, y] An array containing the element's x and y coordinates
8182 getAnchorXY : function(anchor, local, s){
8183 //Passing a different size is useful for pre-calculating anchors,
8184 //especially for anchored animations that change the el size.
8186 var w, h, vp = false;
8189 if(d == document.body || d == document){
8191 w = D.getViewWidth(); h = D.getViewHeight();
8193 w = this.getWidth(); h = this.getHeight();
8196 w = s.width; h = s.height;
8198 var x = 0, y = 0, r = Math.round;
8199 switch((anchor || "tl").toLowerCase()){
8241 var sc = this.getScroll();
8242 return [x + sc.left, y + sc.top];
8244 //Add the element's offset xy
8245 var o = this.getXY();
8246 return [x+o[0], y+o[1]];
8250 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8251 * supported position values.
8252 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8253 * @param {String} position The position to align to.
8254 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8255 * @return {Array} [x, y]
8257 getAlignToXY : function(el, p, o){
8261 throw "Element.alignTo with an element that doesn't exist";
8263 var c = false; //constrain to viewport
8264 var p1 = "", p2 = "";
8271 }else if(p.indexOf("-") == -1){
8274 p = p.toLowerCase();
8275 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8277 throw "Element.alignTo with an invalid alignment " + p;
8279 p1 = m[1]; p2 = m[2]; c = !!m[3];
8281 //Subtract the aligned el's internal xy from the target's offset xy
8282 //plus custom offset to get the aligned el's new offset xy
8283 var a1 = this.getAnchorXY(p1, true);
8284 var a2 = el.getAnchorXY(p2, false);
8285 var x = a2[0] - a1[0] + o[0];
8286 var y = a2[1] - a1[1] + o[1];
8288 //constrain the aligned el to viewport if necessary
8289 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8290 // 5px of margin for ie
8291 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8293 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8294 //perpendicular to the vp border, allow the aligned el to slide on that border,
8295 //otherwise swap the aligned el to the opposite border of the target.
8296 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8297 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8298 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8299 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8302 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8303 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8305 if((x+w) > dw + scrollX){
8306 x = swapX ? r.left-w : dw+scrollX-w;
8309 x = swapX ? r.right : scrollX;
8311 if((y+h) > dh + scrollY){
8312 y = swapY ? r.top-h : dh+scrollY-h;
8315 y = swapY ? r.bottom : scrollY;
8322 getConstrainToXY : function(){
8323 var os = {top:0, left:0, bottom:0, right: 0};
8325 return function(el, local, offsets, proposedXY){
8327 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8329 var vw, vh, vx = 0, vy = 0;
8330 if(el.dom == document.body || el.dom == document){
8331 vw = Roo.lib.Dom.getViewWidth();
8332 vh = Roo.lib.Dom.getViewHeight();
8334 vw = el.dom.clientWidth;
8335 vh = el.dom.clientHeight;
8337 var vxy = el.getXY();
8343 var s = el.getScroll();
8345 vx += offsets.left + s.left;
8346 vy += offsets.top + s.top;
8348 vw -= offsets.right;
8349 vh -= offsets.bottom;
8354 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8355 var x = xy[0], y = xy[1];
8356 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8358 // only move it if it needs it
8361 // first validate right/bottom
8370 // then make sure top/left isn't negative
8379 return moved ? [x, y] : false;
8384 adjustForConstraints : function(xy, parent, offsets){
8385 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8389 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8390 * document it aligns it to the viewport.
8391 * The position parameter is optional, and can be specified in any one of the following formats:
8393 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8394 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8395 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8396 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8397 * <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
8398 * element's anchor point, and the second value is used as the target's anchor point.</li>
8400 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8401 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8402 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8403 * that specified in order to enforce the viewport constraints.
8404 * Following are all of the supported anchor positions:
8407 ----- -----------------------------
8408 tl The top left corner (default)
8409 t The center of the top edge
8410 tr The top right corner
8411 l The center of the left edge
8412 c In the center of the element
8413 r The center of the right edge
8414 bl The bottom left corner
8415 b The center of the bottom edge
8416 br The bottom right corner
8420 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8421 el.alignTo("other-el");
8423 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8424 el.alignTo("other-el", "tr?");
8426 // align the bottom right corner of el with the center left edge of other-el
8427 el.alignTo("other-el", "br-l?");
8429 // align the center of el with the bottom left corner of other-el and
8430 // adjust the x position by -6 pixels (and the y position by 0)
8431 el.alignTo("other-el", "c-bl", [-6, 0]);
8433 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8434 * @param {String} position The position to align to.
8435 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8436 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8437 * @return {Roo.Element} this
8439 alignTo : function(element, position, offsets, animate){
8440 var xy = this.getAlignToXY(element, position, offsets);
8441 this.setXY(xy, this.preanim(arguments, 3));
8446 * Anchors an element to another element and realigns it when the window is resized.
8447 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8448 * @param {String} position The position to align to.
8449 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8450 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8451 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8452 * is a number, it is used as the buffer delay (defaults to 50ms).
8453 * @param {Function} callback The function to call after the animation finishes
8454 * @return {Roo.Element} this
8456 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8457 var action = function(){
8458 this.alignTo(el, alignment, offsets, animate);
8459 Roo.callback(callback, this);
8461 Roo.EventManager.onWindowResize(action, this);
8462 var tm = typeof monitorScroll;
8463 if(tm != 'undefined'){
8464 Roo.EventManager.on(window, 'scroll', action, this,
8465 {buffer: tm == 'number' ? monitorScroll : 50});
8467 action.call(this); // align immediately
8471 * Clears any opacity settings from this element. Required in some cases for IE.
8472 * @return {Roo.Element} this
8474 clearOpacity : function(){
8475 if (window.ActiveXObject) {
8476 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8477 this.dom.style.filter = "";
8480 this.dom.style.opacity = "";
8481 this.dom.style["-moz-opacity"] = "";
8482 this.dom.style["-khtml-opacity"] = "";
8488 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8489 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8490 * @return {Roo.Element} this
8492 hide : function(animate){
8493 this.setVisible(false, this.preanim(arguments, 0));
8498 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8499 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8500 * @return {Roo.Element} this
8502 show : function(animate){
8503 this.setVisible(true, this.preanim(arguments, 0));
8508 * @private Test if size has a unit, otherwise appends the default
8510 addUnits : function(size){
8511 return Roo.Element.addUnits(size, this.defaultUnit);
8515 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8516 * @return {Roo.Element} this
8518 beginMeasure : function(){
8520 if(el.offsetWidth || el.offsetHeight){
8521 return this; // offsets work already
8524 var p = this.dom, b = document.body; // start with this element
8525 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8526 var pe = Roo.get(p);
8527 if(pe.getStyle('display') == 'none'){
8528 changed.push({el: p, visibility: pe.getStyle("visibility")});
8529 p.style.visibility = "hidden";
8530 p.style.display = "block";
8534 this._measureChanged = changed;
8540 * Restores displays to before beginMeasure was called
8541 * @return {Roo.Element} this
8543 endMeasure : function(){
8544 var changed = this._measureChanged;
8546 for(var i = 0, len = changed.length; i < len; i++) {
8548 r.el.style.visibility = r.visibility;
8549 r.el.style.display = "none";
8551 this._measureChanged = null;
8557 * Update the innerHTML of this element, optionally searching for and processing scripts
8558 * @param {String} html The new HTML
8559 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8560 * @param {Function} callback For async script loading you can be noticed when the update completes
8561 * @return {Roo.Element} this
8563 update : function(html, loadScripts, callback){
8564 if(typeof html == "undefined"){
8567 if(loadScripts !== true){
8568 this.dom.innerHTML = html;
8569 if(typeof callback == "function"){
8577 html += '<span id="' + id + '"></span>';
8579 E.onAvailable(id, function(){
8580 var hd = document.getElementsByTagName("head")[0];
8581 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8582 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8583 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8586 while(match = re.exec(html)){
8587 var attrs = match[1];
8588 var srcMatch = attrs ? attrs.match(srcRe) : false;
8589 if(srcMatch && srcMatch[2]){
8590 var s = document.createElement("script");
8591 s.src = srcMatch[2];
8592 var typeMatch = attrs.match(typeRe);
8593 if(typeMatch && typeMatch[2]){
8594 s.type = typeMatch[2];
8597 }else if(match[2] && match[2].length > 0){
8598 if(window.execScript) {
8599 window.execScript(match[2]);
8607 window.eval(match[2]);
8611 var el = document.getElementById(id);
8612 if(el){el.parentNode.removeChild(el);}
8613 if(typeof callback == "function"){
8617 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8622 * Direct access to the UpdateManager update() method (takes the same parameters).
8623 * @param {String/Function} url The url for this request or a function to call to get the url
8624 * @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}
8625 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8626 * @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.
8627 * @return {Roo.Element} this
8630 var um = this.getUpdateManager();
8631 um.update.apply(um, arguments);
8636 * Gets this element's UpdateManager
8637 * @return {Roo.UpdateManager} The UpdateManager
8639 getUpdateManager : function(){
8640 if(!this.updateManager){
8641 this.updateManager = new Roo.UpdateManager(this);
8643 return this.updateManager;
8647 * Disables text selection for this element (normalized across browsers)
8648 * @return {Roo.Element} this
8650 unselectable : function(){
8651 this.dom.unselectable = "on";
8652 this.swallowEvent("selectstart", true);
8653 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8654 this.addClass("x-unselectable");
8659 * Calculates the x, y to center this element on the screen
8660 * @return {Array} The x, y values [x, y]
8662 getCenterXY : function(){
8663 return this.getAlignToXY(document, 'c-c');
8667 * Centers the Element in either the viewport, or another Element.
8668 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8670 center : function(centerIn){
8671 this.alignTo(centerIn || document, 'c-c');
8676 * Tests various css rules/browsers to determine if this element uses a border box
8679 isBorderBox : function(){
8680 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8684 * Return a box {x, y, width, height} that can be used to set another elements
8685 * size/location to match this element.
8686 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8687 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8688 * @return {Object} box An object in the format {x, y, width, height}
8690 getBox : function(contentBox, local){
8695 var left = parseInt(this.getStyle("left"), 10) || 0;
8696 var top = parseInt(this.getStyle("top"), 10) || 0;
8699 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8701 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8703 var l = this.getBorderWidth("l")+this.getPadding("l");
8704 var r = this.getBorderWidth("r")+this.getPadding("r");
8705 var t = this.getBorderWidth("t")+this.getPadding("t");
8706 var b = this.getBorderWidth("b")+this.getPadding("b");
8707 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)};
8709 bx.right = bx.x + bx.width;
8710 bx.bottom = bx.y + bx.height;
8715 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8716 for more information about the sides.
8717 * @param {String} sides
8720 getFrameWidth : function(sides, onlyContentBox){
8721 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8725 * 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.
8726 * @param {Object} box The box to fill {x, y, width, height}
8727 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8728 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8729 * @return {Roo.Element} this
8731 setBox : function(box, adjust, animate){
8732 var w = box.width, h = box.height;
8733 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8734 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8735 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8737 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8742 * Forces the browser to repaint this element
8743 * @return {Roo.Element} this
8745 repaint : function(){
8747 this.addClass("x-repaint");
8748 setTimeout(function(){
8749 Roo.get(dom).removeClass("x-repaint");
8755 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8756 * then it returns the calculated width of the sides (see getPadding)
8757 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8758 * @return {Object/Number}
8760 getMargins : function(side){
8763 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8764 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8765 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8766 right: parseInt(this.getStyle("margin-right"), 10) || 0
8769 return this.addStyles(side, El.margins);
8774 addStyles : function(sides, styles){
8776 for(var i = 0, len = sides.length; i < len; i++){
8777 v = this.getStyle(styles[sides.charAt(i)]);
8779 w = parseInt(v, 10);
8787 * Creates a proxy element of this element
8788 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8789 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8790 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8791 * @return {Roo.Element} The new proxy element
8793 createProxy : function(config, renderTo, matchBox){
8795 renderTo = Roo.getDom(renderTo);
8797 renderTo = document.body;
8799 config = typeof config == "object" ?
8800 config : {tag : "div", cls: config};
8801 var proxy = Roo.DomHelper.append(renderTo, config, true);
8803 proxy.setBox(this.getBox());
8809 * Puts a mask over this element to disable user interaction. Requires core.css.
8810 * This method can only be applied to elements which accept child nodes.
8811 * @param {String} msg (optional) A message to display in the mask
8812 * @param {String} msgCls (optional) A css class to apply to the msg element
8813 * @return {Element} The mask element
8815 mask : function(msg, msgCls){
8816 if(this.getStyle("position") == "static"){
8817 this.setStyle("position", "relative");
8820 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8822 this.addClass("x-masked");
8823 this._mask.setDisplayed(true);
8824 if(typeof msg == 'string'){
8826 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8828 var mm = this._maskMsg;
8829 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8830 mm.dom.firstChild.innerHTML = msg;
8831 mm.setDisplayed(true);
8834 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8835 this._mask.setHeight(this.getHeight());
8841 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8842 * it is cached for reuse.
8844 unmask : function(removeEl){
8846 if(removeEl === true){
8847 this._mask.remove();
8850 this._maskMsg.remove();
8851 delete this._maskMsg;
8854 this._mask.setDisplayed(false);
8856 this._maskMsg.setDisplayed(false);
8860 this.removeClass("x-masked");
8864 * Returns true if this element is masked
8867 isMasked : function(){
8868 return this._mask && this._mask.isVisible();
8872 * Creates an iframe shim for this element to keep selects and other windowed objects from
8874 * @return {Roo.Element} The new shim element
8876 createShim : function(){
8877 var el = document.createElement('iframe');
8878 el.frameBorder = 'no';
8879 el.className = 'roo-shim';
8880 if(Roo.isIE && Roo.isSecure){
8881 el.src = Roo.SSL_SECURE_URL;
8883 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8884 shim.autoBoxAdjust = false;
8889 * Removes this element from the DOM and deletes it from the cache
8891 remove : function(){
8892 if(this.dom.parentNode){
8893 this.dom.parentNode.removeChild(this.dom);
8895 delete El.cache[this.dom.id];
8899 * Sets up event handlers to add and remove a css class when the mouse is over this element
8900 * @param {String} className
8901 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8902 * mouseout events for children elements
8903 * @return {Roo.Element} this
8905 addClassOnOver : function(className, preventFlicker){
8906 this.on("mouseover", function(){
8907 Roo.fly(this, '_internal').addClass(className);
8909 var removeFn = function(e){
8910 if(preventFlicker !== true || !e.within(this, true)){
8911 Roo.fly(this, '_internal').removeClass(className);
8914 this.on("mouseout", removeFn, this.dom);
8919 * Sets up event handlers to add and remove a css class when this element has the focus
8920 * @param {String} className
8921 * @return {Roo.Element} this
8923 addClassOnFocus : function(className){
8924 this.on("focus", function(){
8925 Roo.fly(this, '_internal').addClass(className);
8927 this.on("blur", function(){
8928 Roo.fly(this, '_internal').removeClass(className);
8933 * 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)
8934 * @param {String} className
8935 * @return {Roo.Element} this
8937 addClassOnClick : function(className){
8939 this.on("mousedown", function(){
8940 Roo.fly(dom, '_internal').addClass(className);
8941 var d = Roo.get(document);
8942 var fn = function(){
8943 Roo.fly(dom, '_internal').removeClass(className);
8944 d.removeListener("mouseup", fn);
8946 d.on("mouseup", fn);
8952 * Stops the specified event from bubbling and optionally prevents the default action
8953 * @param {String} eventName
8954 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8955 * @return {Roo.Element} this
8957 swallowEvent : function(eventName, preventDefault){
8958 var fn = function(e){
8959 e.stopPropagation();
8964 if(eventName instanceof Array){
8965 for(var i = 0, len = eventName.length; i < len; i++){
8966 this.on(eventName[i], fn);
8970 this.on(eventName, fn);
8977 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8980 * Sizes this element to its parent element's dimensions performing
8981 * neccessary box adjustments.
8982 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8983 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8984 * @return {Roo.Element} this
8986 fitToParent : function(monitorResize, targetParent) {
8987 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8988 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8989 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8992 var p = Roo.get(targetParent || this.dom.parentNode);
8993 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8994 if (monitorResize === true) {
8995 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8996 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
9002 * Gets the next sibling, skipping text nodes
9003 * @return {HTMLElement} The next sibling or null
9005 getNextSibling : function(){
9006 var n = this.dom.nextSibling;
9007 while(n && n.nodeType != 1){
9014 * Gets the previous sibling, skipping text nodes
9015 * @return {HTMLElement} The previous sibling or null
9017 getPrevSibling : function(){
9018 var n = this.dom.previousSibling;
9019 while(n && n.nodeType != 1){
9020 n = n.previousSibling;
9027 * Appends the passed element(s) to this element
9028 * @param {String/HTMLElement/Array/Element/CompositeElement} el
9029 * @return {Roo.Element} this
9031 appendChild: function(el){
9038 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
9039 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
9040 * automatically generated with the specified attributes.
9041 * @param {HTMLElement} insertBefore (optional) a child element of this element
9042 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
9043 * @return {Roo.Element} The new child element
9045 createChild: function(config, insertBefore, returnDom){
9046 config = config || {tag:'div'};
9048 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
9050 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9054 * Appends this element to the passed element
9055 * @param {String/HTMLElement/Element} el The new parent element
9056 * @return {Roo.Element} this
9058 appendTo: function(el){
9059 el = Roo.getDom(el);
9060 el.appendChild(this.dom);
9065 * Inserts this element before the passed element in the DOM
9066 * @param {String/HTMLElement/Element} el The element to insert before
9067 * @return {Roo.Element} this
9069 insertBefore: function(el){
9070 el = Roo.getDom(el);
9071 el.parentNode.insertBefore(this.dom, el);
9076 * Inserts this element after the passed element in the DOM
9077 * @param {String/HTMLElement/Element} el The element to insert after
9078 * @return {Roo.Element} this
9080 insertAfter: function(el){
9081 el = Roo.getDom(el);
9082 el.parentNode.insertBefore(this.dom, el.nextSibling);
9087 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9088 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9089 * @return {Roo.Element} The new child
9091 insertFirst: function(el, returnDom){
9093 if(typeof el == 'object' && !el.nodeType){ // dh config
9094 return this.createChild(el, this.dom.firstChild, returnDom);
9096 el = Roo.getDom(el);
9097 this.dom.insertBefore(el, this.dom.firstChild);
9098 return !returnDom ? Roo.get(el) : el;
9103 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9104 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9105 * @param {String} where (optional) 'before' or 'after' defaults to before
9106 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9107 * @return {Roo.Element} the inserted Element
9109 insertSibling: function(el, where, returnDom){
9110 where = where ? where.toLowerCase() : 'before';
9112 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9114 if(typeof el == 'object' && !el.nodeType){ // dh config
9115 if(where == 'after' && !this.dom.nextSibling){
9116 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9118 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9122 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9123 where == 'before' ? this.dom : this.dom.nextSibling);
9132 * Creates and wraps this element with another element
9133 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9134 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9135 * @return {HTMLElement/Element} The newly created wrapper element
9137 wrap: function(config, returnDom){
9139 config = {tag: "div"};
9141 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9142 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9147 * Replaces the passed element with this element
9148 * @param {String/HTMLElement/Element} el The element to replace
9149 * @return {Roo.Element} this
9151 replace: function(el){
9153 this.insertBefore(el);
9159 * Inserts an html fragment into this element
9160 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9161 * @param {String} html The HTML fragment
9162 * @param {Boolean} returnEl True to return an Roo.Element
9163 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9165 insertHtml : function(where, html, returnEl){
9166 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9167 return returnEl ? Roo.get(el) : el;
9171 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9172 * @param {Object} o The object with the attributes
9173 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9174 * @return {Roo.Element} this
9176 set : function(o, useSet){
9178 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9180 if(attr == "style" || typeof o[attr] == "function") continue;
9182 el.className = o["cls"];
9184 if(useSet) el.setAttribute(attr, o[attr]);
9185 else el[attr] = o[attr];
9189 Roo.DomHelper.applyStyles(el, o.style);
9195 * Convenience method for constructing a KeyMap
9196 * @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:
9197 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9198 * @param {Function} fn The function to call
9199 * @param {Object} scope (optional) The scope of the function
9200 * @return {Roo.KeyMap} The KeyMap created
9202 addKeyListener : function(key, fn, scope){
9204 if(typeof key != "object" || key instanceof Array){
9220 return new Roo.KeyMap(this, config);
9224 * Creates a KeyMap for this element
9225 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9226 * @return {Roo.KeyMap} The KeyMap created
9228 addKeyMap : function(config){
9229 return new Roo.KeyMap(this, config);
9233 * Returns true if this element is scrollable.
9236 isScrollable : function(){
9238 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9242 * 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().
9243 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9244 * @param {Number} value The new scroll value
9245 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9246 * @return {Element} this
9249 scrollTo : function(side, value, animate){
9250 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9252 this.dom[prop] = value;
9254 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9255 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9261 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9262 * within this element's scrollable range.
9263 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9264 * @param {Number} distance How far to scroll the element in pixels
9265 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9266 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9267 * was scrolled as far as it could go.
9269 scroll : function(direction, distance, animate){
9270 if(!this.isScrollable()){
9274 var l = el.scrollLeft, t = el.scrollTop;
9275 var w = el.scrollWidth, h = el.scrollHeight;
9276 var cw = el.clientWidth, ch = el.clientHeight;
9277 direction = direction.toLowerCase();
9278 var scrolled = false;
9279 var a = this.preanim(arguments, 2);
9284 var v = Math.min(l + distance, w-cw);
9285 this.scrollTo("left", v, a);
9292 var v = Math.max(l - distance, 0);
9293 this.scrollTo("left", v, a);
9301 var v = Math.max(t - distance, 0);
9302 this.scrollTo("top", v, a);
9310 var v = Math.min(t + distance, h-ch);
9311 this.scrollTo("top", v, a);
9320 * Translates the passed page coordinates into left/top css values for this element
9321 * @param {Number/Array} x The page x or an array containing [x, y]
9322 * @param {Number} y The page y
9323 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9325 translatePoints : function(x, y){
9326 if(typeof x == 'object' || x instanceof Array){
9329 var p = this.getStyle('position');
9330 var o = this.getXY();
9332 var l = parseInt(this.getStyle('left'), 10);
9333 var t = parseInt(this.getStyle('top'), 10);
9336 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9339 t = (p == "relative") ? 0 : this.dom.offsetTop;
9342 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9346 * Returns the current scroll position of the element.
9347 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9349 getScroll : function(){
9350 var d = this.dom, doc = document;
9351 if(d == doc || d == doc.body){
9352 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9353 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9354 return {left: l, top: t};
9356 return {left: d.scrollLeft, top: d.scrollTop};
9361 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9362 * are convert to standard 6 digit hex color.
9363 * @param {String} attr The css attribute
9364 * @param {String} defaultValue The default value to use when a valid color isn't found
9365 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9368 getColor : function(attr, defaultValue, prefix){
9369 var v = this.getStyle(attr);
9370 if(!v || v == "transparent" || v == "inherit") {
9371 return defaultValue;
9373 var color = typeof prefix == "undefined" ? "#" : prefix;
9374 if(v.substr(0, 4) == "rgb("){
9375 var rvs = v.slice(4, v.length -1).split(",");
9376 for(var i = 0; i < 3; i++){
9377 var h = parseInt(rvs[i]).toString(16);
9384 if(v.substr(0, 1) == "#"){
9386 for(var i = 1; i < 4; i++){
9387 var c = v.charAt(i);
9390 }else if(v.length == 7){
9391 color += v.substr(1);
9395 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9399 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9400 * gradient background, rounded corners and a 4-way shadow.
9401 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9402 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9403 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9404 * @return {Roo.Element} this
9406 boxWrap : function(cls){
9407 cls = cls || 'x-box';
9408 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9409 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9414 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9415 * @param {String} namespace The namespace in which to look for the attribute
9416 * @param {String} name The attribute name
9417 * @return {String} The attribute value
9419 getAttributeNS : Roo.isIE ? function(ns, name){
9421 var type = typeof d[ns+":"+name];
9422 if(type != 'undefined' && type != 'unknown'){
9423 return d[ns+":"+name];
9426 } : function(ns, name){
9428 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9432 var ep = El.prototype;
9435 * Appends an event handler (Shorthand for addListener)
9436 * @param {String} eventName The type of event to append
9437 * @param {Function} fn The method the event invokes
9438 * @param {Object} scope (optional) The scope (this object) of the fn
9439 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9442 ep.on = ep.addListener;
9444 ep.mon = ep.addListener;
9447 * Removes an event handler from this element (shorthand for removeListener)
9448 * @param {String} eventName the type of event to remove
9449 * @param {Function} fn the method the event invokes
9450 * @return {Roo.Element} this
9453 ep.un = ep.removeListener;
9456 * true to automatically adjust width and height settings for box-model issues (default to true)
9458 ep.autoBoxAdjust = true;
9461 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9464 El.addUnits = function(v, defaultUnit){
9465 if(v === "" || v == "auto"){
9468 if(v === undefined){
9471 if(typeof v == "number" || !El.unitPattern.test(v)){
9472 return v + (defaultUnit || 'px');
9477 // special markup used throughout Roo when box wrapping elements
9478 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>';
9480 * Visibility mode constant - Use visibility to hide element
9486 * Visibility mode constant - Use display to hide element
9492 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9493 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9494 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9506 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9507 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9508 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9509 * @return {Element} The Element object
9512 El.get = function(el){
9514 if(!el){ return null; }
9515 if(typeof el == "string"){ // element id
9516 if(!(elm = document.getElementById(el))){
9519 if(ex = El.cache[el]){
9522 ex = El.cache[el] = new El(elm);
9525 }else if(el.tagName){ // dom element
9529 if(ex = El.cache[id]){
9532 ex = El.cache[id] = new El(el);
9535 }else if(el instanceof El){
9537 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9538 // catch case where it hasn't been appended
9539 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9542 }else if(el.isComposite){
9544 }else if(el instanceof Array){
9545 return El.select(el);
9546 }else if(el == document){
9547 // create a bogus element object representing the document object
9549 var f = function(){};
9550 f.prototype = El.prototype;
9552 docEl.dom = document;
9560 El.uncache = function(el){
9561 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9563 delete El.cache[a[i].id || a[i]];
9569 // Garbage collection - uncache elements/purge listeners on orphaned elements
9570 // so we don't hold a reference and cause the browser to retain them
9571 El.garbageCollect = function(){
9572 if(!Roo.enableGarbageCollector){
9573 clearInterval(El.collectorThread);
9576 for(var eid in El.cache){
9577 var el = El.cache[eid], d = el.dom;
9578 // -------------------------------------------------------
9579 // Determining what is garbage:
9580 // -------------------------------------------------------
9582 // dom node is null, definitely garbage
9583 // -------------------------------------------------------
9585 // no parentNode == direct orphan, definitely garbage
9586 // -------------------------------------------------------
9587 // !d.offsetParent && !document.getElementById(eid)
9588 // display none elements have no offsetParent so we will
9589 // also try to look it up by it's id. However, check
9590 // offsetParent first so we don't do unneeded lookups.
9591 // This enables collection of elements that are not orphans
9592 // directly, but somewhere up the line they have an orphan
9594 // -------------------------------------------------------
9595 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9596 delete El.cache[eid];
9597 if(d && Roo.enableListenerCollection){
9603 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9607 El.Flyweight = function(dom){
9610 El.Flyweight.prototype = El.prototype;
9612 El._flyweights = {};
9614 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9615 * the dom node can be overwritten by other code.
9616 * @param {String/HTMLElement} el The dom node or id
9617 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9618 * prevent conflicts (e.g. internally Roo uses "_internal")
9620 * @return {Element} The shared Element object
9622 El.fly = function(el, named){
9623 named = named || '_global';
9624 el = Roo.getDom(el);
9628 if(!El._flyweights[named]){
9629 El._flyweights[named] = new El.Flyweight();
9631 El._flyweights[named].dom = el;
9632 return El._flyweights[named];
9636 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9637 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9638 * Shorthand of {@link Roo.Element#get}
9639 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9640 * @return {Element} The Element object
9646 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9647 * the dom node can be overwritten by other code.
9648 * Shorthand of {@link Roo.Element#fly}
9649 * @param {String/HTMLElement} el The dom node or id
9650 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9651 * prevent conflicts (e.g. internally Roo uses "_internal")
9653 * @return {Element} The shared Element object
9659 // speedy lookup for elements never to box adjust
9660 var noBoxAdjust = Roo.isStrict ? {
9663 input:1, select:1, textarea:1
9665 if(Roo.isIE || Roo.isGecko){
9666 noBoxAdjust['button'] = 1;
9670 Roo.EventManager.on(window, 'unload', function(){
9672 delete El._flyweights;
9680 Roo.Element.selectorFunction = Roo.DomQuery.select;
9683 Roo.Element.select = function(selector, unique, root){
9685 if(typeof selector == "string"){
9686 els = Roo.Element.selectorFunction(selector, root);
9687 }else if(selector.length !== undefined){
9690 throw "Invalid selector";
9692 if(unique === true){
9693 return new Roo.CompositeElement(els);
9695 return new Roo.CompositeElementLite(els);
9699 * Selects elements based on the passed CSS selector to enable working on them as 1.
9700 * @param {String/Array} selector The CSS selector or an array of elements
9701 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9702 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9703 * @return {CompositeElementLite/CompositeElement}
9707 Roo.select = Roo.Element.select;
9724 * Ext JS Library 1.1.1
9725 * Copyright(c) 2006-2007, Ext JS, LLC.
9727 * Originally Released Under LGPL - original licence link has changed is not relivant.
9730 * <script type="text/javascript">
9735 //Notifies Element that fx methods are available
9736 Roo.enableFx = true;
9740 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9741 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9742 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9743 * Element effects to work.</p><br/>
9745 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9746 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9747 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9748 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9749 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9750 * expected results and should be done with care.</p><br/>
9752 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9753 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9756 ----- -----------------------------
9757 tl The top left corner
9758 t The center of the top edge
9759 tr The top right corner
9760 l The center of the left edge
9761 r The center of the right edge
9762 bl The bottom left corner
9763 b The center of the bottom edge
9764 br The bottom right corner
9766 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9767 * below are common options that can be passed to any Fx method.</b>
9768 * @cfg {Function} callback A function called when the effect is finished
9769 * @cfg {Object} scope The scope of the effect function
9770 * @cfg {String} easing A valid Easing value for the effect
9771 * @cfg {String} afterCls A css class to apply after the effect
9772 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9773 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9774 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9775 * effects that end with the element being visually hidden, ignored otherwise)
9776 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9777 * a function which returns such a specification that will be applied to the Element after the effect finishes
9778 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9779 * @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
9780 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9784 * Slides the element into view. An anchor point can be optionally passed to set the point of
9785 * origin for the slide effect. This function automatically handles wrapping the element with
9786 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9789 // default: slide the element in from the top
9792 // custom: slide the element in from the right with a 2-second duration
9793 el.slideIn('r', { duration: 2 });
9795 // common config options shown with default values
9801 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9802 * @param {Object} options (optional) Object literal with any of the Fx config options
9803 * @return {Roo.Element} The Element
9805 slideIn : function(anchor, o){
9806 var el = this.getFxEl();
9809 el.queueFx(o, function(){
9811 anchor = anchor || "t";
9813 // fix display to visibility
9816 // restore values after effect
9817 var r = this.getFxRestore();
9818 var b = this.getBox();
9819 // fixed size for slide
9823 var wrap = this.fxWrap(r.pos, o, "hidden");
9825 var st = this.dom.style;
9826 st.visibility = "visible";
9827 st.position = "absolute";
9829 // clear out temp styles after slide and unwrap
9830 var after = function(){
9831 el.fxUnwrap(wrap, r.pos, o);
9833 st.height = r.height;
9836 // time to calc the positions
9837 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9839 switch(anchor.toLowerCase()){
9841 wrap.setSize(b.width, 0);
9842 st.left = st.bottom = "0";
9846 wrap.setSize(0, b.height);
9847 st.right = st.top = "0";
9851 wrap.setSize(0, b.height);
9853 st.left = st.top = "0";
9854 a = {width: bw, points: pt};
9857 wrap.setSize(b.width, 0);
9858 wrap.setY(b.bottom);
9859 st.left = st.top = "0";
9860 a = {height: bh, points: pt};
9864 st.right = st.bottom = "0";
9865 a = {width: bw, height: bh};
9869 wrap.setY(b.y+b.height);
9870 st.right = st.top = "0";
9871 a = {width: bw, height: bh, points: pt};
9875 wrap.setXY([b.right, b.bottom]);
9876 st.left = st.top = "0";
9877 a = {width: bw, height: bh, points: pt};
9881 wrap.setX(b.x+b.width);
9882 st.left = st.bottom = "0";
9883 a = {width: bw, height: bh, points: pt};
9886 this.dom.style.visibility = "visible";
9889 arguments.callee.anim = wrap.fxanim(a,
9899 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9900 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9901 * 'hidden') but block elements will still take up space in the document. The element must be removed
9902 * from the DOM using the 'remove' config option if desired. This function automatically handles
9903 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9906 // default: slide the element out to the top
9909 // custom: slide the element out to the right with a 2-second duration
9910 el.slideOut('r', { duration: 2 });
9912 // common config options shown with default values
9920 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9921 * @param {Object} options (optional) Object literal with any of the Fx config options
9922 * @return {Roo.Element} The Element
9924 slideOut : function(anchor, o){
9925 var el = this.getFxEl();
9928 el.queueFx(o, function(){
9930 anchor = anchor || "t";
9932 // restore values after effect
9933 var r = this.getFxRestore();
9935 var b = this.getBox();
9936 // fixed size for slide
9940 var wrap = this.fxWrap(r.pos, o, "visible");
9942 var st = this.dom.style;
9943 st.visibility = "visible";
9944 st.position = "absolute";
9948 var after = function(){
9950 el.setDisplayed(false);
9955 el.fxUnwrap(wrap, r.pos, o);
9958 st.height = r.height;
9963 var a, zero = {to: 0};
9964 switch(anchor.toLowerCase()){
9966 st.left = st.bottom = "0";
9970 st.right = st.top = "0";
9974 st.left = st.top = "0";
9975 a = {width: zero, points: {to:[b.right, b.y]}};
9978 st.left = st.top = "0";
9979 a = {height: zero, points: {to:[b.x, b.bottom]}};
9982 st.right = st.bottom = "0";
9983 a = {width: zero, height: zero};
9986 st.right = st.top = "0";
9987 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9990 st.left = st.top = "0";
9991 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9994 st.left = st.bottom = "0";
9995 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9999 arguments.callee.anim = wrap.fxanim(a,
10009 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
10010 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
10011 * The element must be removed from the DOM using the 'remove' config option if desired.
10017 // common config options shown with default values
10025 * @param {Object} options (optional) Object literal with any of the Fx config options
10026 * @return {Roo.Element} The Element
10028 puff : function(o){
10029 var el = this.getFxEl();
10032 el.queueFx(o, function(){
10033 this.clearOpacity();
10036 // restore values after effect
10037 var r = this.getFxRestore();
10038 var st = this.dom.style;
10040 var after = function(){
10042 el.setDisplayed(false);
10049 el.setPositioning(r.pos);
10050 st.width = r.width;
10051 st.height = r.height;
10056 var width = this.getWidth();
10057 var height = this.getHeight();
10059 arguments.callee.anim = this.fxanim({
10060 width : {to: this.adjustWidth(width * 2)},
10061 height : {to: this.adjustHeight(height * 2)},
10062 points : {by: [-(width * .5), -(height * .5)]},
10064 fontSize: {to:200, unit: "%"}
10075 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10076 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10077 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10083 // all config options shown with default values
10091 * @param {Object} options (optional) Object literal with any of the Fx config options
10092 * @return {Roo.Element} The Element
10094 switchOff : function(o){
10095 var el = this.getFxEl();
10098 el.queueFx(o, function(){
10099 this.clearOpacity();
10102 // restore values after effect
10103 var r = this.getFxRestore();
10104 var st = this.dom.style;
10106 var after = function(){
10108 el.setDisplayed(false);
10114 el.setPositioning(r.pos);
10115 st.width = r.width;
10116 st.height = r.height;
10121 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10122 this.clearOpacity();
10126 points:{by:[0, this.getHeight() * .5]}
10127 }, o, 'motion', 0.3, 'easeIn', after);
10128 }).defer(100, this);
10135 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10136 * changed using the "attr" config option) and then fading back to the original color. If no original
10137 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10140 // default: highlight background to yellow
10143 // custom: highlight foreground text to blue for 2 seconds
10144 el.highlight("0000ff", { attr: 'color', duration: 2 });
10146 // common config options shown with default values
10147 el.highlight("ffff9c", {
10148 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10149 endColor: (current color) or "ffffff",
10154 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10155 * @param {Object} options (optional) Object literal with any of the Fx config options
10156 * @return {Roo.Element} The Element
10158 highlight : function(color, o){
10159 var el = this.getFxEl();
10162 el.queueFx(o, function(){
10163 color = color || "ffff9c";
10164 attr = o.attr || "backgroundColor";
10166 this.clearOpacity();
10169 var origColor = this.getColor(attr);
10170 var restoreColor = this.dom.style[attr];
10171 endColor = (o.endColor || origColor) || "ffffff";
10173 var after = function(){
10174 el.dom.style[attr] = restoreColor;
10179 a[attr] = {from: color, to: endColor};
10180 arguments.callee.anim = this.fxanim(a,
10190 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10193 // default: a single light blue ripple
10196 // custom: 3 red ripples lasting 3 seconds total
10197 el.frame("ff0000", 3, { duration: 3 });
10199 // common config options shown with default values
10200 el.frame("C3DAF9", 1, {
10201 duration: 1 //duration of entire animation (not each individual ripple)
10202 // Note: Easing is not configurable and will be ignored if included
10205 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10206 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10207 * @param {Object} options (optional) Object literal with any of the Fx config options
10208 * @return {Roo.Element} The Element
10210 frame : function(color, count, o){
10211 var el = this.getFxEl();
10214 el.queueFx(o, function(){
10215 color = color || "#C3DAF9";
10216 if(color.length == 6){
10217 color = "#" + color;
10219 count = count || 1;
10220 duration = o.duration || 1;
10223 var b = this.getBox();
10224 var animFn = function(){
10225 var proxy = this.createProxy({
10228 visbility:"hidden",
10229 position:"absolute",
10230 "z-index":"35000", // yee haw
10231 border:"0px solid " + color
10234 var scale = Roo.isBorderBox ? 2 : 1;
10236 top:{from:b.y, to:b.y - 20},
10237 left:{from:b.x, to:b.x - 20},
10238 borderWidth:{from:0, to:10},
10239 opacity:{from:1, to:0},
10240 height:{from:b.height, to:(b.height + (20*scale))},
10241 width:{from:b.width, to:(b.width + (20*scale))}
10242 }, duration, function(){
10246 animFn.defer((duration/2)*1000, this);
10257 * Creates a pause before any subsequent queued effects begin. If there are
10258 * no effects queued after the pause it will have no effect.
10263 * @param {Number} seconds The length of time to pause (in seconds)
10264 * @return {Roo.Element} The Element
10266 pause : function(seconds){
10267 var el = this.getFxEl();
10270 el.queueFx(o, function(){
10271 setTimeout(function(){
10273 }, seconds * 1000);
10279 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10280 * using the "endOpacity" config option.
10283 // default: fade in from opacity 0 to 100%
10286 // custom: fade in from opacity 0 to 75% over 2 seconds
10287 el.fadeIn({ endOpacity: .75, duration: 2});
10289 // common config options shown with default values
10291 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10296 * @param {Object} options (optional) Object literal with any of the Fx config options
10297 * @return {Roo.Element} The Element
10299 fadeIn : function(o){
10300 var el = this.getFxEl();
10302 el.queueFx(o, function(){
10303 this.setOpacity(0);
10305 this.dom.style.visibility = 'visible';
10306 var to = o.endOpacity || 1;
10307 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10308 o, null, .5, "easeOut", function(){
10310 this.clearOpacity();
10319 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10320 * using the "endOpacity" config option.
10323 // default: fade out from the element's current opacity to 0
10326 // custom: fade out from the element's current opacity to 25% over 2 seconds
10327 el.fadeOut({ endOpacity: .25, duration: 2});
10329 // common config options shown with default values
10331 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10338 * @param {Object} options (optional) Object literal with any of the Fx config options
10339 * @return {Roo.Element} The Element
10341 fadeOut : function(o){
10342 var el = this.getFxEl();
10344 el.queueFx(o, function(){
10345 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10346 o, null, .5, "easeOut", function(){
10347 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10348 this.dom.style.display = "none";
10350 this.dom.style.visibility = "hidden";
10352 this.clearOpacity();
10360 * Animates the transition of an element's dimensions from a starting height/width
10361 * to an ending height/width.
10364 // change height and width to 100x100 pixels
10365 el.scale(100, 100);
10367 // common config options shown with default values. The height and width will default to
10368 // the element's existing values if passed as null.
10371 [element's height], {
10376 * @param {Number} width The new width (pass undefined to keep the original width)
10377 * @param {Number} height The new height (pass undefined to keep the original height)
10378 * @param {Object} options (optional) Object literal with any of the Fx config options
10379 * @return {Roo.Element} The Element
10381 scale : function(w, h, o){
10382 this.shift(Roo.apply({}, o, {
10390 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10391 * Any of these properties not specified in the config object will not be changed. This effect
10392 * requires that at least one new dimension, position or opacity setting must be passed in on
10393 * the config object in order for the function to have any effect.
10396 // slide the element horizontally to x position 200 while changing the height and opacity
10397 el.shift({ x: 200, height: 50, opacity: .8 });
10399 // common config options shown with default values.
10401 width: [element's width],
10402 height: [element's height],
10403 x: [element's x position],
10404 y: [element's y position],
10405 opacity: [element's opacity],
10410 * @param {Object} options Object literal with any of the Fx config options
10411 * @return {Roo.Element} The Element
10413 shift : function(o){
10414 var el = this.getFxEl();
10416 el.queueFx(o, function(){
10417 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10418 if(w !== undefined){
10419 a.width = {to: this.adjustWidth(w)};
10421 if(h !== undefined){
10422 a.height = {to: this.adjustHeight(h)};
10424 if(x !== undefined || y !== undefined){
10426 x !== undefined ? x : this.getX(),
10427 y !== undefined ? y : this.getY()
10430 if(op !== undefined){
10431 a.opacity = {to: op};
10433 if(o.xy !== undefined){
10434 a.points = {to: o.xy};
10436 arguments.callee.anim = this.fxanim(a,
10437 o, 'motion', .35, "easeOut", function(){
10445 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10446 * ending point of the effect.
10449 // default: slide the element downward while fading out
10452 // custom: slide the element out to the right with a 2-second duration
10453 el.ghost('r', { duration: 2 });
10455 // common config options shown with default values
10463 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10464 * @param {Object} options (optional) Object literal with any of the Fx config options
10465 * @return {Roo.Element} The Element
10467 ghost : function(anchor, o){
10468 var el = this.getFxEl();
10471 el.queueFx(o, function(){
10472 anchor = anchor || "b";
10474 // restore values after effect
10475 var r = this.getFxRestore();
10476 var w = this.getWidth(),
10477 h = this.getHeight();
10479 var st = this.dom.style;
10481 var after = function(){
10483 el.setDisplayed(false);
10489 el.setPositioning(r.pos);
10490 st.width = r.width;
10491 st.height = r.height;
10496 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10497 switch(anchor.toLowerCase()){
10524 arguments.callee.anim = this.fxanim(a,
10534 * Ensures that all effects queued after syncFx is called on the element are
10535 * run concurrently. This is the opposite of {@link #sequenceFx}.
10536 * @return {Roo.Element} The Element
10538 syncFx : function(){
10539 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10548 * Ensures that all effects queued after sequenceFx is called on the element are
10549 * run in sequence. This is the opposite of {@link #syncFx}.
10550 * @return {Roo.Element} The Element
10552 sequenceFx : function(){
10553 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10555 concurrent : false,
10562 nextFx : function(){
10563 var ef = this.fxQueue[0];
10570 * Returns true if the element has any effects actively running or queued, else returns false.
10571 * @return {Boolean} True if element has active effects, else false
10573 hasActiveFx : function(){
10574 return this.fxQueue && this.fxQueue[0];
10578 * Stops any running effects and clears the element's internal effects queue if it contains
10579 * any additional effects that haven't started yet.
10580 * @return {Roo.Element} The Element
10582 stopFx : function(){
10583 if(this.hasActiveFx()){
10584 var cur = this.fxQueue[0];
10585 if(cur && cur.anim && cur.anim.isAnimated()){
10586 this.fxQueue = [cur]; // clear out others
10587 cur.anim.stop(true);
10594 beforeFx : function(o){
10595 if(this.hasActiveFx() && !o.concurrent){
10606 * Returns true if the element is currently blocking so that no other effect can be queued
10607 * until this effect is finished, else returns false if blocking is not set. This is commonly
10608 * used to ensure that an effect initiated by a user action runs to completion prior to the
10609 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10610 * @return {Boolean} True if blocking, else false
10612 hasFxBlock : function(){
10613 var q = this.fxQueue;
10614 return q && q[0] && q[0].block;
10618 queueFx : function(o, fn){
10622 if(!this.hasFxBlock()){
10623 Roo.applyIf(o, this.fxDefaults);
10625 var run = this.beforeFx(o);
10626 fn.block = o.block;
10627 this.fxQueue.push(fn);
10639 fxWrap : function(pos, o, vis){
10641 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10644 wrapXY = this.getXY();
10646 var div = document.createElement("div");
10647 div.style.visibility = vis;
10648 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10649 wrap.setPositioning(pos);
10650 if(wrap.getStyle("position") == "static"){
10651 wrap.position("relative");
10653 this.clearPositioning('auto');
10655 wrap.dom.appendChild(this.dom);
10657 wrap.setXY(wrapXY);
10664 fxUnwrap : function(wrap, pos, o){
10665 this.clearPositioning();
10666 this.setPositioning(pos);
10668 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10674 getFxRestore : function(){
10675 var st = this.dom.style;
10676 return {pos: this.getPositioning(), width: st.width, height : st.height};
10680 afterFx : function(o){
10682 this.applyStyles(o.afterStyle);
10685 this.addClass(o.afterCls);
10687 if(o.remove === true){
10690 Roo.callback(o.callback, o.scope, [this]);
10692 this.fxQueue.shift();
10698 getFxEl : function(){ // support for composite element fx
10699 return Roo.get(this.dom);
10703 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10704 animType = animType || 'run';
10706 var anim = Roo.lib.Anim[animType](
10708 (opt.duration || defaultDur) || .35,
10709 (opt.easing || defaultEase) || 'easeOut',
10711 Roo.callback(cb, this);
10720 // backwords compat
10721 Roo.Fx.resize = Roo.Fx.scale;
10723 //When included, Roo.Fx is automatically applied to Element so that all basic
10724 //effects are available directly via the Element API
10725 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10727 * Ext JS Library 1.1.1
10728 * Copyright(c) 2006-2007, Ext JS, LLC.
10730 * Originally Released Under LGPL - original licence link has changed is not relivant.
10733 * <script type="text/javascript">
10738 * @class Roo.CompositeElement
10739 * Standard composite class. Creates a Roo.Element for every element in the collection.
10741 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10742 * actions will be performed on all the elements in this collection.</b>
10744 * All methods return <i>this</i> and can be chained.
10746 var els = Roo.select("#some-el div.some-class", true);
10747 // or select directly from an existing element
10748 var el = Roo.get('some-el');
10749 el.select('div.some-class', true);
10751 els.setWidth(100); // all elements become 100 width
10752 els.hide(true); // all elements fade out and hide
10754 els.setWidth(100).hide(true);
10757 Roo.CompositeElement = function(els){
10758 this.elements = [];
10759 this.addElements(els);
10761 Roo.CompositeElement.prototype = {
10763 addElements : function(els){
10764 if(!els) return this;
10765 if(typeof els == "string"){
10766 els = Roo.Element.selectorFunction(els);
10768 var yels = this.elements;
10769 var index = yels.length-1;
10770 for(var i = 0, len = els.length; i < len; i++) {
10771 yels[++index] = Roo.get(els[i]);
10777 * Clears this composite and adds the elements returned by the passed selector.
10778 * @param {String/Array} els A string CSS selector, an array of elements or an element
10779 * @return {CompositeElement} this
10781 fill : function(els){
10782 this.elements = [];
10788 * Filters this composite to only elements that match the passed selector.
10789 * @param {String} selector A string CSS selector
10790 * @return {CompositeElement} this
10792 filter : function(selector){
10794 this.each(function(el){
10795 if(el.is(selector)){
10796 els[els.length] = el.dom;
10803 invoke : function(fn, args){
10804 var els = this.elements;
10805 for(var i = 0, len = els.length; i < len; i++) {
10806 Roo.Element.prototype[fn].apply(els[i], args);
10811 * Adds elements to this composite.
10812 * @param {String/Array} els A string CSS selector, an array of elements or an element
10813 * @return {CompositeElement} this
10815 add : function(els){
10816 if(typeof els == "string"){
10817 this.addElements(Roo.Element.selectorFunction(els));
10818 }else if(els.length !== undefined){
10819 this.addElements(els);
10821 this.addElements([els]);
10826 * Calls the passed function passing (el, this, index) for each element in this composite.
10827 * @param {Function} fn The function to call
10828 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10829 * @return {CompositeElement} this
10831 each : function(fn, scope){
10832 var els = this.elements;
10833 for(var i = 0, len = els.length; i < len; i++){
10834 if(fn.call(scope || els[i], els[i], this, i) === false) {
10842 * Returns the Element object at the specified index
10843 * @param {Number} index
10844 * @return {Roo.Element}
10846 item : function(index){
10847 return this.elements[index] || null;
10851 * Returns the first Element
10852 * @return {Roo.Element}
10854 first : function(){
10855 return this.item(0);
10859 * Returns the last Element
10860 * @return {Roo.Element}
10863 return this.item(this.elements.length-1);
10867 * Returns the number of elements in this composite
10870 getCount : function(){
10871 return this.elements.length;
10875 * Returns true if this composite contains the passed element
10878 contains : function(el){
10879 return this.indexOf(el) !== -1;
10883 * Returns true if this composite contains the passed element
10886 indexOf : function(el){
10887 return this.elements.indexOf(Roo.get(el));
10892 * Removes the specified element(s).
10893 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10894 * or an array of any of those.
10895 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10896 * @return {CompositeElement} this
10898 removeElement : function(el, removeDom){
10899 if(el instanceof Array){
10900 for(var i = 0, len = el.length; i < len; i++){
10901 this.removeElement(el[i]);
10905 var index = typeof el == 'number' ? el : this.indexOf(el);
10908 var d = this.elements[index];
10912 d.parentNode.removeChild(d);
10915 this.elements.splice(index, 1);
10921 * Replaces the specified element with the passed element.
10922 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10924 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10925 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10926 * @return {CompositeElement} this
10928 replaceElement : function(el, replacement, domReplace){
10929 var index = typeof el == 'number' ? el : this.indexOf(el);
10932 this.elements[index].replaceWith(replacement);
10934 this.elements.splice(index, 1, Roo.get(replacement))
10941 * Removes all elements.
10943 clear : function(){
10944 this.elements = [];
10948 Roo.CompositeElement.createCall = function(proto, fnName){
10949 if(!proto[fnName]){
10950 proto[fnName] = function(){
10951 return this.invoke(fnName, arguments);
10955 for(var fnName in Roo.Element.prototype){
10956 if(typeof Roo.Element.prototype[fnName] == "function"){
10957 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10963 * Ext JS Library 1.1.1
10964 * Copyright(c) 2006-2007, Ext JS, LLC.
10966 * Originally Released Under LGPL - original licence link has changed is not relivant.
10969 * <script type="text/javascript">
10973 * @class Roo.CompositeElementLite
10974 * @extends Roo.CompositeElement
10975 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10977 var els = Roo.select("#some-el div.some-class");
10978 // or select directly from an existing element
10979 var el = Roo.get('some-el');
10980 el.select('div.some-class');
10982 els.setWidth(100); // all elements become 100 width
10983 els.hide(true); // all elements fade out and hide
10985 els.setWidth(100).hide(true);
10986 </code></pre><br><br>
10987 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10988 * actions will be performed on all the elements in this collection.</b>
10990 Roo.CompositeElementLite = function(els){
10991 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10992 this.el = new Roo.Element.Flyweight();
10994 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10995 addElements : function(els){
10997 if(els instanceof Array){
10998 this.elements = this.elements.concat(els);
11000 var yels = this.elements;
11001 var index = yels.length-1;
11002 for(var i = 0, len = els.length; i < len; i++) {
11003 yels[++index] = els[i];
11009 invoke : function(fn, args){
11010 var els = this.elements;
11012 for(var i = 0, len = els.length; i < len; i++) {
11014 Roo.Element.prototype[fn].apply(el, args);
11019 * Returns a flyweight Element of the dom element object at the specified index
11020 * @param {Number} index
11021 * @return {Roo.Element}
11023 item : function(index){
11024 if(!this.elements[index]){
11027 this.el.dom = this.elements[index];
11031 // fixes scope with flyweight
11032 addListener : function(eventName, handler, scope, opt){
11033 var els = this.elements;
11034 for(var i = 0, len = els.length; i < len; i++) {
11035 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
11041 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
11042 * passed is the flyweight (shared) Roo.Element instance, so if you require a
11043 * a reference to the dom node, use el.dom.</b>
11044 * @param {Function} fn The function to call
11045 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
11046 * @return {CompositeElement} this
11048 each : function(fn, scope){
11049 var els = this.elements;
11051 for(var i = 0, len = els.length; i < len; i++){
11053 if(fn.call(scope || el, el, this, i) === false){
11060 indexOf : function(el){
11061 return this.elements.indexOf(Roo.getDom(el));
11064 replaceElement : function(el, replacement, domReplace){
11065 var index = typeof el == 'number' ? el : this.indexOf(el);
11067 replacement = Roo.getDom(replacement);
11069 var d = this.elements[index];
11070 d.parentNode.insertBefore(replacement, d);
11071 d.parentNode.removeChild(d);
11073 this.elements.splice(index, 1, replacement);
11078 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11082 * Ext JS Library 1.1.1
11083 * Copyright(c) 2006-2007, Ext JS, LLC.
11085 * Originally Released Under LGPL - original licence link has changed is not relivant.
11088 * <script type="text/javascript">
11094 * @class Roo.data.Connection
11095 * @extends Roo.util.Observable
11096 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11097 * either to a configured URL, or to a URL specified at request time.<br><br>
11099 * Requests made by this class are asynchronous, and will return immediately. No data from
11100 * the server will be available to the statement immediately following the {@link #request} call.
11101 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11103 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11104 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11105 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11106 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11107 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11108 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11109 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11110 * standard DOM methods.
11112 * @param {Object} config a configuration object.
11114 Roo.data.Connection = function(config){
11115 Roo.apply(this, config);
11118 * @event beforerequest
11119 * Fires before a network request is made to retrieve a data object.
11120 * @param {Connection} conn This Connection object.
11121 * @param {Object} options The options config object passed to the {@link #request} method.
11123 "beforerequest" : true,
11125 * @event requestcomplete
11126 * Fires if the request was successfully completed.
11127 * @param {Connection} conn This Connection object.
11128 * @param {Object} response The XHR object containing the response data.
11129 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11130 * @param {Object} options The options config object passed to the {@link #request} method.
11132 "requestcomplete" : true,
11134 * @event requestexception
11135 * Fires if an error HTTP status was returned from the server.
11136 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11137 * @param {Connection} conn This Connection object.
11138 * @param {Object} response The XHR object containing the response data.
11139 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11140 * @param {Object} options The options config object passed to the {@link #request} method.
11142 "requestexception" : true
11144 Roo.data.Connection.superclass.constructor.call(this);
11147 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11149 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11152 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11153 * extra parameters to each request made by this object. (defaults to undefined)
11156 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11157 * to each request made by this object. (defaults to undefined)
11160 * @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)
11163 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11167 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11173 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11176 disableCaching: true,
11179 * Sends an HTTP request to a remote server.
11180 * @param {Object} options An object which may contain the following properties:<ul>
11181 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11182 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11183 * request, a url encoded string or a function to call to get either.</li>
11184 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11185 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11186 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11187 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11188 * <li>options {Object} The parameter to the request call.</li>
11189 * <li>success {Boolean} True if the request succeeded.</li>
11190 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11192 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11193 * The callback is passed the following parameters:<ul>
11194 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11195 * <li>options {Object} The parameter to the request call.</li>
11197 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11198 * The callback is passed the following parameters:<ul>
11199 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11200 * <li>options {Object} The parameter to the request call.</li>
11202 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11203 * for the callback function. Defaults to the browser window.</li>
11204 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11205 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11206 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11207 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11208 * params for the post data. Any params will be appended to the URL.</li>
11209 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11211 * @return {Number} transactionId
11213 request : function(o){
11214 if(this.fireEvent("beforerequest", this, o) !== false){
11217 if(typeof p == "function"){
11218 p = p.call(o.scope||window, o);
11220 if(typeof p == "object"){
11221 p = Roo.urlEncode(o.params);
11223 if(this.extraParams){
11224 var extras = Roo.urlEncode(this.extraParams);
11225 p = p ? (p + '&' + extras) : extras;
11228 var url = o.url || this.url;
11229 if(typeof url == 'function'){
11230 url = url.call(o.scope||window, o);
11234 var form = Roo.getDom(o.form);
11235 url = url || form.action;
11237 var enctype = form.getAttribute("enctype");
11238 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11239 return this.doFormUpload(o, p, url);
11241 var f = Roo.lib.Ajax.serializeForm(form);
11242 p = p ? (p + '&' + f) : f;
11245 var hs = o.headers;
11246 if(this.defaultHeaders){
11247 hs = Roo.apply(hs || {}, this.defaultHeaders);
11254 success: this.handleResponse,
11255 failure: this.handleFailure,
11257 argument: {options: o},
11258 timeout : this.timeout
11261 var method = o.method||this.method||(p ? "POST" : "GET");
11263 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11264 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11267 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11271 }else if(this.autoAbort !== false){
11275 if((method == 'GET' && p) || o.xmlData){
11276 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11279 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11280 return this.transId;
11282 Roo.callback(o.callback, o.scope, [o, null, null]);
11288 * Determine whether this object has a request outstanding.
11289 * @param {Number} transactionId (Optional) defaults to the last transaction
11290 * @return {Boolean} True if there is an outstanding request.
11292 isLoading : function(transId){
11294 return Roo.lib.Ajax.isCallInProgress(transId);
11296 return this.transId ? true : false;
11301 * Aborts any outstanding request.
11302 * @param {Number} transactionId (Optional) defaults to the last transaction
11304 abort : function(transId){
11305 if(transId || this.isLoading()){
11306 Roo.lib.Ajax.abort(transId || this.transId);
11311 handleResponse : function(response){
11312 this.transId = false;
11313 var options = response.argument.options;
11314 response.argument = options ? options.argument : null;
11315 this.fireEvent("requestcomplete", this, response, options);
11316 Roo.callback(options.success, options.scope, [response, options]);
11317 Roo.callback(options.callback, options.scope, [options, true, response]);
11321 handleFailure : function(response, e){
11322 this.transId = false;
11323 var options = response.argument.options;
11324 response.argument = options ? options.argument : null;
11325 this.fireEvent("requestexception", this, response, options, e);
11326 Roo.callback(options.failure, options.scope, [response, options]);
11327 Roo.callback(options.callback, options.scope, [options, false, response]);
11331 doFormUpload : function(o, ps, url){
11333 var frame = document.createElement('iframe');
11336 frame.className = 'x-hidden';
11338 frame.src = Roo.SSL_SECURE_URL;
11340 document.body.appendChild(frame);
11343 document.frames[id].name = id;
11346 var form = Roo.getDom(o.form);
11348 form.method = 'POST';
11349 form.enctype = form.encoding = 'multipart/form-data';
11355 if(ps){ // add dynamic params
11357 ps = Roo.urlDecode(ps, false);
11359 if(ps.hasOwnProperty(k)){
11360 hd = document.createElement('input');
11361 hd.type = 'hidden';
11364 form.appendChild(hd);
11371 var r = { // bogus response object
11376 r.argument = o ? o.argument : null;
11381 doc = frame.contentWindow.document;
11383 doc = (frame.contentDocument || window.frames[id].document);
11385 if(doc && doc.body){
11386 r.responseText = doc.body.innerHTML;
11388 if(doc && doc.XMLDocument){
11389 r.responseXML = doc.XMLDocument;
11391 r.responseXML = doc;
11398 Roo.EventManager.removeListener(frame, 'load', cb, this);
11400 this.fireEvent("requestcomplete", this, r, o);
11401 Roo.callback(o.success, o.scope, [r, o]);
11402 Roo.callback(o.callback, o.scope, [o, true, r]);
11404 setTimeout(function(){document.body.removeChild(frame);}, 100);
11407 Roo.EventManager.on(frame, 'load', cb, this);
11410 if(hiddens){ // remove dynamic params
11411 for(var i = 0, len = hiddens.length; i < len; i++){
11412 form.removeChild(hiddens[i]);
11420 * @extends Roo.data.Connection
11421 * Global Ajax request class.
11425 Roo.Ajax = new Roo.data.Connection({
11428 * @cfg {String} url @hide
11431 * @cfg {Object} extraParams @hide
11434 * @cfg {Object} defaultHeaders @hide
11437 * @cfg {String} method (Optional) @hide
11440 * @cfg {Number} timeout (Optional) @hide
11443 * @cfg {Boolean} autoAbort (Optional) @hide
11447 * @cfg {Boolean} disableCaching (Optional) @hide
11451 * @property disableCaching
11452 * True to add a unique cache-buster param to GET requests. (defaults to true)
11457 * The default URL to be used for requests to the server. (defaults to undefined)
11461 * @property extraParams
11462 * An object containing properties which are used as
11463 * extra parameters to each request made by this object. (defaults to undefined)
11467 * @property defaultHeaders
11468 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11473 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11477 * @property timeout
11478 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11483 * @property autoAbort
11484 * Whether a new request should abort any pending requests. (defaults to false)
11490 * Serialize the passed form into a url encoded string
11491 * @param {String/HTMLElement} form
11494 serializeForm : function(form){
11495 return Roo.lib.Ajax.serializeForm(form);
11499 * Ext JS Library 1.1.1
11500 * Copyright(c) 2006-2007, Ext JS, LLC.
11502 * Originally Released Under LGPL - original licence link has changed is not relivant.
11505 * <script type="text/javascript">
11510 * @extends Roo.data.Connection
11511 * Global Ajax request class.
11513 * @instanceOf Roo.data.Connection
11515 Roo.Ajax = new Roo.data.Connection({
11524 * @cfg {String} url @hide
11527 * @cfg {Object} extraParams @hide
11530 * @cfg {Object} defaultHeaders @hide
11533 * @cfg {String} method (Optional) @hide
11536 * @cfg {Number} timeout (Optional) @hide
11539 * @cfg {Boolean} autoAbort (Optional) @hide
11543 * @cfg {Boolean} disableCaching (Optional) @hide
11547 * @property disableCaching
11548 * True to add a unique cache-buster param to GET requests. (defaults to true)
11553 * The default URL to be used for requests to the server. (defaults to undefined)
11557 * @property extraParams
11558 * An object containing properties which are used as
11559 * extra parameters to each request made by this object. (defaults to undefined)
11563 * @property defaultHeaders
11564 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11569 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11573 * @property timeout
11574 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11579 * @property autoAbort
11580 * Whether a new request should abort any pending requests. (defaults to false)
11586 * Serialize the passed form into a url encoded string
11587 * @param {String/HTMLElement} form
11590 serializeForm : function(form){
11591 return Roo.lib.Ajax.serializeForm(form);
11595 * Ext JS Library 1.1.1
11596 * Copyright(c) 2006-2007, Ext JS, LLC.
11598 * Originally Released Under LGPL - original licence link has changed is not relivant.
11601 * <script type="text/javascript">
11606 * @class Roo.UpdateManager
11607 * @extends Roo.util.Observable
11608 * Provides AJAX-style update for Element object.<br><br>
11611 * // Get it from a Roo.Element object
11612 * var el = Roo.get("foo");
11613 * var mgr = el.getUpdateManager();
11614 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11616 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11618 * // or directly (returns the same UpdateManager instance)
11619 * var mgr = new Roo.UpdateManager("myElementId");
11620 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11621 * mgr.on("update", myFcnNeedsToKnow);
11623 // short handed call directly from the element object
11624 Roo.get("foo").load({
11628 text: "Loading Foo..."
11632 * Create new UpdateManager directly.
11633 * @param {String/HTMLElement/Roo.Element} el The element to update
11634 * @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).
11636 Roo.UpdateManager = function(el, forceNew){
11638 if(!forceNew && el.updateManager){
11639 return el.updateManager;
11642 * The Element object
11643 * @type Roo.Element
11647 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11650 this.defaultUrl = null;
11654 * @event beforeupdate
11655 * Fired before an update is made, return false from your handler and the update is cancelled.
11656 * @param {Roo.Element} el
11657 * @param {String/Object/Function} url
11658 * @param {String/Object} params
11660 "beforeupdate": true,
11663 * Fired after successful update is made.
11664 * @param {Roo.Element} el
11665 * @param {Object} oResponseObject The response Object
11670 * Fired on update failure.
11671 * @param {Roo.Element} el
11672 * @param {Object} oResponseObject The response Object
11676 var d = Roo.UpdateManager.defaults;
11678 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11681 this.sslBlankUrl = d.sslBlankUrl;
11683 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11686 this.disableCaching = d.disableCaching;
11688 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11691 this.indicatorText = d.indicatorText;
11693 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11696 this.showLoadIndicator = d.showLoadIndicator;
11698 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11701 this.timeout = d.timeout;
11704 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11707 this.loadScripts = d.loadScripts;
11710 * Transaction object of current executing transaction
11712 this.transaction = null;
11717 this.autoRefreshProcId = null;
11719 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11722 this.refreshDelegate = this.refresh.createDelegate(this);
11724 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11727 this.updateDelegate = this.update.createDelegate(this);
11729 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11732 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11736 this.successDelegate = this.processSuccess.createDelegate(this);
11740 this.failureDelegate = this.processFailure.createDelegate(this);
11742 if(!this.renderer){
11744 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11746 this.renderer = new Roo.UpdateManager.BasicRenderer();
11749 Roo.UpdateManager.superclass.constructor.call(this);
11752 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11754 * Get the Element this UpdateManager is bound to
11755 * @return {Roo.Element} The element
11757 getEl : function(){
11761 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11762 * @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:
11765 url: "your-url.php",<br/>
11766 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11767 callback: yourFunction,<br/>
11768 scope: yourObject, //(optional scope) <br/>
11769 discardUrl: false, <br/>
11770 nocache: false,<br/>
11771 text: "Loading...",<br/>
11773 scripts: false<br/>
11776 * The only required property is url. The optional properties nocache, text and scripts
11777 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11778 * @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}
11779 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11780 * @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.
11782 update : function(url, params, callback, discardUrl){
11783 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11784 var method = this.method, cfg;
11785 if(typeof url == "object"){ // must be config object
11788 params = params || cfg.params;
11789 callback = callback || cfg.callback;
11790 discardUrl = discardUrl || cfg.discardUrl;
11791 if(callback && cfg.scope){
11792 callback = callback.createDelegate(cfg.scope);
11794 if(typeof cfg.method != "undefined"){method = cfg.method;};
11795 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11796 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11797 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11798 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11800 this.showLoading();
11802 this.defaultUrl = url;
11804 if(typeof url == "function"){
11805 url = url.call(this);
11808 method = method || (params ? "POST" : "GET");
11809 if(method == "GET"){
11810 url = this.prepareUrl(url);
11813 var o = Roo.apply(cfg ||{}, {
11816 success: this.successDelegate,
11817 failure: this.failureDelegate,
11818 callback: undefined,
11819 timeout: (this.timeout*1000),
11820 argument: {"url": url, "form": null, "callback": callback, "params": params}
11823 this.transaction = Roo.Ajax.request(o);
11828 * 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.
11829 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11830 * @param {String/HTMLElement} form The form Id or form element
11831 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11832 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11833 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11835 formUpdate : function(form, url, reset, callback){
11836 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11837 if(typeof url == "function"){
11838 url = url.call(this);
11840 form = Roo.getDom(form);
11841 this.transaction = Roo.Ajax.request({
11844 success: this.successDelegate,
11845 failure: this.failureDelegate,
11846 timeout: (this.timeout*1000),
11847 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11849 this.showLoading.defer(1, this);
11854 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11855 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11857 refresh : function(callback){
11858 if(this.defaultUrl == null){
11861 this.update(this.defaultUrl, null, callback, true);
11865 * Set this element to auto refresh.
11866 * @param {Number} interval How often to update (in seconds).
11867 * @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)
11868 * @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}
11869 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11870 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11872 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11874 this.update(url || this.defaultUrl, params, callback, true);
11876 if(this.autoRefreshProcId){
11877 clearInterval(this.autoRefreshProcId);
11879 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11883 * Stop auto refresh on this element.
11885 stopAutoRefresh : function(){
11886 if(this.autoRefreshProcId){
11887 clearInterval(this.autoRefreshProcId);
11888 delete this.autoRefreshProcId;
11892 isAutoRefreshing : function(){
11893 return this.autoRefreshProcId ? true : false;
11896 * Called to update the element to "Loading" state. Override to perform custom action.
11898 showLoading : function(){
11899 if(this.showLoadIndicator){
11900 this.el.update(this.indicatorText);
11905 * Adds unique parameter to query string if disableCaching = true
11908 prepareUrl : function(url){
11909 if(this.disableCaching){
11910 var append = "_dc=" + (new Date().getTime());
11911 if(url.indexOf("?") !== -1){
11912 url += "&" + append;
11914 url += "?" + append;
11923 processSuccess : function(response){
11924 this.transaction = null;
11925 if(response.argument.form && response.argument.reset){
11926 try{ // put in try/catch since some older FF releases had problems with this
11927 response.argument.form.reset();
11930 if(this.loadScripts){
11931 this.renderer.render(this.el, response, this,
11932 this.updateComplete.createDelegate(this, [response]));
11934 this.renderer.render(this.el, response, this);
11935 this.updateComplete(response);
11939 updateComplete : function(response){
11940 this.fireEvent("update", this.el, response);
11941 if(typeof response.argument.callback == "function"){
11942 response.argument.callback(this.el, true, response);
11949 processFailure : function(response){
11950 this.transaction = null;
11951 this.fireEvent("failure", this.el, response);
11952 if(typeof response.argument.callback == "function"){
11953 response.argument.callback(this.el, false, response);
11958 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11959 * @param {Object} renderer The object implementing the render() method
11961 setRenderer : function(renderer){
11962 this.renderer = renderer;
11965 getRenderer : function(){
11966 return this.renderer;
11970 * Set the defaultUrl used for updates
11971 * @param {String/Function} defaultUrl The url or a function to call to get the url
11973 setDefaultUrl : function(defaultUrl){
11974 this.defaultUrl = defaultUrl;
11978 * Aborts the executing transaction
11980 abort : function(){
11981 if(this.transaction){
11982 Roo.Ajax.abort(this.transaction);
11987 * Returns true if an update is in progress
11988 * @return {Boolean}
11990 isUpdating : function(){
11991 if(this.transaction){
11992 return Roo.Ajax.isLoading(this.transaction);
11999 * @class Roo.UpdateManager.defaults
12000 * @static (not really - but it helps the doc tool)
12001 * The defaults collection enables customizing the default properties of UpdateManager
12003 Roo.UpdateManager.defaults = {
12005 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
12011 * True to process scripts by default (Defaults to false).
12014 loadScripts : false,
12017 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
12020 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
12022 * Whether to append unique parameter on get request to disable caching (Defaults to false).
12025 disableCaching : false,
12027 * Whether to show indicatorText when loading (Defaults to true).
12030 showLoadIndicator : true,
12032 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
12035 indicatorText : '<div class="loading-indicator">Loading...</div>'
12039 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
12041 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
12042 * @param {String/HTMLElement/Roo.Element} el The element to update
12043 * @param {String} url The url
12044 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
12045 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
12048 * @member Roo.UpdateManager
12050 Roo.UpdateManager.updateElement = function(el, url, params, options){
12051 var um = Roo.get(el, true).getUpdateManager();
12052 Roo.apply(um, options);
12053 um.update(url, params, options ? options.callback : null);
12055 // alias for backwards compat
12056 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12058 * @class Roo.UpdateManager.BasicRenderer
12059 * Default Content renderer. Updates the elements innerHTML with the responseText.
12061 Roo.UpdateManager.BasicRenderer = function(){};
12063 Roo.UpdateManager.BasicRenderer.prototype = {
12065 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12066 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12067 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12068 * @param {Roo.Element} el The element being rendered
12069 * @param {Object} response The YUI Connect response object
12070 * @param {UpdateManager} updateManager The calling update manager
12071 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12073 render : function(el, response, updateManager, callback){
12074 el.update(response.responseText, updateManager.loadScripts, callback);
12079 * Ext JS Library 1.1.1
12080 * Copyright(c) 2006-2007, Ext JS, LLC.
12082 * Originally Released Under LGPL - original licence link has changed is not relivant.
12085 * <script type="text/javascript">
12089 * @class Roo.util.DelayedTask
12090 * Provides a convenient method of performing setTimeout where a new
12091 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12092 * You can use this class to buffer
12093 * the keypress events for a certain number of milliseconds, and perform only if they stop
12094 * for that amount of time.
12095 * @constructor The parameters to this constructor serve as defaults and are not required.
12096 * @param {Function} fn (optional) The default function to timeout
12097 * @param {Object} scope (optional) The default scope of that timeout
12098 * @param {Array} args (optional) The default Array of arguments
12100 Roo.util.DelayedTask = function(fn, scope, args){
12101 var id = null, d, t;
12103 var call = function(){
12104 var now = new Date().getTime();
12108 fn.apply(scope, args || []);
12112 * Cancels any pending timeout and queues a new one
12113 * @param {Number} delay The milliseconds to delay
12114 * @param {Function} newFn (optional) Overrides function passed to constructor
12115 * @param {Object} newScope (optional) Overrides scope passed to constructor
12116 * @param {Array} newArgs (optional) Overrides args passed to constructor
12118 this.delay = function(delay, newFn, newScope, newArgs){
12119 if(id && delay != d){
12123 t = new Date().getTime();
12125 scope = newScope || scope;
12126 args = newArgs || args;
12128 id = setInterval(call, d);
12133 * Cancel the last queued timeout
12135 this.cancel = function(){
12143 * Ext JS Library 1.1.1
12144 * Copyright(c) 2006-2007, Ext JS, LLC.
12146 * Originally Released Under LGPL - original licence link has changed is not relivant.
12149 * <script type="text/javascript">
12153 Roo.util.TaskRunner = function(interval){
12154 interval = interval || 10;
12155 var tasks = [], removeQueue = [];
12157 var running = false;
12159 var stopThread = function(){
12165 var startThread = function(){
12168 id = setInterval(runTasks, interval);
12172 var removeTask = function(task){
12173 removeQueue.push(task);
12179 var runTasks = function(){
12180 if(removeQueue.length > 0){
12181 for(var i = 0, len = removeQueue.length; i < len; i++){
12182 tasks.remove(removeQueue[i]);
12185 if(tasks.length < 1){
12190 var now = new Date().getTime();
12191 for(var i = 0, len = tasks.length; i < len; ++i){
12193 var itime = now - t.taskRunTime;
12194 if(t.interval <= itime){
12195 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12196 t.taskRunTime = now;
12197 if(rt === false || t.taskRunCount === t.repeat){
12202 if(t.duration && t.duration <= (now - t.taskStartTime)){
12209 * Queues a new task.
12210 * @param {Object} task
12212 this.start = function(task){
12214 task.taskStartTime = new Date().getTime();
12215 task.taskRunTime = 0;
12216 task.taskRunCount = 0;
12221 this.stop = function(task){
12226 this.stopAll = function(){
12228 for(var i = 0, len = tasks.length; i < len; i++){
12229 if(tasks[i].onStop){
12238 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12240 * Ext JS Library 1.1.1
12241 * Copyright(c) 2006-2007, Ext JS, LLC.
12243 * Originally Released Under LGPL - original licence link has changed is not relivant.
12246 * <script type="text/javascript">
12251 * @class Roo.util.MixedCollection
12252 * @extends Roo.util.Observable
12253 * A Collection class that maintains both numeric indexes and keys and exposes events.
12255 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12256 * collection (defaults to false)
12257 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12258 * and return the key value for that item. This is used when available to look up the key on items that
12259 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12260 * equivalent to providing an implementation for the {@link #getKey} method.
12262 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12270 * Fires when the collection is cleared.
12275 * Fires when an item is added to the collection.
12276 * @param {Number} index The index at which the item was added.
12277 * @param {Object} o The item added.
12278 * @param {String} key The key associated with the added item.
12283 * Fires when an item is replaced in the collection.
12284 * @param {String} key he key associated with the new added.
12285 * @param {Object} old The item being replaced.
12286 * @param {Object} new The new item.
12291 * Fires when an item is removed from the collection.
12292 * @param {Object} o The item being removed.
12293 * @param {String} key (optional) The key associated with the removed item.
12298 this.allowFunctions = allowFunctions === true;
12300 this.getKey = keyFn;
12302 Roo.util.MixedCollection.superclass.constructor.call(this);
12305 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12306 allowFunctions : false,
12309 * Adds an item to the collection.
12310 * @param {String} key The key to associate with the item
12311 * @param {Object} o The item to add.
12312 * @return {Object} The item added.
12314 add : function(key, o){
12315 if(arguments.length == 1){
12317 key = this.getKey(o);
12319 if(typeof key == "undefined" || key === null){
12321 this.items.push(o);
12322 this.keys.push(null);
12324 var old = this.map[key];
12326 return this.replace(key, o);
12329 this.items.push(o);
12331 this.keys.push(key);
12333 this.fireEvent("add", this.length-1, o, key);
12338 * MixedCollection has a generic way to fetch keys if you implement getKey.
12341 var mc = new Roo.util.MixedCollection();
12342 mc.add(someEl.dom.id, someEl);
12343 mc.add(otherEl.dom.id, otherEl);
12347 var mc = new Roo.util.MixedCollection();
12348 mc.getKey = function(el){
12354 // or via the constructor
12355 var mc = new Roo.util.MixedCollection(false, function(el){
12361 * @param o {Object} The item for which to find the key.
12362 * @return {Object} The key for the passed item.
12364 getKey : function(o){
12369 * Replaces an item in the collection.
12370 * @param {String} key The key associated with the item to replace, or the item to replace.
12371 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12372 * @return {Object} The new item.
12374 replace : function(key, o){
12375 if(arguments.length == 1){
12377 key = this.getKey(o);
12379 var old = this.item(key);
12380 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12381 return this.add(key, o);
12383 var index = this.indexOfKey(key);
12384 this.items[index] = o;
12386 this.fireEvent("replace", key, old, o);
12391 * Adds all elements of an Array or an Object to the collection.
12392 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12393 * an Array of values, each of which are added to the collection.
12395 addAll : function(objs){
12396 if(arguments.length > 1 || objs instanceof Array){
12397 var args = arguments.length > 1 ? arguments : objs;
12398 for(var i = 0, len = args.length; i < len; i++){
12402 for(var key in objs){
12403 if(this.allowFunctions || typeof objs[key] != "function"){
12404 this.add(key, objs[key]);
12411 * Executes the specified function once for every item in the collection, passing each
12412 * item as the first and only parameter. returning false from the function will stop the iteration.
12413 * @param {Function} fn The function to execute for each item.
12414 * @param {Object} scope (optional) The scope in which to execute the function.
12416 each : function(fn, scope){
12417 var items = [].concat(this.items); // each safe for removal
12418 for(var i = 0, len = items.length; i < len; i++){
12419 if(fn.call(scope || items[i], items[i], i, len) === false){
12426 * Executes the specified function once for every key in the collection, passing each
12427 * key, and its associated item as the first two parameters.
12428 * @param {Function} fn The function to execute for each item.
12429 * @param {Object} scope (optional) The scope in which to execute the function.
12431 eachKey : function(fn, scope){
12432 for(var i = 0, len = this.keys.length; i < len; i++){
12433 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12438 * Returns the first item in the collection which elicits a true return value from the
12439 * passed selection function.
12440 * @param {Function} fn The selection function to execute for each item.
12441 * @param {Object} scope (optional) The scope in which to execute the function.
12442 * @return {Object} The first item in the collection which returned true from the selection function.
12444 find : function(fn, scope){
12445 for(var i = 0, len = this.items.length; i < len; i++){
12446 if(fn.call(scope || window, this.items[i], this.keys[i])){
12447 return this.items[i];
12454 * Inserts an item at the specified index in the collection.
12455 * @param {Number} index The index to insert the item at.
12456 * @param {String} key The key to associate with the new item, or the item itself.
12457 * @param {Object} o (optional) If the second parameter was a key, the new item.
12458 * @return {Object} The item inserted.
12460 insert : function(index, key, o){
12461 if(arguments.length == 2){
12463 key = this.getKey(o);
12465 if(index >= this.length){
12466 return this.add(key, o);
12469 this.items.splice(index, 0, o);
12470 if(typeof key != "undefined" && key != null){
12473 this.keys.splice(index, 0, key);
12474 this.fireEvent("add", index, o, key);
12479 * Removed an item from the collection.
12480 * @param {Object} o The item to remove.
12481 * @return {Object} The item removed.
12483 remove : function(o){
12484 return this.removeAt(this.indexOf(o));
12488 * Remove an item from a specified index in the collection.
12489 * @param {Number} index The index within the collection of the item to remove.
12491 removeAt : function(index){
12492 if(index < this.length && index >= 0){
12494 var o = this.items[index];
12495 this.items.splice(index, 1);
12496 var key = this.keys[index];
12497 if(typeof key != "undefined"){
12498 delete this.map[key];
12500 this.keys.splice(index, 1);
12501 this.fireEvent("remove", o, key);
12506 * Removed an item associated with the passed key fom the collection.
12507 * @param {String} key The key of the item to remove.
12509 removeKey : function(key){
12510 return this.removeAt(this.indexOfKey(key));
12514 * Returns the number of items in the collection.
12515 * @return {Number} the number of items in the collection.
12517 getCount : function(){
12518 return this.length;
12522 * Returns index within the collection of the passed Object.
12523 * @param {Object} o The item to find the index of.
12524 * @return {Number} index of the item.
12526 indexOf : function(o){
12527 if(!this.items.indexOf){
12528 for(var i = 0, len = this.items.length; i < len; i++){
12529 if(this.items[i] == o) return i;
12533 return this.items.indexOf(o);
12538 * Returns index within the collection of the passed key.
12539 * @param {String} key The key to find the index of.
12540 * @return {Number} index of the key.
12542 indexOfKey : function(key){
12543 if(!this.keys.indexOf){
12544 for(var i = 0, len = this.keys.length; i < len; i++){
12545 if(this.keys[i] == key) return i;
12549 return this.keys.indexOf(key);
12554 * Returns the item associated with the passed key OR index. Key has priority over index.
12555 * @param {String/Number} key The key or index of the item.
12556 * @return {Object} The item associated with the passed key.
12558 item : function(key){
12559 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12560 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12564 * Returns the item at the specified index.
12565 * @param {Number} index The index of the item.
12568 itemAt : function(index){
12569 return this.items[index];
12573 * Returns the item associated with the passed key.
12574 * @param {String/Number} key The key of the item.
12575 * @return {Object} The item associated with the passed key.
12577 key : function(key){
12578 return this.map[key];
12582 * Returns true if the collection contains the passed Object as an item.
12583 * @param {Object} o The Object to look for in the collection.
12584 * @return {Boolean} True if the collection contains the Object as an item.
12586 contains : function(o){
12587 return this.indexOf(o) != -1;
12591 * Returns true if the collection contains the passed Object as a key.
12592 * @param {String} key The key to look for in the collection.
12593 * @return {Boolean} True if the collection contains the Object as a key.
12595 containsKey : function(key){
12596 return typeof this.map[key] != "undefined";
12600 * Removes all items from the collection.
12602 clear : function(){
12607 this.fireEvent("clear");
12611 * Returns the first item in the collection.
12612 * @return {Object} the first item in the collection..
12614 first : function(){
12615 return this.items[0];
12619 * Returns the last item in the collection.
12620 * @return {Object} the last item in the collection..
12623 return this.items[this.length-1];
12626 _sort : function(property, dir, fn){
12627 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12628 fn = fn || function(a, b){
12631 var c = [], k = this.keys, items = this.items;
12632 for(var i = 0, len = items.length; i < len; i++){
12633 c[c.length] = {key: k[i], value: items[i], index: i};
12635 c.sort(function(a, b){
12636 var v = fn(a[property], b[property]) * dsc;
12638 v = (a.index < b.index ? -1 : 1);
12642 for(var i = 0, len = c.length; i < len; i++){
12643 items[i] = c[i].value;
12646 this.fireEvent("sort", this);
12650 * Sorts this collection with the passed comparison function
12651 * @param {String} direction (optional) "ASC" or "DESC"
12652 * @param {Function} fn (optional) comparison function
12654 sort : function(dir, fn){
12655 this._sort("value", dir, fn);
12659 * Sorts this collection by keys
12660 * @param {String} direction (optional) "ASC" or "DESC"
12661 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12663 keySort : function(dir, fn){
12664 this._sort("key", dir, fn || function(a, b){
12665 return String(a).toUpperCase()-String(b).toUpperCase();
12670 * Returns a range of items in this collection
12671 * @param {Number} startIndex (optional) defaults to 0
12672 * @param {Number} endIndex (optional) default to the last item
12673 * @return {Array} An array of items
12675 getRange : function(start, end){
12676 var items = this.items;
12677 if(items.length < 1){
12680 start = start || 0;
12681 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12684 for(var i = start; i <= end; i++) {
12685 r[r.length] = items[i];
12688 for(var i = start; i >= end; i--) {
12689 r[r.length] = items[i];
12696 * Filter the <i>objects</i> in this collection by a specific property.
12697 * Returns a new collection that has been filtered.
12698 * @param {String} property A property on your objects
12699 * @param {String/RegExp} value Either string that the property values
12700 * should start with or a RegExp to test against the property
12701 * @return {MixedCollection} The new filtered collection
12703 filter : function(property, value){
12704 if(!value.exec){ // not a regex
12705 value = String(value);
12706 if(value.length == 0){
12707 return this.clone();
12709 value = new RegExp("^" + Roo.escapeRe(value), "i");
12711 return this.filterBy(function(o){
12712 return o && value.test(o[property]);
12717 * Filter by a function. * Returns a new collection that has been filtered.
12718 * The passed function will be called with each
12719 * object in the collection. If the function returns true, the value is included
12720 * otherwise it is filtered.
12721 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12722 * @param {Object} scope (optional) The scope of the function (defaults to this)
12723 * @return {MixedCollection} The new filtered collection
12725 filterBy : function(fn, scope){
12726 var r = new Roo.util.MixedCollection();
12727 r.getKey = this.getKey;
12728 var k = this.keys, it = this.items;
12729 for(var i = 0, len = it.length; i < len; i++){
12730 if(fn.call(scope||this, it[i], k[i])){
12731 r.add(k[i], it[i]);
12738 * Creates a duplicate of this collection
12739 * @return {MixedCollection}
12741 clone : function(){
12742 var r = new Roo.util.MixedCollection();
12743 var k = this.keys, it = this.items;
12744 for(var i = 0, len = it.length; i < len; i++){
12745 r.add(k[i], it[i]);
12747 r.getKey = this.getKey;
12752 * Returns the item associated with the passed key or index.
12754 * @param {String/Number} key The key or index of the item.
12755 * @return {Object} The item associated with the passed key.
12757 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12759 * Ext JS Library 1.1.1
12760 * Copyright(c) 2006-2007, Ext JS, LLC.
12762 * Originally Released Under LGPL - original licence link has changed is not relivant.
12765 * <script type="text/javascript">
12768 * @class Roo.util.JSON
12769 * Modified version of Douglas Crockford"s json.js that doesn"t
12770 * mess with the Object prototype
12771 * http://www.json.org/js.html
12774 Roo.util.JSON = new (function(){
12775 var useHasOwn = {}.hasOwnProperty ? true : false;
12777 // crashes Safari in some instances
12778 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12780 var pad = function(n) {
12781 return n < 10 ? "0" + n : n;
12794 var encodeString = function(s){
12795 if (/["\\\x00-\x1f]/.test(s)) {
12796 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12801 c = b.charCodeAt();
12803 Math.floor(c / 16).toString(16) +
12804 (c % 16).toString(16);
12807 return '"' + s + '"';
12810 var encodeArray = function(o){
12811 var a = ["["], b, i, l = o.length, v;
12812 for (i = 0; i < l; i += 1) {
12814 switch (typeof v) {
12823 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12831 var encodeDate = function(o){
12832 return '"' + o.getFullYear() + "-" +
12833 pad(o.getMonth() + 1) + "-" +
12834 pad(o.getDate()) + "T" +
12835 pad(o.getHours()) + ":" +
12836 pad(o.getMinutes()) + ":" +
12837 pad(o.getSeconds()) + '"';
12841 * Encodes an Object, Array or other value
12842 * @param {Mixed} o The variable to encode
12843 * @return {String} The JSON string
12845 this.encode = function(o)
12847 // should this be extended to fully wrap stringify..
12849 if(typeof o == "undefined" || o === null){
12851 }else if(o instanceof Array){
12852 return encodeArray(o);
12853 }else if(o instanceof Date){
12854 return encodeDate(o);
12855 }else if(typeof o == "string"){
12856 return encodeString(o);
12857 }else if(typeof o == "number"){
12858 return isFinite(o) ? String(o) : "null";
12859 }else if(typeof o == "boolean"){
12862 var a = ["{"], b, i, v;
12864 if(!useHasOwn || o.hasOwnProperty(i)) {
12866 switch (typeof v) {
12875 a.push(this.encode(i), ":",
12876 v === null ? "null" : this.encode(v));
12887 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12888 * @param {String} json The JSON string
12889 * @return {Object} The resulting object
12891 this.decode = function(json){
12893 return /** eval:var:json */ eval("(" + json + ')');
12897 * Shorthand for {@link Roo.util.JSON#encode}
12898 * @member Roo encode
12900 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
12902 * Shorthand for {@link Roo.util.JSON#decode}
12903 * @member Roo decode
12905 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
12908 * Ext JS Library 1.1.1
12909 * Copyright(c) 2006-2007, Ext JS, LLC.
12911 * Originally Released Under LGPL - original licence link has changed is not relivant.
12914 * <script type="text/javascript">
12918 * @class Roo.util.Format
12919 * Reusable data formatting functions
12922 Roo.util.Format = function(){
12923 var trimRe = /^\s+|\s+$/g;
12926 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12927 * @param {String} value The string to truncate
12928 * @param {Number} length The maximum length to allow before truncating
12929 * @return {String} The converted text
12931 ellipsis : function(value, len){
12932 if(value && value.length > len){
12933 return value.substr(0, len-3)+"...";
12939 * Checks a reference and converts it to empty string if it is undefined
12940 * @param {Mixed} value Reference to check
12941 * @return {Mixed} Empty string if converted, otherwise the original value
12943 undef : function(value){
12944 return typeof value != "undefined" ? value : "";
12948 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12949 * @param {String} value The string to encode
12950 * @return {String} The encoded text
12952 htmlEncode : function(value){
12953 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12957 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12958 * @param {String} value The string to decode
12959 * @return {String} The decoded text
12961 htmlDecode : function(value){
12962 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12966 * Trims any whitespace from either side of a string
12967 * @param {String} value The text to trim
12968 * @return {String} The trimmed text
12970 trim : function(value){
12971 return String(value).replace(trimRe, "");
12975 * Returns a substring from within an original string
12976 * @param {String} value The original text
12977 * @param {Number} start The start index of the substring
12978 * @param {Number} length The length of the substring
12979 * @return {String} The substring
12981 substr : function(value, start, length){
12982 return String(value).substr(start, length);
12986 * Converts a string to all lower case letters
12987 * @param {String} value The text to convert
12988 * @return {String} The converted text
12990 lowercase : function(value){
12991 return String(value).toLowerCase();
12995 * Converts a string to all upper case letters
12996 * @param {String} value The text to convert
12997 * @return {String} The converted text
12999 uppercase : function(value){
13000 return String(value).toUpperCase();
13004 * Converts the first character only of a string to upper case
13005 * @param {String} value The text to convert
13006 * @return {String} The converted text
13008 capitalize : function(value){
13009 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
13013 call : function(value, fn){
13014 if(arguments.length > 2){
13015 var args = Array.prototype.slice.call(arguments, 2);
13016 args.unshift(value);
13018 return /** eval:var:value */ eval(fn).apply(window, args);
13020 /** eval:var:value */
13021 return /** eval:var:value */ eval(fn).call(window, value);
13027 * safer version of Math.toFixed..??/
13028 * @param {Number/String} value The numeric value to format
13029 * @param {Number/String} value Decimal places
13030 * @return {String} The formatted currency string
13032 toFixed : function(v, n)
13034 // why not use to fixed - precision is buggered???
13036 return Math.round(v-0);
13038 var fact = Math.pow(10,n+1);
13039 v = (Math.round((v-0)*fact))/fact;
13040 var z = (''+fact).substring(2);
13041 if (v == Math.floor(v)) {
13042 return Math.floor(v) + '.' + z;
13045 // now just padd decimals..
13046 var ps = String(v).split('.');
13047 var fd = (ps[1] + z);
13048 var r = fd.substring(0,n);
13049 var rm = fd.substring(n);
13051 return ps[0] + '.' + r;
13053 r*=1; // turn it into a number;
13055 if (String(r).length != n) {
13058 r = String(r).substring(1); // chop the end off.
13061 return ps[0] + '.' + r;
13066 * Format a number as US currency
13067 * @param {Number/String} value The numeric value to format
13068 * @return {String} The formatted currency string
13070 usMoney : function(v){
13071 v = (Math.round((v-0)*100))/100;
13072 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13074 var ps = v.split('.');
13076 var sub = ps[1] ? '.'+ ps[1] : '.00';
13077 var r = /(\d+)(\d{3})/;
13078 while (r.test(whole)) {
13079 whole = whole.replace(r, '$1' + ',' + '$2');
13081 return "$" + whole + sub ;
13085 * Parse a value into a formatted date using the specified format pattern.
13086 * @param {Mixed} value The value to format
13087 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13088 * @return {String} The formatted date string
13090 date : function(v, format){
13094 if(!(v instanceof Date)){
13095 v = new Date(Date.parse(v));
13097 return v.dateFormat(format || "m/d/Y");
13101 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13102 * @param {String} format Any valid date format string
13103 * @return {Function} The date formatting function
13105 dateRenderer : function(format){
13106 return function(v){
13107 return Roo.util.Format.date(v, format);
13112 stripTagsRE : /<\/?[^>]+>/gi,
13115 * Strips all HTML tags
13116 * @param {Mixed} value The text from which to strip tags
13117 * @return {String} The stripped text
13119 stripTags : function(v){
13120 return !v ? v : String(v).replace(this.stripTagsRE, "");
13125 * Ext JS Library 1.1.1
13126 * Copyright(c) 2006-2007, Ext JS, LLC.
13128 * Originally Released Under LGPL - original licence link has changed is not relivant.
13131 * <script type="text/javascript">
13138 * @class Roo.MasterTemplate
13139 * @extends Roo.Template
13140 * Provides a template that can have child templates. The syntax is:
13142 var t = new Roo.MasterTemplate(
13143 '<select name="{name}">',
13144 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13147 t.add('options', {value: 'foo', text: 'bar'});
13148 // or you can add multiple child elements in one shot
13149 t.addAll('options', [
13150 {value: 'foo', text: 'bar'},
13151 {value: 'foo2', text: 'bar2'},
13152 {value: 'foo3', text: 'bar3'}
13154 // then append, applying the master template values
13155 t.append('my-form', {name: 'my-select'});
13157 * A name attribute for the child template is not required if you have only one child
13158 * template or you want to refer to them by index.
13160 Roo.MasterTemplate = function(){
13161 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13162 this.originalHtml = this.html;
13164 var m, re = this.subTemplateRe;
13167 while(m = re.exec(this.html)){
13168 var name = m[1], content = m[2];
13173 tpl : new Roo.Template(content)
13176 st[name] = st[subIndex];
13178 st[subIndex].tpl.compile();
13179 st[subIndex].tpl.call = this.call.createDelegate(this);
13182 this.subCount = subIndex;
13185 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13187 * The regular expression used to match sub templates
13191 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13194 * Applies the passed values to a child template.
13195 * @param {String/Number} name (optional) The name or index of the child template
13196 * @param {Array/Object} values The values to be applied to the template
13197 * @return {MasterTemplate} this
13199 add : function(name, values){
13200 if(arguments.length == 1){
13201 values = arguments[0];
13204 var s = this.subs[name];
13205 s.buffer[s.buffer.length] = s.tpl.apply(values);
13210 * Applies all the passed values to a child template.
13211 * @param {String/Number} name (optional) The name or index of the child template
13212 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13213 * @param {Boolean} reset (optional) True to reset the template first
13214 * @return {MasterTemplate} this
13216 fill : function(name, values, reset){
13218 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13226 for(var i = 0, len = values.length; i < len; i++){
13227 this.add(name, values[i]);
13233 * Resets the template for reuse
13234 * @return {MasterTemplate} this
13236 reset : function(){
13238 for(var i = 0; i < this.subCount; i++){
13244 applyTemplate : function(values){
13246 var replaceIndex = -1;
13247 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13248 return s[++replaceIndex].buffer.join("");
13250 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13253 apply : function(){
13254 return this.applyTemplate.apply(this, arguments);
13257 compile : function(){return this;}
13261 * Alias for fill().
13264 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13266 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13267 * var tpl = Roo.MasterTemplate.from('element-id');
13268 * @param {String/HTMLElement} el
13269 * @param {Object} config
13272 Roo.MasterTemplate.from = function(el, config){
13273 el = Roo.getDom(el);
13274 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13277 * Ext JS Library 1.1.1
13278 * Copyright(c) 2006-2007, Ext JS, LLC.
13280 * Originally Released Under LGPL - original licence link has changed is not relivant.
13283 * <script type="text/javascript">
13288 * @class Roo.util.CSS
13289 * Utility class for manipulating CSS rules
13292 Roo.util.CSS = function(){
13294 var doc = document;
13296 var camelRe = /(-[a-z])/gi;
13297 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13301 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13302 * tag and appended to the HEAD of the document.
13303 * @param {String|Object} cssText The text containing the css rules
13304 * @param {String} id An id to add to the stylesheet for later removal
13305 * @return {StyleSheet}
13307 createStyleSheet : function(cssText, id){
13309 var head = doc.getElementsByTagName("head")[0];
13310 var nrules = doc.createElement("style");
13311 nrules.setAttribute("type", "text/css");
13313 nrules.setAttribute("id", id);
13315 if (typeof(cssText) != 'string') {
13316 // support object maps..
13317 // not sure if this a good idea..
13318 // perhaps it should be merged with the general css handling
13319 // and handle js style props.
13320 var cssTextNew = [];
13321 for(var n in cssText) {
13323 for(var k in cssText[n]) {
13324 citems.push( k + ' : ' +cssText[n][k] + ';' );
13326 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13329 cssText = cssTextNew.join("\n");
13335 head.appendChild(nrules);
13336 ss = nrules.styleSheet;
13337 ss.cssText = cssText;
13340 nrules.appendChild(doc.createTextNode(cssText));
13342 nrules.cssText = cssText;
13344 head.appendChild(nrules);
13345 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13347 this.cacheStyleSheet(ss);
13352 * Removes a style or link tag by id
13353 * @param {String} id The id of the tag
13355 removeStyleSheet : function(id){
13356 var existing = doc.getElementById(id);
13358 existing.parentNode.removeChild(existing);
13363 * Dynamically swaps an existing stylesheet reference for a new one
13364 * @param {String} id The id of an existing link tag to remove
13365 * @param {String} url The href of the new stylesheet to include
13367 swapStyleSheet : function(id, url){
13368 this.removeStyleSheet(id);
13369 var ss = doc.createElement("link");
13370 ss.setAttribute("rel", "stylesheet");
13371 ss.setAttribute("type", "text/css");
13372 ss.setAttribute("id", id);
13373 ss.setAttribute("href", url);
13374 doc.getElementsByTagName("head")[0].appendChild(ss);
13378 * Refresh the rule cache if you have dynamically added stylesheets
13379 * @return {Object} An object (hash) of rules indexed by selector
13381 refreshCache : function(){
13382 return this.getRules(true);
13386 cacheStyleSheet : function(stylesheet){
13390 try{// try catch for cross domain access issue
13391 var ssRules = stylesheet.cssRules || stylesheet.rules;
13392 for(var j = ssRules.length-1; j >= 0; --j){
13393 rules[ssRules[j].selectorText] = ssRules[j];
13399 * Gets all css rules for the document
13400 * @param {Boolean} refreshCache true to refresh the internal cache
13401 * @return {Object} An object (hash) of rules indexed by selector
13403 getRules : function(refreshCache){
13404 if(rules == null || refreshCache){
13406 var ds = doc.styleSheets;
13407 for(var i =0, len = ds.length; i < len; i++){
13409 this.cacheStyleSheet(ds[i]);
13417 * Gets an an individual CSS rule by selector(s)
13418 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13419 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13420 * @return {CSSRule} The CSS rule or null if one is not found
13422 getRule : function(selector, refreshCache){
13423 var rs = this.getRules(refreshCache);
13424 if(!(selector instanceof Array)){
13425 return rs[selector];
13427 for(var i = 0; i < selector.length; i++){
13428 if(rs[selector[i]]){
13429 return rs[selector[i]];
13437 * Updates a rule property
13438 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13439 * @param {String} property The css property
13440 * @param {String} value The new value for the property
13441 * @return {Boolean} true If a rule was found and updated
13443 updateRule : function(selector, property, value){
13444 if(!(selector instanceof Array)){
13445 var rule = this.getRule(selector);
13447 rule.style[property.replace(camelRe, camelFn)] = value;
13451 for(var i = 0; i < selector.length; i++){
13452 if(this.updateRule(selector[i], property, value)){
13462 * Ext JS Library 1.1.1
13463 * Copyright(c) 2006-2007, Ext JS, LLC.
13465 * Originally Released Under LGPL - original licence link has changed is not relivant.
13468 * <script type="text/javascript">
13474 * @class Roo.util.ClickRepeater
13475 * @extends Roo.util.Observable
13477 * A wrapper class which can be applied to any element. Fires a "click" event while the
13478 * mouse is pressed. The interval between firings may be specified in the config but
13479 * defaults to 10 milliseconds.
13481 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13483 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13484 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13485 * Similar to an autorepeat key delay.
13486 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13487 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13488 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13489 * "interval" and "delay" are ignored. "immediate" is honored.
13490 * @cfg {Boolean} preventDefault True to prevent the default click event
13491 * @cfg {Boolean} stopDefault True to stop the default click event
13494 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13495 * 2007-02-02 jvs Renamed to ClickRepeater
13496 * 2007-02-03 jvs Modifications for FF Mac and Safari
13499 * @param {String/HTMLElement/Element} el The element to listen on
13500 * @param {Object} config
13502 Roo.util.ClickRepeater = function(el, config)
13504 this.el = Roo.get(el);
13505 this.el.unselectable();
13507 Roo.apply(this, config);
13512 * Fires when the mouse button is depressed.
13513 * @param {Roo.util.ClickRepeater} this
13515 "mousedown" : true,
13518 * Fires on a specified interval during the time the element is pressed.
13519 * @param {Roo.util.ClickRepeater} this
13524 * Fires when the mouse key is released.
13525 * @param {Roo.util.ClickRepeater} this
13530 this.el.on("mousedown", this.handleMouseDown, this);
13531 if(this.preventDefault || this.stopDefault){
13532 this.el.on("click", function(e){
13533 if(this.preventDefault){
13534 e.preventDefault();
13536 if(this.stopDefault){
13542 // allow inline handler
13544 this.on("click", this.handler, this.scope || this);
13547 Roo.util.ClickRepeater.superclass.constructor.call(this);
13550 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13553 preventDefault : true,
13554 stopDefault : false,
13558 handleMouseDown : function(){
13559 clearTimeout(this.timer);
13561 if(this.pressClass){
13562 this.el.addClass(this.pressClass);
13564 this.mousedownTime = new Date();
13566 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13567 this.el.on("mouseout", this.handleMouseOut, this);
13569 this.fireEvent("mousedown", this);
13570 this.fireEvent("click", this);
13572 this.timer = this.click.defer(this.delay || this.interval, this);
13576 click : function(){
13577 this.fireEvent("click", this);
13578 this.timer = this.click.defer(this.getInterval(), this);
13582 getInterval: function(){
13583 if(!this.accelerate){
13584 return this.interval;
13586 var pressTime = this.mousedownTime.getElapsed();
13587 if(pressTime < 500){
13589 }else if(pressTime < 1700){
13591 }else if(pressTime < 2600){
13593 }else if(pressTime < 3500){
13595 }else if(pressTime < 4400){
13597 }else if(pressTime < 5300){
13599 }else if(pressTime < 6200){
13607 handleMouseOut : function(){
13608 clearTimeout(this.timer);
13609 if(this.pressClass){
13610 this.el.removeClass(this.pressClass);
13612 this.el.on("mouseover", this.handleMouseReturn, this);
13616 handleMouseReturn : function(){
13617 this.el.un("mouseover", this.handleMouseReturn);
13618 if(this.pressClass){
13619 this.el.addClass(this.pressClass);
13625 handleMouseUp : function(){
13626 clearTimeout(this.timer);
13627 this.el.un("mouseover", this.handleMouseReturn);
13628 this.el.un("mouseout", this.handleMouseOut);
13629 Roo.get(document).un("mouseup", this.handleMouseUp);
13630 this.el.removeClass(this.pressClass);
13631 this.fireEvent("mouseup", this);
13635 * Ext JS Library 1.1.1
13636 * Copyright(c) 2006-2007, Ext JS, LLC.
13638 * Originally Released Under LGPL - original licence link has changed is not relivant.
13641 * <script type="text/javascript">
13646 * @class Roo.KeyNav
13647 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13648 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13649 * way to implement custom navigation schemes for any UI component.</p>
13650 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13651 * pageUp, pageDown, del, home, end. Usage:</p>
13653 var nav = new Roo.KeyNav("my-element", {
13654 "left" : function(e){
13655 this.moveLeft(e.ctrlKey);
13657 "right" : function(e){
13658 this.moveRight(e.ctrlKey);
13660 "enter" : function(e){
13667 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13668 * @param {Object} config The config
13670 Roo.KeyNav = function(el, config){
13671 this.el = Roo.get(el);
13672 Roo.apply(this, config);
13673 if(!this.disabled){
13674 this.disabled = true;
13679 Roo.KeyNav.prototype = {
13681 * @cfg {Boolean} disabled
13682 * True to disable this KeyNav instance (defaults to false)
13686 * @cfg {String} defaultEventAction
13687 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13688 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13689 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13691 defaultEventAction: "stopEvent",
13693 * @cfg {Boolean} forceKeyDown
13694 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13695 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13696 * handle keydown instead of keypress.
13698 forceKeyDown : false,
13701 prepareEvent : function(e){
13702 var k = e.getKey();
13703 var h = this.keyToHandler[k];
13704 //if(h && this[h]){
13705 // e.stopPropagation();
13707 if(Roo.isSafari && h && k >= 37 && k <= 40){
13713 relay : function(e){
13714 var k = e.getKey();
13715 var h = this.keyToHandler[k];
13717 if(this.doRelay(e, this[h], h) !== true){
13718 e[this.defaultEventAction]();
13724 doRelay : function(e, h, hname){
13725 return h.call(this.scope || this, e);
13728 // possible handlers
13742 // quick lookup hash
13759 * Enable this KeyNav
13761 enable: function(){
13763 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13764 // the EventObject will normalize Safari automatically
13765 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13766 this.el.on("keydown", this.relay, this);
13768 this.el.on("keydown", this.prepareEvent, this);
13769 this.el.on("keypress", this.relay, this);
13771 this.disabled = false;
13776 * Disable this KeyNav
13778 disable: function(){
13779 if(!this.disabled){
13780 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13781 this.el.un("keydown", this.relay);
13783 this.el.un("keydown", this.prepareEvent);
13784 this.el.un("keypress", this.relay);
13786 this.disabled = true;
13791 * Ext JS Library 1.1.1
13792 * Copyright(c) 2006-2007, Ext JS, LLC.
13794 * Originally Released Under LGPL - original licence link has changed is not relivant.
13797 * <script type="text/javascript">
13802 * @class Roo.KeyMap
13803 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13804 * The constructor accepts the same config object as defined by {@link #addBinding}.
13805 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13806 * combination it will call the function with this signature (if the match is a multi-key
13807 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13808 * A KeyMap can also handle a string representation of keys.<br />
13811 // map one key by key code
13812 var map = new Roo.KeyMap("my-element", {
13813 key: 13, // or Roo.EventObject.ENTER
13818 // map multiple keys to one action by string
13819 var map = new Roo.KeyMap("my-element", {
13825 // map multiple keys to multiple actions by strings and array of codes
13826 var map = new Roo.KeyMap("my-element", [
13829 fn: function(){ alert("Return was pressed"); }
13832 fn: function(){ alert('a, b or c was pressed'); }
13837 fn: function(){ alert('Control + shift + tab was pressed.'); }
13841 * <b>Note: A KeyMap starts enabled</b>
13843 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13844 * @param {Object} config The config (see {@link #addBinding})
13845 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13847 Roo.KeyMap = function(el, config, eventName){
13848 this.el = Roo.get(el);
13849 this.eventName = eventName || "keydown";
13850 this.bindings = [];
13852 this.addBinding(config);
13857 Roo.KeyMap.prototype = {
13859 * True to stop the event from bubbling and prevent the default browser action if the
13860 * key was handled by the KeyMap (defaults to false)
13866 * Add a new binding to this KeyMap. The following config object properties are supported:
13868 Property Type Description
13869 ---------- --------------- ----------------------------------------------------------------------
13870 key String/Array A single keycode or an array of keycodes to handle
13871 shift Boolean True to handle key only when shift is pressed (defaults to false)
13872 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13873 alt Boolean True to handle key only when alt is pressed (defaults to false)
13874 fn Function The function to call when KeyMap finds the expected key combination
13875 scope Object The scope of the callback function
13881 var map = new Roo.KeyMap(document, {
13882 key: Roo.EventObject.ENTER,
13887 //Add a new binding to the existing KeyMap later
13895 * @param {Object/Array} config A single KeyMap config or an array of configs
13897 addBinding : function(config){
13898 if(config instanceof Array){
13899 for(var i = 0, len = config.length; i < len; i++){
13900 this.addBinding(config[i]);
13904 var keyCode = config.key,
13905 shift = config.shift,
13906 ctrl = config.ctrl,
13909 scope = config.scope;
13910 if(typeof keyCode == "string"){
13912 var keyString = keyCode.toUpperCase();
13913 for(var j = 0, len = keyString.length; j < len; j++){
13914 ks.push(keyString.charCodeAt(j));
13918 var keyArray = keyCode instanceof Array;
13919 var handler = function(e){
13920 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13921 var k = e.getKey();
13923 for(var i = 0, len = keyCode.length; i < len; i++){
13924 if(keyCode[i] == k){
13925 if(this.stopEvent){
13928 fn.call(scope || window, k, e);
13934 if(this.stopEvent){
13937 fn.call(scope || window, k, e);
13942 this.bindings.push(handler);
13946 * Shorthand for adding a single key listener
13947 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13948 * following options:
13949 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13950 * @param {Function} fn The function to call
13951 * @param {Object} scope (optional) The scope of the function
13953 on : function(key, fn, scope){
13954 var keyCode, shift, ctrl, alt;
13955 if(typeof key == "object" && !(key instanceof Array)){
13974 handleKeyDown : function(e){
13975 if(this.enabled){ //just in case
13976 var b = this.bindings;
13977 for(var i = 0, len = b.length; i < len; i++){
13978 b[i].call(this, e);
13984 * Returns true if this KeyMap is enabled
13985 * @return {Boolean}
13987 isEnabled : function(){
13988 return this.enabled;
13992 * Enables this KeyMap
13994 enable: function(){
13996 this.el.on(this.eventName, this.handleKeyDown, this);
13997 this.enabled = true;
14002 * Disable this KeyMap
14004 disable: function(){
14006 this.el.removeListener(this.eventName, this.handleKeyDown, this);
14007 this.enabled = false;
14012 * Ext JS Library 1.1.1
14013 * Copyright(c) 2006-2007, Ext JS, LLC.
14015 * Originally Released Under LGPL - original licence link has changed is not relivant.
14018 * <script type="text/javascript">
14023 * @class Roo.util.TextMetrics
14024 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
14025 * wide, in pixels, a given block of text will be.
14028 Roo.util.TextMetrics = function(){
14032 * Measures the size of the specified text
14033 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
14034 * that can affect the size of the rendered text
14035 * @param {String} text The text to measure
14036 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14037 * in order to accurately measure the text height
14038 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14040 measure : function(el, text, fixedWidth){
14042 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
14045 shared.setFixedWidth(fixedWidth || 'auto');
14046 return shared.getSize(text);
14050 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
14051 * the overhead of multiple calls to initialize the style properties on each measurement.
14052 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
14053 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14054 * in order to accurately measure the text height
14055 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14057 createInstance : function(el, fixedWidth){
14058 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14065 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14066 var ml = new Roo.Element(document.createElement('div'));
14067 document.body.appendChild(ml.dom);
14068 ml.position('absolute');
14069 ml.setLeftTop(-1000, -1000);
14073 ml.setWidth(fixedWidth);
14078 * Returns the size of the specified text based on the internal element's style and width properties
14079 * @memberOf Roo.util.TextMetrics.Instance#
14080 * @param {String} text The text to measure
14081 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14083 getSize : function(text){
14085 var s = ml.getSize();
14091 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14092 * that can affect the size of the rendered text
14093 * @memberOf Roo.util.TextMetrics.Instance#
14094 * @param {String/HTMLElement} el The element, dom node or id
14096 bind : function(el){
14098 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14103 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14104 * to set a fixed width in order to accurately measure the text height.
14105 * @memberOf Roo.util.TextMetrics.Instance#
14106 * @param {Number} width The width to set on the element
14108 setFixedWidth : function(width){
14109 ml.setWidth(width);
14113 * Returns the measured width of the specified text
14114 * @memberOf Roo.util.TextMetrics.Instance#
14115 * @param {String} text The text to measure
14116 * @return {Number} width The width in pixels
14118 getWidth : function(text){
14119 ml.dom.style.width = 'auto';
14120 return this.getSize(text).width;
14124 * Returns the measured height of the specified text. For multiline text, be sure to call
14125 * {@link #setFixedWidth} if necessary.
14126 * @memberOf Roo.util.TextMetrics.Instance#
14127 * @param {String} text The text to measure
14128 * @return {Number} height The height in pixels
14130 getHeight : function(text){
14131 return this.getSize(text).height;
14135 instance.bind(bindTo);
14140 // backwards compat
14141 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14143 * Ext JS Library 1.1.1
14144 * Copyright(c) 2006-2007, Ext JS, LLC.
14146 * Originally Released Under LGPL - original licence link has changed is not relivant.
14149 * <script type="text/javascript">
14153 * @class Roo.state.Provider
14154 * Abstract base class for state provider implementations. This class provides methods
14155 * for encoding and decoding <b>typed</b> variables including dates and defines the
14156 * Provider interface.
14158 Roo.state.Provider = function(){
14160 * @event statechange
14161 * Fires when a state change occurs.
14162 * @param {Provider} this This state provider
14163 * @param {String} key The state key which was changed
14164 * @param {String} value The encoded value for the state
14167 "statechange": true
14170 Roo.state.Provider.superclass.constructor.call(this);
14172 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14174 * Returns the current value for a key
14175 * @param {String} name The key name
14176 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14177 * @return {Mixed} The state data
14179 get : function(name, defaultValue){
14180 return typeof this.state[name] == "undefined" ?
14181 defaultValue : this.state[name];
14185 * Clears a value from the state
14186 * @param {String} name The key name
14188 clear : function(name){
14189 delete this.state[name];
14190 this.fireEvent("statechange", this, name, null);
14194 * Sets the value for a key
14195 * @param {String} name The key name
14196 * @param {Mixed} value The value to set
14198 set : function(name, value){
14199 this.state[name] = value;
14200 this.fireEvent("statechange", this, name, value);
14204 * Decodes a string previously encoded with {@link #encodeValue}.
14205 * @param {String} value The value to decode
14206 * @return {Mixed} The decoded value
14208 decodeValue : function(cookie){
14209 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14210 var matches = re.exec(unescape(cookie));
14211 if(!matches || !matches[1]) return; // non state cookie
14212 var type = matches[1];
14213 var v = matches[2];
14216 return parseFloat(v);
14218 return new Date(Date.parse(v));
14223 var values = v.split("^");
14224 for(var i = 0, len = values.length; i < len; i++){
14225 all.push(this.decodeValue(values[i]));
14230 var values = v.split("^");
14231 for(var i = 0, len = values.length; i < len; i++){
14232 var kv = values[i].split("=");
14233 all[kv[0]] = this.decodeValue(kv[1]);
14242 * Encodes a value including type information. Decode with {@link #decodeValue}.
14243 * @param {Mixed} value The value to encode
14244 * @return {String} The encoded value
14246 encodeValue : function(v){
14248 if(typeof v == "number"){
14250 }else if(typeof v == "boolean"){
14251 enc = "b:" + (v ? "1" : "0");
14252 }else if(v instanceof Date){
14253 enc = "d:" + v.toGMTString();
14254 }else if(v instanceof Array){
14256 for(var i = 0, len = v.length; i < len; i++){
14257 flat += this.encodeValue(v[i]);
14258 if(i != len-1) flat += "^";
14261 }else if(typeof v == "object"){
14264 if(typeof v[key] != "function"){
14265 flat += key + "=" + this.encodeValue(v[key]) + "^";
14268 enc = "o:" + flat.substring(0, flat.length-1);
14272 return escape(enc);
14278 * Ext JS Library 1.1.1
14279 * Copyright(c) 2006-2007, Ext JS, LLC.
14281 * Originally Released Under LGPL - original licence link has changed is not relivant.
14284 * <script type="text/javascript">
14287 * @class Roo.state.Manager
14288 * This is the global state manager. By default all components that are "state aware" check this class
14289 * for state information if you don't pass them a custom state provider. In order for this class
14290 * to be useful, it must be initialized with a provider when your application initializes.
14292 // in your initialization function
14294 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14296 // supposed you have a {@link Roo.BorderLayout}
14297 var layout = new Roo.BorderLayout(...);
14298 layout.restoreState();
14299 // or a {Roo.BasicDialog}
14300 var dialog = new Roo.BasicDialog(...);
14301 dialog.restoreState();
14305 Roo.state.Manager = function(){
14306 var provider = new Roo.state.Provider();
14310 * Configures the default state provider for your application
14311 * @param {Provider} stateProvider The state provider to set
14313 setProvider : function(stateProvider){
14314 provider = stateProvider;
14318 * Returns the current value for a key
14319 * @param {String} name The key name
14320 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14321 * @return {Mixed} The state data
14323 get : function(key, defaultValue){
14324 return provider.get(key, defaultValue);
14328 * Sets the value for a key
14329 * @param {String} name The key name
14330 * @param {Mixed} value The state data
14332 set : function(key, value){
14333 provider.set(key, value);
14337 * Clears a value from the state
14338 * @param {String} name The key name
14340 clear : function(key){
14341 provider.clear(key);
14345 * Gets the currently configured state provider
14346 * @return {Provider} The state provider
14348 getProvider : function(){
14355 * Ext JS Library 1.1.1
14356 * Copyright(c) 2006-2007, Ext JS, LLC.
14358 * Originally Released Under LGPL - original licence link has changed is not relivant.
14361 * <script type="text/javascript">
14364 * @class Roo.state.CookieProvider
14365 * @extends Roo.state.Provider
14366 * The default Provider implementation which saves state via cookies.
14369 var cp = new Roo.state.CookieProvider({
14371 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14372 domain: "roojs.com"
14374 Roo.state.Manager.setProvider(cp);
14376 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14377 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14378 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14379 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14380 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14381 * domain the page is running on including the 'www' like 'www.roojs.com')
14382 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14384 * Create a new CookieProvider
14385 * @param {Object} config The configuration object
14387 Roo.state.CookieProvider = function(config){
14388 Roo.state.CookieProvider.superclass.constructor.call(this);
14390 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14391 this.domain = null;
14392 this.secure = false;
14393 Roo.apply(this, config);
14394 this.state = this.readCookies();
14397 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14399 set : function(name, value){
14400 if(typeof value == "undefined" || value === null){
14404 this.setCookie(name, value);
14405 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14409 clear : function(name){
14410 this.clearCookie(name);
14411 Roo.state.CookieProvider.superclass.clear.call(this, name);
14415 readCookies : function(){
14417 var c = document.cookie + ";";
14418 var re = /\s?(.*?)=(.*?);/g;
14420 while((matches = re.exec(c)) != null){
14421 var name = matches[1];
14422 var value = matches[2];
14423 if(name && name.substring(0,3) == "ys-"){
14424 cookies[name.substr(3)] = this.decodeValue(value);
14431 setCookie : function(name, value){
14432 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14433 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14434 ((this.path == null) ? "" : ("; path=" + this.path)) +
14435 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14436 ((this.secure == true) ? "; secure" : "");
14440 clearCookie : function(name){
14441 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14442 ((this.path == null) ? "" : ("; path=" + this.path)) +
14443 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14444 ((this.secure == true) ? "; secure" : "");