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
90 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
93 enableGarbageCollector : true,
96 * True to automatically purge event listeners after uncaching an element (defaults to false).
97 * Note: this only happens if enableGarbageCollector is true.
100 enableListenerCollection:false,
103 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
104 * the IE insecure content warning (defaults to javascript:false).
107 SSL_SECURE_URL : "javascript:false",
110 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
111 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
114 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
116 emptyFn : function(){},
119 * Copies all the properties of config to obj if they don't already exist.
120 * @param {Object} obj The receiver of the properties
121 * @param {Object} config The source of the properties
122 * @return {Object} returns obj
124 applyIf : function(o, c){
127 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
134 * Applies event listeners to elements by selectors when the document is ready.
135 * The event name is specified with an @ suffix.
138 // add a listener for click on all anchors in element with id foo
139 '#foo a@click' : function(e, t){
143 // add the same listener to multiple selectors (separated by comma BEFORE the @)
144 '#foo a, #bar span.some-class@mouseover' : function(){
149 * @param {Object} obj The list of behaviors to apply
151 addBehaviors : function(o){
153 Roo.onReady(function(){
158 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
160 var parts = b.split('@');
161 if(parts[1]){ // for Object prototype breakers
164 cache[s] = Roo.select(s);
166 cache[s].on(parts[1], o[b]);
173 * Generates unique ids. If the element already has an id, it is unchanged
174 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
175 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
176 * @return {String} The generated Id.
178 id : function(el, prefix){
179 prefix = prefix || "roo-gen";
181 var id = prefix + (++idSeed);
182 return el ? (el.id ? el.id : (el.id = id)) : id;
187 * Extends one class with another class and optionally overrides members with the passed literal. This class
188 * also adds the function "override()" to the class that can be used to override
189 * members on an instance.
190 * @param {Object} subclass The class inheriting the functionality
191 * @param {Object} superclass The class being extended
192 * @param {Object} overrides (optional) A literal with members
197 var io = function(o){
202 return function(sb, sp, overrides){
203 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
206 sb = function(){sp.apply(this, arguments);};
208 var F = function(){}, sbp, spp = sp.prototype;
210 sbp = sb.prototype = new F();
214 if(spp.constructor == Object.prototype.constructor){
219 sb.override = function(o){
223 Roo.override(sb, overrides);
229 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
231 Roo.override(MyClass, {
232 newMethod1: function(){
235 newMethod2: function(foo){
240 * @param {Object} origclass The class to override
241 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
242 * containing one or more methods.
245 override : function(origclass, overrides){
247 var p = origclass.prototype;
248 for(var method in overrides){
249 p[method] = overrides[method];
254 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
256 Roo.namespace('Company', 'Company.data');
257 Company.Widget = function() { ... }
258 Company.data.CustomStore = function(config) { ... }
260 * @param {String} namespace1
261 * @param {String} namespace2
262 * @param {String} etc
265 namespace : function(){
266 var a=arguments, o=null, i, j, d, rt;
267 for (i=0; i<a.length; ++i) {
271 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
272 for (j=1; j<d.length; ++j) {
273 o[d[j]]=o[d[j]] || {};
279 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
281 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
282 Roo.factory(conf, Roo.data);
284 * @param {String} classname
285 * @param {String} namespace (optional)
289 factory : function(c, ns)
291 // no xtype, no ns or c.xns - or forced off by c.xns
292 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
295 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
296 if (c.constructor == ns[c.xtype]) {// already created...
300 if (Roo.debug) console.log("Roo.Factory(" + c.xtype + ")");
301 var ret = new ns[c.xtype](c);
305 c.xns = false; // prevent recursion..
310 * 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.
314 urlEncode : function(o){
320 var ov = o[key], k = encodeURIComponent(key);
321 var type = typeof ov;
322 if(type == 'undefined'){
324 }else if(type != "function" && type != "object"){
325 buf.push(k, "=", encodeURIComponent(ov), "&");
326 }else if(ov instanceof Array){
328 for(var i = 0, len = ov.length; i < len; i++) {
329 buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
341 * 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]}.
342 * @param {String} string
343 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
344 * @return {Object} A literal with members
346 urlDecode : function(string, overwrite){
347 if(!string || !string.length){
351 var pairs = string.split('&');
352 var pair, name, value;
353 for(var i = 0, len = pairs.length; i < len; i++){
354 pair = pairs[i].split('=');
355 name = decodeURIComponent(pair[0]);
356 value = decodeURIComponent(pair[1]);
357 if(overwrite !== true){
358 if(typeof obj[name] == "undefined"){
360 }else if(typeof obj[name] == "string"){
361 obj[name] = [obj[name]];
362 obj[name].push(value);
364 obj[name].push(value);
374 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
375 * passed array is not really an array, your function is called once with it.
376 * The supplied function is called with (Object item, Number index, Array allItems).
377 * @param {Array/NodeList/Mixed} array
378 * @param {Function} fn
379 * @param {Object} scope
381 each : function(array, fn, scope){
382 if(typeof array.length == "undefined" || typeof array == "string"){
385 for(var i = 0, len = array.length; i < len; i++){
386 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
391 combine : function(){
392 var as = arguments, l = as.length, r = [];
393 for(var i = 0; i < l; i++){
395 if(a instanceof Array){
397 }else if(a.length !== undefined && !a.substr){
398 r = r.concat(Array.prototype.slice.call(a, 0));
407 * Escapes the passed string for use in a regular expression
408 * @param {String} str
411 escapeRe : function(s) {
412 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
416 callback : function(cb, scope, args, delay){
417 if(typeof cb == "function"){
419 cb.defer(delay, scope, args || []);
421 cb.apply(scope, args || []);
427 * Return the dom node for the passed string (id), dom node, or Roo.Element
428 * @param {String/HTMLElement/Roo.Element} el
429 * @return HTMLElement
431 getDom : function(el){
435 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
439 * Shorthand for {@link Roo.ComponentMgr#get}
441 * @return Roo.Component
443 getCmp : function(id){
444 return Roo.ComponentMgr.get(id);
447 num : function(v, defaultValue){
448 if(typeof v != 'number'){
454 destroy : function(){
455 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
459 as.removeAllListeners();
463 if(typeof as.purgeListeners == 'function'){
466 if(typeof as.destroy == 'function'){
473 // inpired by a similar function in mootools library
475 * Returns the type of object that is passed in. If the object passed in is null or undefined it
476 * return false otherwise it returns one of the following values:<ul>
477 * <li><b>string</b>: If the object passed is a string</li>
478 * <li><b>number</b>: If the object passed is a number</li>
479 * <li><b>boolean</b>: If the object passed is a boolean value</li>
480 * <li><b>function</b>: If the object passed is a function reference</li>
481 * <li><b>object</b>: If the object passed is an object</li>
482 * <li><b>array</b>: If the object passed is an array</li>
483 * <li><b>regexp</b>: If the object passed is a regular expression</li>
484 * <li><b>element</b>: If the object passed is a DOM Element</li>
485 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
486 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
487 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
488 * @param {Mixed} object
492 if(o === undefined || o === null){
499 if(t == 'object' && o.nodeName) {
501 case 1: return 'element';
502 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
505 if(t == 'object' || t == 'function') {
506 switch(o.constructor) {
507 case Array: return 'array';
508 case RegExp: return 'regexp';
510 if(typeof o.length == 'number' && typeof o.item == 'function') {
518 * Returns true if the passed value is null, undefined or an empty string (optional).
519 * @param {Mixed} value The value to test
520 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
523 isEmpty : function(v, allowBlank){
524 return v === null || v === undefined || (!allowBlank ? v === '' : false);
538 isBorderBox : isBorderBox,
540 isWindows : isWindows,
547 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
548 * you may want to set this to true.
551 useShims : ((isIE && !isIE7) || (isGecko && isMac))
557 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
558 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
561 * Ext JS Library 1.1.1
562 * Copyright(c) 2006-2007, Ext JS, LLC.
564 * Originally Released Under LGPL - original licence link has changed is not relivant.
567 * <script type="text/javascript">
571 // wrappedn so fnCleanup is not in global scope...
573 function fnCleanUp() {
574 var p = Function.prototype;
575 delete p.createSequence;
577 delete p.createDelegate;
578 delete p.createCallback;
579 delete p.createInterceptor;
581 window.detachEvent("onunload", fnCleanUp);
583 window.attachEvent("onunload", fnCleanUp);
590 * These functions are available on every Function object (any JavaScript function).
592 Roo.apply(Function.prototype, {
594 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
595 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
596 * Will create a function that is bound to those 2 args.
597 * @return {Function} The new function
599 createCallback : function(/*args...*/){
600 // make args available, in function below
601 var args = arguments;
604 return method.apply(window, args);
609 * Creates a delegate (callback) that sets the scope to obj.
610 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
611 * Will create a function that is automatically scoped to this.
612 * @param {Object} obj (optional) The object for which the scope is set
613 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
614 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
615 * if a number the args are inserted at the specified position
616 * @return {Function} The new function
618 createDelegate : function(obj, args, appendArgs){
621 var callArgs = args || arguments;
622 if(appendArgs === true){
623 callArgs = Array.prototype.slice.call(arguments, 0);
624 callArgs = callArgs.concat(args);
625 }else if(typeof appendArgs == "number"){
626 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
627 var applyArgs = [appendArgs, 0].concat(args); // create method call params
628 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
630 return method.apply(obj || window, callArgs);
635 * Calls this function after the number of millseconds specified.
636 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
637 * @param {Object} obj (optional) The object for which the scope is set
638 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
639 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
640 * if a number the args are inserted at the specified position
641 * @return {Number} The timeout id that can be used with clearTimeout
643 defer : function(millis, obj, args, appendArgs){
644 var fn = this.createDelegate(obj, args, appendArgs);
646 return setTimeout(fn, millis);
652 * Create a combined function call sequence of the original function + the passed function.
653 * The resulting function returns the results of the original function.
654 * The passed fcn is called with the parameters of the original function
655 * @param {Function} fcn The function to sequence
656 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
657 * @return {Function} The new function
659 createSequence : function(fcn, scope){
660 if(typeof fcn != "function"){
665 var retval = method.apply(this || window, arguments);
666 fcn.apply(scope || this || window, arguments);
672 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
673 * The resulting function returns the results of the original function.
674 * The passed fcn is called with the parameters of the original function.
676 * @param {Function} fcn The function to call before the original
677 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
678 * @return {Function} The new function
680 createInterceptor : function(fcn, scope){
681 if(typeof fcn != "function"){
688 if(fcn.apply(scope || this || window, arguments) === false){
691 return method.apply(this || window, arguments);
697 * Ext JS Library 1.1.1
698 * Copyright(c) 2006-2007, Ext JS, LLC.
700 * Originally Released Under LGPL - original licence link has changed is not relivant.
703 * <script type="text/javascript">
706 Roo.applyIf(String, {
711 * Escapes the passed string for ' and \
712 * @param {String} string The string to escape
713 * @return {String} The escaped string
716 escape : function(string) {
717 return string.replace(/('|\\)/g, "\\$1");
721 * Pads the left side of a string with a specified character. This is especially useful
722 * for normalizing number and date strings. Example usage:
724 var s = String.leftPad('123', 5, '0');
725 // s now contains the string: '00123'
727 * @param {String} string The original string
728 * @param {Number} size The total length of the output string
729 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
730 * @return {String} The padded string
733 leftPad : function (val, size, ch) {
734 var result = new String(val);
735 if(ch === null || ch === undefined || ch === '') {
738 while (result.length < size) {
739 result = ch + result;
745 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
746 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
748 var cls = 'my-class', text = 'Some text';
749 var s = String.format('<div class="{0}">{1}</div>', cls, text);
750 // s now contains the string: '<div class="my-class">Some text</div>'
752 * @param {String} string The tokenized string to be formatted
753 * @param {String} value1 The value to replace token {0}
754 * @param {String} value2 Etc...
755 * @return {String} The formatted string
758 format : function(format){
759 var args = Array.prototype.slice.call(arguments, 1);
760 return format.replace(/\{(\d+)\}/g, function(m, i){
761 return Roo.util.Format.htmlEncode(args[i]);
767 * Utility function that allows you to easily switch a string between two alternating values. The passed value
768 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
769 * they are already different, the first value passed in is returned. Note that this method returns the new value
770 * but does not change the current string.
772 // alternate sort directions
773 sort = sort.toggle('ASC', 'DESC');
775 // instead of conditional logic:
776 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
778 * @param {String} value The value to compare to the current string
779 * @param {String} other The new value to use if the string already equals the first value passed in
780 * @return {String} The new value
783 String.prototype.toggle = function(value, other){
784 return this == value ? other : value;
787 * Ext JS Library 1.1.1
788 * Copyright(c) 2006-2007, Ext JS, LLC.
790 * Originally Released Under LGPL - original licence link has changed is not relivant.
793 * <script type="text/javascript">
799 Roo.applyIf(Number.prototype, {
801 * Checks whether or not the current number is within a desired range. If the number is already within the
802 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
803 * exceeded. Note that this method returns the constrained value but does not change the current number.
804 * @param {Number} min The minimum number in the range
805 * @param {Number} max The maximum number in the range
806 * @return {Number} The constrained value if outside the range, otherwise the current value
808 constrain : function(min, max){
809 return Math.min(Math.max(this, min), max);
813 * Ext JS Library 1.1.1
814 * Copyright(c) 2006-2007, Ext JS, LLC.
816 * Originally Released Under LGPL - original licence link has changed is not relivant.
819 * <script type="text/javascript">
824 Roo.applyIf(Array.prototype, {
826 * Checks whether or not the specified object exists in the array.
827 * @param {Object} o The object to check for
828 * @return {Number} The index of o in the array (or -1 if it is not found)
830 indexOf : function(o){
831 for (var i = 0, len = this.length; i < len; i++){
832 if(this[i] == o) return i;
838 * Removes the specified object from the array. If the object is not found nothing happens.
839 * @param {Object} o The object to remove
841 remove : function(o){
842 var index = this.indexOf(o);
844 this.splice(index, 1);
848 * Map (JS 1.6 compatibility)
849 * @param {Function} function to call
853 var len = this.length >>> 0;
854 if (typeof fun != "function")
855 throw new TypeError();
857 var res = new Array(len);
858 var thisp = arguments[1];
859 for (var i = 0; i < len; i++)
862 res[i] = fun.call(thisp, this[i], i, this);
873 * Ext JS Library 1.1.1
874 * Copyright(c) 2006-2007, Ext JS, LLC.
876 * Originally Released Under LGPL - original licence link has changed is not relivant.
879 * <script type="text/javascript">
885 * The date parsing and format syntax is a subset of
886 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
887 * supported will provide results equivalent to their PHP versions.
889 * Following is the list of all currently supported formats:
892 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
894 Format Output Description
895 ------ ---------- --------------------------------------------------------------
896 d 10 Day of the month, 2 digits with leading zeros
897 D Wed A textual representation of a day, three letters
898 j 10 Day of the month without leading zeros
899 l Wednesday A full textual representation of the day of the week
900 S th English ordinal day of month suffix, 2 chars (use with j)
901 w 3 Numeric representation of the day of the week
902 z 9 The julian date, or day of the year (0-365)
903 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
904 F January A full textual representation of the month
905 m 01 Numeric representation of a month, with leading zeros
906 M Jan Month name abbreviation, three letters
907 n 1 Numeric representation of a month, without leading zeros
908 t 31 Number of days in the given month
909 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
910 Y 2007 A full numeric representation of a year, 4 digits
911 y 07 A two digit representation of a year
912 a pm Lowercase Ante meridiem and Post meridiem
913 A PM Uppercase Ante meridiem and Post meridiem
914 g 3 12-hour format of an hour without leading zeros
915 G 15 24-hour format of an hour without leading zeros
916 h 03 12-hour format of an hour with leading zeros
917 H 15 24-hour format of an hour with leading zeros
918 i 05 Minutes with leading zeros
919 s 01 Seconds, with leading zeros
920 O -0600 Difference to Greenwich time (GMT) in hours
921 T CST Timezone setting of the machine running the code
922 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
925 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
927 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
928 document.write(dt.format('Y-m-d')); //2007-01-10
929 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
930 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
933 * Here are some standard date/time patterns that you might find helpful. They
934 * are not part of the source of Date.js, but to use them you can simply copy this
935 * block of code into any script that is included after Date.js and they will also become
936 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
939 ISO8601Long:"Y-m-d H:i:s",
940 ISO8601Short:"Y-m-d",
942 LongDate: "l, F d, Y",
943 FullDateTime: "l, F d, Y g:i:s A",
947 SortableDateTime: "Y-m-d\\TH:i:s",
948 UniversalSortableDateTime: "Y-m-d H:i:sO",
956 document.write(dt.format(Date.patterns.ShortDate));
961 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
962 * They generate precompiled functions from date formats instead of parsing and
963 * processing the pattern every time you format a date. These functions are available
964 * on every Date object (any javascript function).
966 * The original article and download are here:
967 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
974 Returns the number of milliseconds between this date and date
975 @param {Date} date (optional) Defaults to now
976 @return {Number} The diff in milliseconds
977 @member Date getElapsed
979 Date.prototype.getElapsed = function(date) {
980 return Math.abs((date || new Date()).getTime()-this.getTime());
982 // was in date file..
986 Date.parseFunctions = {count:0};
988 Date.parseRegexes = [];
990 Date.formatFunctions = {count:0};
993 Date.prototype.dateFormat = function(format) {
994 if (Date.formatFunctions[format] == null) {
995 Date.createNewFormat(format);
997 var func = Date.formatFunctions[format];
1003 * Formats a date given the supplied format string
1004 * @param {String} format The format string
1005 * @return {String} The formatted date
1008 Date.prototype.format = Date.prototype.dateFormat;
1011 Date.createNewFormat = function(format) {
1012 var funcName = "format" + Date.formatFunctions.count++;
1013 Date.formatFunctions[format] = funcName;
1014 var code = "Date.prototype." + funcName + " = function(){return ";
1015 var special = false;
1017 for (var i = 0; i < format.length; ++i) {
1018 ch = format.charAt(i);
1019 if (!special && ch == "\\") {
1024 code += "'" + String.escape(ch) + "' + ";
1027 code += Date.getFormatCode(ch);
1030 /** eval:var:zzzzzzzzzzzzz */
1031 eval(code.substring(0, code.length - 3) + ";}");
1035 Date.getFormatCode = function(character) {
1036 switch (character) {
1038 return "String.leftPad(this.getDate(), 2, '0') + ";
1040 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1042 return "this.getDate() + ";
1044 return "Date.dayNames[this.getDay()] + ";
1046 return "this.getSuffix() + ";
1048 return "this.getDay() + ";
1050 return "this.getDayOfYear() + ";
1052 return "this.getWeekOfYear() + ";
1054 return "Date.monthNames[this.getMonth()] + ";
1056 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1058 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1060 return "(this.getMonth() + 1) + ";
1062 return "this.getDaysInMonth() + ";
1064 return "(this.isLeapYear() ? 1 : 0) + ";
1066 return "this.getFullYear() + ";
1068 return "('' + this.getFullYear()).substring(2, 4) + ";
1070 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1072 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1074 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1076 return "this.getHours() + ";
1078 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1080 return "String.leftPad(this.getHours(), 2, '0') + ";
1082 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1084 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1086 return "this.getGMTOffset() + ";
1088 return "this.getTimezone() + ";
1090 return "(this.getTimezoneOffset() * -60) + ";
1092 return "'" + String.escape(character) + "' + ";
1097 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1098 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1099 * the date format that is not specified will default to the current date value for that part. Time parts can also
1100 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1101 * string or the parse operation will fail.
1104 //dt = Fri May 25 2007 (current date)
1105 var dt = new Date();
1107 //dt = Thu May 25 2006 (today's month/day in 2006)
1108 dt = Date.parseDate("2006", "Y");
1110 //dt = Sun Jan 15 2006 (all date parts specified)
1111 dt = Date.parseDate("2006-1-15", "Y-m-d");
1113 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1114 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1116 * @param {String} input The unparsed date as a string
1117 * @param {String} format The format the date is in
1118 * @return {Date} The parsed date
1121 Date.parseDate = function(input, format) {
1122 if (Date.parseFunctions[format] == null) {
1123 Date.createParser(format);
1125 var func = Date.parseFunctions[format];
1126 return Date[func](input);
1131 Date.createParser = function(format) {
1132 var funcName = "parse" + Date.parseFunctions.count++;
1133 var regexNum = Date.parseRegexes.length;
1134 var currentGroup = 1;
1135 Date.parseFunctions[format] = funcName;
1137 var code = "Date." + funcName + " = function(input){\n"
1138 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1139 + "var d = new Date();\n"
1140 + "y = d.getFullYear();\n"
1141 + "m = d.getMonth();\n"
1142 + "d = d.getDate();\n"
1143 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1144 + "if (results && results.length > 0) {";
1147 var special = false;
1149 for (var i = 0; i < format.length; ++i) {
1150 ch = format.charAt(i);
1151 if (!special && ch == "\\") {
1156 regex += String.escape(ch);
1159 var obj = Date.formatCodeToRegex(ch, currentGroup);
1160 currentGroup += obj.g;
1162 if (obj.g && obj.c) {
1168 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1169 + "{v = new Date(y, m, d, h, i, s);}\n"
1170 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1171 + "{v = new Date(y, m, d, h, i);}\n"
1172 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1173 + "{v = new Date(y, m, d, h);}\n"
1174 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1175 + "{v = new Date(y, m, d);}\n"
1176 + "else if (y >= 0 && m >= 0)\n"
1177 + "{v = new Date(y, m);}\n"
1178 + "else if (y >= 0)\n"
1179 + "{v = new Date(y);}\n"
1180 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1181 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1182 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1185 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1186 /** eval:var:zzzzzzzzzzzzz */
1191 Date.formatCodeToRegex = function(character, currentGroup) {
1192 switch (character) {
1196 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1199 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1200 s:"(\\d{1,2})"}; // day of month without leading zeroes
1203 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1204 s:"(\\d{2})"}; // day of month with leading zeroes
1208 s:"(?:" + Date.dayNames.join("|") + ")"};
1212 s:"(?:st|nd|rd|th)"};
1227 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1228 s:"(" + Date.monthNames.join("|") + ")"};
1231 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1232 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1235 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1236 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1239 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1240 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1251 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1255 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1256 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1260 c:"if (results[" + currentGroup + "] == 'am') {\n"
1261 + "if (h == 12) { h = 0; }\n"
1262 + "} else { if (h < 12) { h += 12; }}",
1266 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1267 + "if (h == 12) { h = 0; }\n"
1268 + "} else { if (h < 12) { h += 12; }}",
1273 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1274 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1278 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1279 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1282 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1286 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1291 "o = results[", currentGroup, "];\n",
1292 "var sn = o.substring(0,1);\n", // get + / - sign
1293 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1294 "var mn = o.substring(3,5) % 60;\n", // get minutes
1295 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1296 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1302 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1305 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1306 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1307 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1311 s:String.escape(character)};
1316 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1317 * @return {String} The abbreviated timezone name (e.g. 'CST')
1319 Date.prototype.getTimezone = function() {
1320 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1324 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1325 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1327 Date.prototype.getGMTOffset = function() {
1328 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1329 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1330 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1334 * Get the numeric day number of the year, adjusted for leap year.
1335 * @return {Number} 0 through 364 (365 in leap years)
1337 Date.prototype.getDayOfYear = function() {
1339 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1340 for (var i = 0; i < this.getMonth(); ++i) {
1341 num += Date.daysInMonth[i];
1343 return num + this.getDate() - 1;
1347 * Get the string representation of the numeric week number of the year
1348 * (equivalent to the format specifier 'W').
1349 * @return {String} '00' through '52'
1351 Date.prototype.getWeekOfYear = function() {
1352 // Skip to Thursday of this week
1353 var now = this.getDayOfYear() + (4 - this.getDay());
1354 // Find the first Thursday of the year
1355 var jan1 = new Date(this.getFullYear(), 0, 1);
1356 var then = (7 - jan1.getDay() + 4);
1357 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1361 * Whether or not the current date is in a leap year.
1362 * @return {Boolean} True if the current date is in a leap year, else false
1364 Date.prototype.isLeapYear = function() {
1365 var year = this.getFullYear();
1366 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1370 * Get the first day of the current month, adjusted for leap year. The returned value
1371 * is the numeric day index within the week (0-6) which can be used in conjunction with
1372 * the {@link #monthNames} array to retrieve the textual day name.
1375 var dt = new Date('1/10/2007');
1376 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1378 * @return {Number} The day number (0-6)
1380 Date.prototype.getFirstDayOfMonth = function() {
1381 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1382 return (day < 0) ? (day + 7) : day;
1386 * Get the last day of the current month, adjusted for leap year. The returned value
1387 * is the numeric day index within the week (0-6) which can be used in conjunction with
1388 * the {@link #monthNames} array to retrieve the textual day name.
1391 var dt = new Date('1/10/2007');
1392 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1394 * @return {Number} The day number (0-6)
1396 Date.prototype.getLastDayOfMonth = function() {
1397 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1398 return (day < 0) ? (day + 7) : day;
1403 * Get the first date of this date's month
1406 Date.prototype.getFirstDateOfMonth = function() {
1407 return new Date(this.getFullYear(), this.getMonth(), 1);
1411 * Get the last date of this date's month
1414 Date.prototype.getLastDateOfMonth = function() {
1415 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1418 * Get the number of days in the current month, adjusted for leap year.
1419 * @return {Number} The number of days in the month
1421 Date.prototype.getDaysInMonth = function() {
1422 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1423 return Date.daysInMonth[this.getMonth()];
1427 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1428 * @return {String} 'st, 'nd', 'rd' or 'th'
1430 Date.prototype.getSuffix = function() {
1431 switch (this.getDate()) {
1448 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1451 * An array of textual month names.
1452 * Override these values for international dates, for example...
1453 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1472 * An array of textual day names.
1473 * Override these values for international dates, for example...
1474 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1490 Date.monthNumbers = {
1505 * Creates and returns a new Date instance with the exact same date value as the called instance.
1506 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1507 * variable will also be changed. When the intention is to create a new variable that will not
1508 * modify the original instance, you should create a clone.
1510 * Example of correctly cloning a date:
1513 var orig = new Date('10/1/2006');
1516 document.write(orig); //returns 'Thu Oct 05 2006'!
1519 var orig = new Date('10/1/2006');
1520 var copy = orig.clone();
1522 document.write(orig); //returns 'Thu Oct 01 2006'
1524 * @return {Date} The new Date instance
1526 Date.prototype.clone = function() {
1527 return new Date(this.getTime());
1531 * Clears any time information from this date
1532 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1533 @return {Date} this or the clone
1535 Date.prototype.clearTime = function(clone){
1537 return this.clone().clearTime();
1542 this.setMilliseconds(0);
1547 // safari setMonth is broken
1549 Date.brokenSetMonth = Date.prototype.setMonth;
1550 Date.prototype.setMonth = function(num){
1552 var n = Math.ceil(-num);
1553 var back_year = Math.ceil(n/12);
1554 var month = (n % 12) ? 12 - n % 12 : 0 ;
1555 this.setFullYear(this.getFullYear() - back_year);
1556 return Date.brokenSetMonth.call(this, month);
1558 return Date.brokenSetMonth.apply(this, arguments);
1563 /** Date interval constant
1567 /** Date interval constant
1571 /** Date interval constant
1575 /** Date interval constant
1579 /** Date interval constant
1583 /** Date interval constant
1587 /** Date interval constant
1593 * Provides a convenient method of performing basic date arithmetic. This method
1594 * does not modify the Date instance being called - it creates and returns
1595 * a new Date instance containing the resulting date value.
1600 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1601 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1603 //Negative values will subtract correctly:
1604 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1605 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1607 //You can even chain several calls together in one line!
1608 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1609 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1612 * @param {String} interval A valid date interval enum value
1613 * @param {Number} value The amount to add to the current date
1614 * @return {Date} The new Date instance
1616 Date.prototype.add = function(interval, value){
1617 var d = this.clone();
1618 if (!interval || value === 0) return d;
1619 switch(interval.toLowerCase()){
1621 d.setMilliseconds(this.getMilliseconds() + value);
1624 d.setSeconds(this.getSeconds() + value);
1627 d.setMinutes(this.getMinutes() + value);
1630 d.setHours(this.getHours() + value);
1633 d.setDate(this.getDate() + value);
1636 var day = this.getDate();
1638 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1641 d.setMonth(this.getMonth() + value);
1644 d.setFullYear(this.getFullYear() + value);
1650 * Ext JS Library 1.1.1
1651 * Copyright(c) 2006-2007, Ext JS, LLC.
1653 * Originally Released Under LGPL - original licence link has changed is not relivant.
1656 * <script type="text/javascript">
1660 getViewWidth : function(full) {
1661 return full ? this.getDocumentWidth() : this.getViewportWidth();
1664 getViewHeight : function(full) {
1665 return full ? this.getDocumentHeight() : this.getViewportHeight();
1668 getDocumentHeight: function() {
1669 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1670 return Math.max(scrollHeight, this.getViewportHeight());
1673 getDocumentWidth: function() {
1674 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1675 return Math.max(scrollWidth, this.getViewportWidth());
1678 getViewportHeight: function() {
1679 var height = self.innerHeight;
1680 var mode = document.compatMode;
1682 if ((mode || Roo.isIE) && !Roo.isOpera) {
1683 height = (mode == "CSS1Compat") ?
1684 document.documentElement.clientHeight :
1685 document.body.clientHeight;
1691 getViewportWidth: function() {
1692 var width = self.innerWidth;
1693 var mode = document.compatMode;
1695 if (mode || Roo.isIE) {
1696 width = (mode == "CSS1Compat") ?
1697 document.documentElement.clientWidth :
1698 document.body.clientWidth;
1703 isAncestor : function(p, c) {
1710 if (p.contains && !Roo.isSafari) {
1711 return p.contains(c);
1712 } else if (p.compareDocumentPosition) {
1713 return !!(p.compareDocumentPosition(c) & 16);
1715 var parent = c.parentNode;
1720 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1723 parent = parent.parentNode;
1729 getRegion : function(el) {
1730 return Roo.lib.Region.getRegion(el);
1733 getY : function(el) {
1734 return this.getXY(el)[1];
1737 getX : function(el) {
1738 return this.getXY(el)[0];
1741 getXY : function(el) {
1742 var p, pe, b, scroll, bd = document.body;
1743 el = Roo.getDom(el);
1744 var fly = Roo.lib.AnimBase.fly;
1745 if (el.getBoundingClientRect) {
1746 b = el.getBoundingClientRect();
1747 scroll = fly(document).getScroll();
1748 return [b.left + scroll.left, b.top + scroll.top];
1754 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1761 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1768 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1769 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1776 if (p != el && pe.getStyle('overflow') != 'visible') {
1784 if (Roo.isSafari && hasAbsolute) {
1789 if (Roo.isGecko && !hasAbsolute) {
1791 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1792 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1796 while (p && p != bd) {
1797 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1809 setXY : function(el, xy) {
1810 el = Roo.fly(el, '_setXY');
1812 var pts = el.translatePoints(xy);
1813 if (xy[0] !== false) {
1814 el.dom.style.left = pts.left + "px";
1816 if (xy[1] !== false) {
1817 el.dom.style.top = pts.top + "px";
1821 setX : function(el, x) {
1822 this.setXY(el, [x, false]);
1825 setY : function(el, y) {
1826 this.setXY(el, [false, y]);
1830 * Portions of this file are based on pieces of Yahoo User Interface Library
1831 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1832 * YUI licensed under the BSD License:
1833 * http://developer.yahoo.net/yui/license.txt
1834 * <script type="text/javascript">
1838 Roo.lib.Event = function() {
1839 var loadComplete = false;
1841 var unloadListeners = [];
1843 var onAvailStack = [];
1845 var lastError = null;
1858 startInterval: function() {
1859 if (!this._interval) {
1861 var callback = function() {
1862 self._tryPreloadAttach();
1864 this._interval = setInterval(callback, this.POLL_INTERVAL);
1869 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1870 onAvailStack.push({ id: p_id,
1873 override: p_override,
1874 checkReady: false });
1876 retryCount = this.POLL_RETRYS;
1877 this.startInterval();
1881 addListener: function(el, eventName, fn) {
1882 el = Roo.getDom(el);
1887 if ("unload" == eventName) {
1888 unloadListeners[unloadListeners.length] =
1889 [el, eventName, fn];
1893 var wrappedFn = function(e) {
1894 return fn(Roo.lib.Event.getEvent(e));
1897 var li = [el, eventName, fn, wrappedFn];
1899 var index = listeners.length;
1900 listeners[index] = li;
1902 this.doAdd(el, eventName, wrappedFn, false);
1908 removeListener: function(el, eventName, fn) {
1911 el = Roo.getDom(el);
1914 return this.purgeElement(el, false, eventName);
1918 if ("unload" == eventName) {
1920 for (i = 0,len = unloadListeners.length; i < len; i++) {
1921 var li = unloadListeners[i];
1924 li[1] == eventName &&
1926 unloadListeners.splice(i, 1);
1934 var cacheItem = null;
1937 var index = arguments[3];
1939 if ("undefined" == typeof index) {
1940 index = this._getCacheIndex(el, eventName, fn);
1944 cacheItem = listeners[index];
1947 if (!el || !cacheItem) {
1951 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1953 delete listeners[index][this.WFN];
1954 delete listeners[index][this.FN];
1955 listeners.splice(index, 1);
1962 getTarget: function(ev, resolveTextNode) {
1963 ev = ev.browserEvent || ev;
1964 var t = ev.target || ev.srcElement;
1965 return this.resolveTextNode(t);
1969 resolveTextNode: function(node) {
1970 if (Roo.isSafari && node && 3 == node.nodeType) {
1971 return node.parentNode;
1978 getPageX: function(ev) {
1979 ev = ev.browserEvent || ev;
1981 if (!x && 0 !== x) {
1982 x = ev.clientX || 0;
1985 x += this.getScroll()[1];
1993 getPageY: function(ev) {
1994 ev = ev.browserEvent || ev;
1996 if (!y && 0 !== y) {
1997 y = ev.clientY || 0;
2000 y += this.getScroll()[0];
2009 getXY: function(ev) {
2010 ev = ev.browserEvent || ev;
2011 return [this.getPageX(ev), this.getPageY(ev)];
2015 getRelatedTarget: function(ev) {
2016 ev = ev.browserEvent || ev;
2017 var t = ev.relatedTarget;
2019 if (ev.type == "mouseout") {
2021 } else if (ev.type == "mouseover") {
2026 return this.resolveTextNode(t);
2030 getTime: function(ev) {
2031 ev = ev.browserEvent || ev;
2033 var t = new Date().getTime();
2037 this.lastError = ex;
2046 stopEvent: function(ev) {
2047 this.stopPropagation(ev);
2048 this.preventDefault(ev);
2052 stopPropagation: function(ev) {
2053 ev = ev.browserEvent || ev;
2054 if (ev.stopPropagation) {
2055 ev.stopPropagation();
2057 ev.cancelBubble = true;
2062 preventDefault: function(ev) {
2063 ev = ev.browserEvent || ev;
2064 if(ev.preventDefault) {
2065 ev.preventDefault();
2067 ev.returnValue = false;
2072 getEvent: function(e) {
2073 var ev = e || window.event;
2075 var c = this.getEvent.caller;
2077 ev = c.arguments[0];
2078 if (ev && Event == ev.constructor) {
2088 getCharCode: function(ev) {
2089 ev = ev.browserEvent || ev;
2090 return ev.charCode || ev.keyCode || 0;
2094 _getCacheIndex: function(el, eventName, fn) {
2095 for (var i = 0,len = listeners.length; i < len; ++i) {
2096 var li = listeners[i];
2098 li[this.FN] == fn &&
2099 li[this.EL] == el &&
2100 li[this.TYPE] == eventName) {
2112 getEl: function(id) {
2113 return document.getElementById(id);
2117 clearCache: function() {
2121 _load: function(e) {
2122 loadComplete = true;
2123 var EU = Roo.lib.Event;
2127 EU.doRemove(window, "load", EU._load);
2132 _tryPreloadAttach: function() {
2141 var tryAgain = !loadComplete;
2143 tryAgain = (retryCount > 0);
2148 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2149 var item = onAvailStack[i];
2151 var el = this.getEl(item.id);
2154 if (!item.checkReady ||
2157 (document && document.body)) {
2160 if (item.override) {
2161 if (item.override === true) {
2164 scope = item.override;
2167 item.fn.call(scope, item.obj);
2168 onAvailStack[i] = null;
2171 notAvail.push(item);
2176 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2180 this.startInterval();
2182 clearInterval(this._interval);
2183 this._interval = null;
2186 this.locked = false;
2193 purgeElement: function(el, recurse, eventName) {
2194 var elListeners = this.getListeners(el, eventName);
2196 for (var i = 0,len = elListeners.length; i < len; ++i) {
2197 var l = elListeners[i];
2198 this.removeListener(el, l.type, l.fn);
2202 if (recurse && el && el.childNodes) {
2203 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2204 this.purgeElement(el.childNodes[i], recurse, eventName);
2210 getListeners: function(el, eventName) {
2211 var results = [], searchLists;
2213 searchLists = [listeners, unloadListeners];
2214 } else if (eventName == "unload") {
2215 searchLists = [unloadListeners];
2217 searchLists = [listeners];
2220 for (var j = 0; j < searchLists.length; ++j) {
2221 var searchList = searchLists[j];
2222 if (searchList && searchList.length > 0) {
2223 for (var i = 0,len = searchList.length; i < len; ++i) {
2224 var l = searchList[i];
2225 if (l && l[this.EL] === el &&
2226 (!eventName || eventName === l[this.TYPE])) {
2231 adjust: l[this.ADJ_SCOPE],
2239 return (results.length) ? results : null;
2243 _unload: function(e) {
2245 var EU = Roo.lib.Event, i, j, l, len, index;
2247 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2248 l = unloadListeners[i];
2251 if (l[EU.ADJ_SCOPE]) {
2252 if (l[EU.ADJ_SCOPE] === true) {
2255 scope = l[EU.ADJ_SCOPE];
2258 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2259 unloadListeners[i] = null;
2265 unloadListeners = null;
2267 if (listeners && listeners.length > 0) {
2268 j = listeners.length;
2271 l = listeners[index];
2273 EU.removeListener(l[EU.EL], l[EU.TYPE],
2283 EU.doRemove(window, "unload", EU._unload);
2288 getScroll: function() {
2289 var dd = document.documentElement, db = document.body;
2290 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2291 return [dd.scrollTop, dd.scrollLeft];
2293 return [db.scrollTop, db.scrollLeft];
2300 doAdd: function () {
2301 if (window.addEventListener) {
2302 return function(el, eventName, fn, capture) {
2303 el.addEventListener(eventName, fn, (capture));
2305 } else if (window.attachEvent) {
2306 return function(el, eventName, fn, capture) {
2307 el.attachEvent("on" + eventName, fn);
2316 doRemove: function() {
2317 if (window.removeEventListener) {
2318 return function (el, eventName, fn, capture) {
2319 el.removeEventListener(eventName, fn, (capture));
2321 } else if (window.detachEvent) {
2322 return function (el, eventName, fn) {
2323 el.detachEvent("on" + eventName, fn);
2335 var E = Roo.lib.Event;
2336 E.on = E.addListener;
2337 E.un = E.removeListener;
2339 if (document && document.body) {
2342 E.doAdd(window, "load", E._load);
2344 E.doAdd(window, "unload", E._unload);
2345 E._tryPreloadAttach();
2349 * Portions of this file are based on pieces of Yahoo User Interface Library
2350 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2351 * YUI licensed under the BSD License:
2352 * http://developer.yahoo.net/yui/license.txt
2353 * <script type="text/javascript">
2360 request : function(method, uri, cb, data, options) {
2362 var hs = options.headers;
2365 if(hs.hasOwnProperty(h)){
2366 this.initHeader(h, hs[h], false);
2370 if(options.xmlData){
2371 this.initHeader('Content-Type', 'text/xml', false);
2373 data = options.xmlData;
2377 return this.asyncRequest(method, uri, cb, data);
2380 serializeForm : function(form) {
2381 if(typeof form == 'string') {
2382 form = (document.getElementById(form) || document.forms[form]);
2385 var el, name, val, disabled, data = '', hasSubmit = false;
2386 for (var i = 0; i < form.elements.length; i++) {
2387 el = form.elements[i];
2388 disabled = form.elements[i].disabled;
2389 name = form.elements[i].name;
2390 val = form.elements[i].value;
2392 if (!disabled && name){
2396 case 'select-multiple':
2397 for (var j = 0; j < el.options.length; j++) {
2398 if (el.options[j].selected) {
2400 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2403 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2411 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2424 if(hasSubmit == false) {
2425 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2430 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2435 data = data.substr(0, data.length - 1);
2443 useDefaultHeader:true,
2445 defaultPostHeader:'application/x-www-form-urlencoded',
2447 useDefaultXhrHeader:true,
2449 defaultXhrHeader:'XMLHttpRequest',
2451 hasDefaultHeaders:true,
2463 setProgId:function(id)
2465 this.activeX.unshift(id);
2468 setDefaultPostHeader:function(b)
2470 this.useDefaultHeader = b;
2473 setDefaultXhrHeader:function(b)
2475 this.useDefaultXhrHeader = b;
2478 setPollingInterval:function(i)
2480 if (typeof i == 'number' && isFinite(i)) {
2481 this.pollInterval = i;
2485 createXhrObject:function(transactionId)
2491 http = new XMLHttpRequest();
2493 obj = { conn:http, tId:transactionId };
2497 for (var i = 0; i < this.activeX.length; ++i) {
2501 http = new ActiveXObject(this.activeX[i]);
2503 obj = { conn:http, tId:transactionId };
2516 getConnectionObject:function()
2519 var tId = this.transactionId;
2523 o = this.createXhrObject(tId);
2525 this.transactionId++;
2536 asyncRequest:function(method, uri, callback, postData)
2538 var o = this.getConnectionObject();
2544 o.conn.open(method, uri, true);
2546 if (this.useDefaultXhrHeader) {
2547 if (!this.defaultHeaders['X-Requested-With']) {
2548 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2552 if(postData && this.useDefaultHeader){
2553 this.initHeader('Content-Type', this.defaultPostHeader);
2556 if (this.hasDefaultHeaders || this.hasHeaders) {
2560 this.handleReadyState(o, callback);
2561 o.conn.send(postData || null);
2567 handleReadyState:function(o, callback)
2571 if (callback && callback.timeout) {
2572 this.timeout[o.tId] = window.setTimeout(function() {
2573 oConn.abort(o, callback, true);
2574 }, callback.timeout);
2577 this.poll[o.tId] = window.setInterval(
2579 if (o.conn && o.conn.readyState == 4) {
2580 window.clearInterval(oConn.poll[o.tId]);
2581 delete oConn.poll[o.tId];
2583 if(callback && callback.timeout) {
2584 window.clearTimeout(oConn.timeout[o.tId]);
2585 delete oConn.timeout[o.tId];
2588 oConn.handleTransactionResponse(o, callback);
2591 , this.pollInterval);
2594 handleTransactionResponse:function(o, callback, isAbort)
2598 this.releaseObject(o);
2602 var httpStatus, responseObject;
2606 if (o.conn.status !== undefined && o.conn.status != 0) {
2607 httpStatus = o.conn.status;
2619 if (httpStatus >= 200 && httpStatus < 300) {
2620 responseObject = this.createResponseObject(o, callback.argument);
2621 if (callback.success) {
2622 if (!callback.scope) {
2623 callback.success(responseObject);
2628 callback.success.apply(callback.scope, [responseObject]);
2633 switch (httpStatus) {
2641 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2642 if (callback.failure) {
2643 if (!callback.scope) {
2644 callback.failure(responseObject);
2647 callback.failure.apply(callback.scope, [responseObject]);
2652 responseObject = this.createResponseObject(o, callback.argument);
2653 if (callback.failure) {
2654 if (!callback.scope) {
2655 callback.failure(responseObject);
2658 callback.failure.apply(callback.scope, [responseObject]);
2664 this.releaseObject(o);
2665 responseObject = null;
2668 createResponseObject:function(o, callbackArg)
2675 var headerStr = o.conn.getAllResponseHeaders();
2676 var header = headerStr.split('\n');
2677 for (var i = 0; i < header.length; i++) {
2678 var delimitPos = header[i].indexOf(':');
2679 if (delimitPos != -1) {
2680 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2688 obj.status = o.conn.status;
2689 obj.statusText = o.conn.statusText;
2690 obj.getResponseHeader = headerObj;
2691 obj.getAllResponseHeaders = headerStr;
2692 obj.responseText = o.conn.responseText;
2693 obj.responseXML = o.conn.responseXML;
2695 if (typeof callbackArg !== undefined) {
2696 obj.argument = callbackArg;
2702 createExceptionObject:function(tId, callbackArg, isAbort)
2705 var COMM_ERROR = 'communication failure';
2706 var ABORT_CODE = -1;
2707 var ABORT_ERROR = 'transaction aborted';
2713 obj.status = ABORT_CODE;
2714 obj.statusText = ABORT_ERROR;
2717 obj.status = COMM_CODE;
2718 obj.statusText = COMM_ERROR;
2722 obj.argument = callbackArg;
2728 initHeader:function(label, value, isDefault)
2730 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2732 if (headerObj[label] === undefined) {
2733 headerObj[label] = value;
2738 headerObj[label] = value + "," + headerObj[label];
2742 this.hasDefaultHeaders = true;
2745 this.hasHeaders = true;
2750 setHeader:function(o)
2752 if (this.hasDefaultHeaders) {
2753 for (var prop in this.defaultHeaders) {
2754 if (this.defaultHeaders.hasOwnProperty(prop)) {
2755 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2760 if (this.hasHeaders) {
2761 for (var prop in this.headers) {
2762 if (this.headers.hasOwnProperty(prop)) {
2763 o.conn.setRequestHeader(prop, this.headers[prop]);
2767 this.hasHeaders = false;
2771 resetDefaultHeaders:function() {
2772 delete this.defaultHeaders;
2773 this.defaultHeaders = {};
2774 this.hasDefaultHeaders = false;
2777 abort:function(o, callback, isTimeout)
2779 if(this.isCallInProgress(o)) {
2781 window.clearInterval(this.poll[o.tId]);
2782 delete this.poll[o.tId];
2784 delete this.timeout[o.tId];
2787 this.handleTransactionResponse(o, callback, true);
2797 isCallInProgress:function(o)
2800 return o.conn.readyState != 4 && o.conn.readyState != 0;
2809 releaseObject:function(o)
2818 'MSXML2.XMLHTTP.3.0',
2826 * Portions of this file are based on pieces of Yahoo User Interface Library
2827 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2828 * YUI licensed under the BSD License:
2829 * http://developer.yahoo.net/yui/license.txt
2830 * <script type="text/javascript">
2834 Roo.lib.Region = function(t, r, b, l) {
2844 Roo.lib.Region.prototype = {
2845 contains : function(region) {
2846 return ( region.left >= this.left &&
2847 region.right <= this.right &&
2848 region.top >= this.top &&
2849 region.bottom <= this.bottom );
2853 getArea : function() {
2854 return ( (this.bottom - this.top) * (this.right - this.left) );
2857 intersect : function(region) {
2858 var t = Math.max(this.top, region.top);
2859 var r = Math.min(this.right, region.right);
2860 var b = Math.min(this.bottom, region.bottom);
2861 var l = Math.max(this.left, region.left);
2863 if (b >= t && r >= l) {
2864 return new Roo.lib.Region(t, r, b, l);
2869 union : function(region) {
2870 var t = Math.min(this.top, region.top);
2871 var r = Math.max(this.right, region.right);
2872 var b = Math.max(this.bottom, region.bottom);
2873 var l = Math.min(this.left, region.left);
2875 return new Roo.lib.Region(t, r, b, l);
2878 adjust : function(t, l, b, r) {
2887 Roo.lib.Region.getRegion = function(el) {
2888 var p = Roo.lib.Dom.getXY(el);
2891 var r = p[0] + el.offsetWidth;
2892 var b = p[1] + el.offsetHeight;
2895 return new Roo.lib.Region(t, r, b, l);
2898 * Portions of this file are based on pieces of Yahoo User Interface Library
2899 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2900 * YUI licensed under the BSD License:
2901 * http://developer.yahoo.net/yui/license.txt
2902 * <script type="text/javascript">
2905 //@@dep Roo.lib.Region
2908 Roo.lib.Point = function(x, y) {
2909 if (x instanceof Array) {
2913 this.x = this.right = this.left = this[0] = x;
2914 this.y = this.top = this.bottom = this[1] = y;
2917 Roo.lib.Point.prototype = new Roo.lib.Region();
2919 * Portions of this file are based on pieces of Yahoo User Interface Library
2920 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2921 * YUI licensed under the BSD License:
2922 * http://developer.yahoo.net/yui/license.txt
2923 * <script type="text/javascript">
2930 scroll : function(el, args, duration, easing, cb, scope) {
2931 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2934 motion : function(el, args, duration, easing, cb, scope) {
2935 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2938 color : function(el, args, duration, easing, cb, scope) {
2939 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2942 run : function(el, args, duration, easing, cb, scope, type) {
2943 type = type || Roo.lib.AnimBase;
2944 if (typeof easing == "string") {
2945 easing = Roo.lib.Easing[easing];
2947 var anim = new type(el, args, duration, easing);
2948 anim.animateX(function() {
2949 Roo.callback(cb, scope);
2955 * Portions of this file are based on pieces of Yahoo User Interface Library
2956 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2957 * YUI licensed under the BSD License:
2958 * http://developer.yahoo.net/yui/license.txt
2959 * <script type="text/javascript">
2967 if (!libFlyweight) {
2968 libFlyweight = new Roo.Element.Flyweight();
2970 libFlyweight.dom = el;
2971 return libFlyweight;
2974 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2978 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2980 this.init(el, attributes, duration, method);
2984 Roo.lib.AnimBase.fly = fly;
2988 Roo.lib.AnimBase.prototype = {
2990 toString: function() {
2991 var el = this.getEl();
2992 var id = el.id || el.tagName;
2993 return ("Anim " + id);
2997 noNegatives: /width|height|opacity|padding/i,
2998 offsetAttribute: /^((width|height)|(top|left))$/,
2999 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3000 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3004 doMethod: function(attr, start, end) {
3005 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3009 setAttribute: function(attr, val, unit) {
3010 if (this.patterns.noNegatives.test(attr)) {
3011 val = (val > 0) ? val : 0;
3014 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3018 getAttribute: function(attr) {
3019 var el = this.getEl();
3020 var val = fly(el).getStyle(attr);
3022 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3023 return parseFloat(val);
3026 var a = this.patterns.offsetAttribute.exec(attr) || [];
3027 var pos = !!( a[3] );
3028 var box = !!( a[2] );
3031 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3032 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3041 getDefaultUnit: function(attr) {
3042 if (this.patterns.defaultUnit.test(attr)) {
3049 animateX : function(callback, scope) {
3050 var f = function() {
3051 this.onComplete.removeListener(f);
3052 if (typeof callback == "function") {
3053 callback.call(scope || this, this);
3056 this.onComplete.addListener(f, this);
3061 setRuntimeAttribute: function(attr) {
3064 var attributes = this.attributes;
3066 this.runtimeAttributes[attr] = {};
3068 var isset = function(prop) {
3069 return (typeof prop !== 'undefined');
3072 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3076 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3079 if (isset(attributes[attr]['to'])) {
3080 end = attributes[attr]['to'];
3081 } else if (isset(attributes[attr]['by'])) {
3082 if (start.constructor == Array) {
3084 for (var i = 0, len = start.length; i < len; ++i) {
3085 end[i] = start[i] + attributes[attr]['by'][i];
3088 end = start + attributes[attr]['by'];
3092 this.runtimeAttributes[attr].start = start;
3093 this.runtimeAttributes[attr].end = end;
3096 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3100 init: function(el, attributes, duration, method) {
3102 var isAnimated = false;
3105 var startTime = null;
3108 var actualFrames = 0;
3111 el = Roo.getDom(el);
3114 this.attributes = attributes || {};
3117 this.duration = duration || 1;
3120 this.method = method || Roo.lib.Easing.easeNone;
3123 this.useSeconds = true;
3126 this.currentFrame = 0;
3129 this.totalFrames = Roo.lib.AnimMgr.fps;
3132 this.getEl = function() {
3137 this.isAnimated = function() {
3142 this.getStartTime = function() {
3146 this.runtimeAttributes = {};
3149 this.animate = function() {
3150 if (this.isAnimated()) {
3154 this.currentFrame = 0;
3156 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3158 Roo.lib.AnimMgr.registerElement(this);
3162 this.stop = function(finish) {
3164 this.currentFrame = this.totalFrames;
3165 this._onTween.fire();
3167 Roo.lib.AnimMgr.stop(this);
3170 var onStart = function() {
3171 this.onStart.fire();
3173 this.runtimeAttributes = {};
3174 for (var attr in this.attributes) {
3175 this.setRuntimeAttribute(attr);
3180 startTime = new Date();
3184 var onTween = function() {
3186 duration: new Date() - this.getStartTime(),
3187 currentFrame: this.currentFrame
3190 data.toString = function() {
3192 'duration: ' + data.duration +
3193 ', currentFrame: ' + data.currentFrame
3197 this.onTween.fire(data);
3199 var runtimeAttributes = this.runtimeAttributes;
3201 for (var attr in runtimeAttributes) {
3202 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3208 var onComplete = function() {
3209 var actual_duration = (new Date() - startTime) / 1000 ;
3212 duration: actual_duration,
3213 frames: actualFrames,
3214 fps: actualFrames / actual_duration
3217 data.toString = function() {
3219 'duration: ' + data.duration +
3220 ', frames: ' + data.frames +
3221 ', fps: ' + data.fps
3227 this.onComplete.fire(data);
3231 this._onStart = new Roo.util.Event(this);
3232 this.onStart = new Roo.util.Event(this);
3233 this.onTween = new Roo.util.Event(this);
3234 this._onTween = new Roo.util.Event(this);
3235 this.onComplete = new Roo.util.Event(this);
3236 this._onComplete = new Roo.util.Event(this);
3237 this._onStart.addListener(onStart);
3238 this._onTween.addListener(onTween);
3239 this._onComplete.addListener(onComplete);
3244 * Portions of this file are based on pieces of Yahoo User Interface Library
3245 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3246 * YUI licensed under the BSD License:
3247 * http://developer.yahoo.net/yui/license.txt
3248 * <script type="text/javascript">
3252 Roo.lib.AnimMgr = new function() {
3269 this.registerElement = function(tween) {
3270 queue[queue.length] = tween;
3272 tween._onStart.fire();
3277 this.unRegister = function(tween, index) {
3278 tween._onComplete.fire();
3279 index = index || getIndex(tween);
3281 queue.splice(index, 1);
3285 if (tweenCount <= 0) {
3291 this.start = function() {
3292 if (thread === null) {
3293 thread = setInterval(this.run, this.delay);
3298 this.stop = function(tween) {
3300 clearInterval(thread);
3302 for (var i = 0, len = queue.length; i < len; ++i) {
3303 if (queue[0].isAnimated()) {
3304 this.unRegister(queue[0], 0);
3313 this.unRegister(tween);
3318 this.run = function() {
3319 for (var i = 0, len = queue.length; i < len; ++i) {
3320 var tween = queue[i];
3321 if (!tween || !tween.isAnimated()) {
3325 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3327 tween.currentFrame += 1;
3329 if (tween.useSeconds) {
3330 correctFrame(tween);
3332 tween._onTween.fire();
3335 Roo.lib.AnimMgr.stop(tween, i);
3340 var getIndex = function(anim) {
3341 for (var i = 0, len = queue.length; i < len; ++i) {
3342 if (queue[i] == anim) {
3350 var correctFrame = function(tween) {
3351 var frames = tween.totalFrames;
3352 var frame = tween.currentFrame;
3353 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3354 var elapsed = (new Date() - tween.getStartTime());
3357 if (elapsed < tween.duration * 1000) {
3358 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3360 tweak = frames - (frame + 1);
3362 if (tweak > 0 && isFinite(tweak)) {
3363 if (tween.currentFrame + tweak >= frames) {
3364 tweak = frames - (frame + 1);
3367 tween.currentFrame += tweak;
3371 * Portions of this file are based on pieces of Yahoo User Interface Library
3372 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3373 * YUI licensed under the BSD License:
3374 * http://developer.yahoo.net/yui/license.txt
3375 * <script type="text/javascript">
3378 Roo.lib.Bezier = new function() {
3380 this.getPosition = function(points, t) {
3381 var n = points.length;
3384 for (var i = 0; i < n; ++i) {
3385 tmp[i] = [points[i][0], points[i][1]];
3388 for (var j = 1; j < n; ++j) {
3389 for (i = 0; i < n - j; ++i) {
3390 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3391 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3395 return [ tmp[0][0], tmp[0][1] ];
3399 * Portions of this file are based on pieces of Yahoo User Interface Library
3400 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3401 * YUI licensed under the BSD License:
3402 * http://developer.yahoo.net/yui/license.txt
3403 * <script type="text/javascript">
3408 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3409 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3412 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3414 var fly = Roo.lib.AnimBase.fly;
3416 var superclass = Y.ColorAnim.superclass;
3417 var proto = Y.ColorAnim.prototype;
3419 proto.toString = function() {
3420 var el = this.getEl();
3421 var id = el.id || el.tagName;
3422 return ("ColorAnim " + id);
3425 proto.patterns.color = /color$/i;
3426 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3427 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3428 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3429 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3432 proto.parseColor = function(s) {
3433 if (s.length == 3) {
3437 var c = this.patterns.hex.exec(s);
3438 if (c && c.length == 4) {
3439 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3442 c = this.patterns.rgb.exec(s);
3443 if (c && c.length == 4) {
3444 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3447 c = this.patterns.hex3.exec(s);
3448 if (c && c.length == 4) {
3449 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3454 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3455 proto.getAttribute = function(attr) {
3456 var el = this.getEl();
3457 if (this.patterns.color.test(attr)) {
3458 var val = fly(el).getStyle(attr);
3460 if (this.patterns.transparent.test(val)) {
3461 var parent = el.parentNode;
3462 val = fly(parent).getStyle(attr);
3464 while (parent && this.patterns.transparent.test(val)) {
3465 parent = parent.parentNode;
3466 val = fly(parent).getStyle(attr);
3467 if (parent.tagName.toUpperCase() == 'HTML') {
3473 val = superclass.getAttribute.call(this, attr);
3478 proto.getAttribute = function(attr) {
3479 var el = this.getEl();
3480 if (this.patterns.color.test(attr)) {
3481 var val = fly(el).getStyle(attr);
3483 if (this.patterns.transparent.test(val)) {
3484 var parent = el.parentNode;
3485 val = fly(parent).getStyle(attr);
3487 while (parent && this.patterns.transparent.test(val)) {
3488 parent = parent.parentNode;
3489 val = fly(parent).getStyle(attr);
3490 if (parent.tagName.toUpperCase() == 'HTML') {
3496 val = superclass.getAttribute.call(this, attr);
3502 proto.doMethod = function(attr, start, end) {
3505 if (this.patterns.color.test(attr)) {
3507 for (var i = 0, len = start.length; i < len; ++i) {
3508 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3511 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3514 val = superclass.doMethod.call(this, attr, start, end);
3520 proto.setRuntimeAttribute = function(attr) {
3521 superclass.setRuntimeAttribute.call(this, attr);
3523 if (this.patterns.color.test(attr)) {
3524 var attributes = this.attributes;
3525 var start = this.parseColor(this.runtimeAttributes[attr].start);
3526 var end = this.parseColor(this.runtimeAttributes[attr].end);
3528 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3529 end = this.parseColor(attributes[attr].by);
3531 for (var i = 0, len = start.length; i < len; ++i) {
3532 end[i] = start[i] + end[i];
3536 this.runtimeAttributes[attr].start = start;
3537 this.runtimeAttributes[attr].end = end;
3543 * Portions of this file are based on pieces of Yahoo User Interface Library
3544 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3545 * YUI licensed under the BSD License:
3546 * http://developer.yahoo.net/yui/license.txt
3547 * <script type="text/javascript">
3553 easeNone: function (t, b, c, d) {
3554 return c * t / d + b;
3558 easeIn: function (t, b, c, d) {
3559 return c * (t /= d) * t + b;
3563 easeOut: function (t, b, c, d) {
3564 return -c * (t /= d) * (t - 2) + b;
3568 easeBoth: function (t, b, c, d) {
3569 if ((t /= d / 2) < 1) {
3570 return c / 2 * t * t + b;
3573 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3577 easeInStrong: function (t, b, c, d) {
3578 return c * (t /= d) * t * t * t + b;
3582 easeOutStrong: function (t, b, c, d) {
3583 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3587 easeBothStrong: function (t, b, c, d) {
3588 if ((t /= d / 2) < 1) {
3589 return c / 2 * t * t * t * t + b;
3592 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3597 elasticIn: function (t, b, c, d, a, p) {
3601 if ((t /= d) == 1) {
3608 if (!a || a < Math.abs(c)) {
3613 var s = p / (2 * Math.PI) * Math.asin(c / a);
3616 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3620 elasticOut: function (t, b, c, d, a, p) {
3624 if ((t /= d) == 1) {
3631 if (!a || a < Math.abs(c)) {
3636 var s = p / (2 * Math.PI) * Math.asin(c / a);
3639 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3643 elasticBoth: function (t, b, c, d, a, p) {
3648 if ((t /= d / 2) == 2) {
3656 if (!a || a < Math.abs(c)) {
3661 var s = p / (2 * Math.PI) * Math.asin(c / a);
3665 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3666 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3668 return a * Math.pow(2, -10 * (t -= 1)) *
3669 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3674 backIn: function (t, b, c, d, s) {
3675 if (typeof s == 'undefined') {
3678 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3682 backOut: function (t, b, c, d, s) {
3683 if (typeof s == 'undefined') {
3686 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3690 backBoth: function (t, b, c, d, s) {
3691 if (typeof s == 'undefined') {
3695 if ((t /= d / 2 ) < 1) {
3696 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3698 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3702 bounceIn: function (t, b, c, d) {
3703 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3707 bounceOut: function (t, b, c, d) {
3708 if ((t /= d) < (1 / 2.75)) {
3709 return c * (7.5625 * t * t) + b;
3710 } else if (t < (2 / 2.75)) {
3711 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3712 } else if (t < (2.5 / 2.75)) {
3713 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3715 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3719 bounceBoth: function (t, b, c, d) {
3721 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3723 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3726 * Portions of this file are based on pieces of Yahoo User Interface Library
3727 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3728 * YUI licensed under the BSD License:
3729 * http://developer.yahoo.net/yui/license.txt
3730 * <script type="text/javascript">
3734 Roo.lib.Motion = function(el, attributes, duration, method) {
3736 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3740 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3744 var superclass = Y.Motion.superclass;
3745 var proto = Y.Motion.prototype;
3747 proto.toString = function() {
3748 var el = this.getEl();
3749 var id = el.id || el.tagName;
3750 return ("Motion " + id);
3753 proto.patterns.points = /^points$/i;
3755 proto.setAttribute = function(attr, val, unit) {
3756 if (this.patterns.points.test(attr)) {
3757 unit = unit || 'px';
3758 superclass.setAttribute.call(this, 'left', val[0], unit);
3759 superclass.setAttribute.call(this, 'top', val[1], unit);
3761 superclass.setAttribute.call(this, attr, val, unit);
3765 proto.getAttribute = function(attr) {
3766 if (this.patterns.points.test(attr)) {
3768 superclass.getAttribute.call(this, 'left'),
3769 superclass.getAttribute.call(this, 'top')
3772 val = superclass.getAttribute.call(this, attr);
3778 proto.doMethod = function(attr, start, end) {
3781 if (this.patterns.points.test(attr)) {
3782 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3783 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3785 val = superclass.doMethod.call(this, attr, start, end);
3790 proto.setRuntimeAttribute = function(attr) {
3791 if (this.patterns.points.test(attr)) {
3792 var el = this.getEl();
3793 var attributes = this.attributes;
3795 var control = attributes['points']['control'] || [];
3799 if (control.length > 0 && !(control[0] instanceof Array)) {
3800 control = [control];
3803 for (i = 0,len = control.length; i < len; ++i) {
3804 tmp[i] = control[i];
3809 Roo.fly(el).position();
3811 if (isset(attributes['points']['from'])) {
3812 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3815 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3818 start = this.getAttribute('points');
3821 if (isset(attributes['points']['to'])) {
3822 end = translateValues.call(this, attributes['points']['to'], start);
3824 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3825 for (i = 0,len = control.length; i < len; ++i) {
3826 control[i] = translateValues.call(this, control[i], start);
3830 } else if (isset(attributes['points']['by'])) {
3831 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3833 for (i = 0,len = control.length; i < len; ++i) {
3834 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3838 this.runtimeAttributes[attr] = [start];
3840 if (control.length > 0) {
3841 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3844 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3847 superclass.setRuntimeAttribute.call(this, attr);
3851 var translateValues = function(val, start) {
3852 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3853 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3858 var isset = function(prop) {
3859 return (typeof prop !== 'undefined');
3863 * Portions of this file are based on pieces of Yahoo User Interface Library
3864 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3865 * YUI licensed under the BSD License:
3866 * http://developer.yahoo.net/yui/license.txt
3867 * <script type="text/javascript">
3871 Roo.lib.Scroll = function(el, attributes, duration, method) {
3873 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3877 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3881 var superclass = Y.Scroll.superclass;
3882 var proto = Y.Scroll.prototype;
3884 proto.toString = function() {
3885 var el = this.getEl();
3886 var id = el.id || el.tagName;
3887 return ("Scroll " + id);
3890 proto.doMethod = function(attr, start, end) {
3893 if (attr == 'scroll') {
3895 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3896 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3900 val = superclass.doMethod.call(this, attr, start, end);
3905 proto.getAttribute = function(attr) {
3907 var el = this.getEl();
3909 if (attr == 'scroll') {
3910 val = [ el.scrollLeft, el.scrollTop ];
3912 val = superclass.getAttribute.call(this, attr);
3918 proto.setAttribute = function(attr, val, unit) {
3919 var el = this.getEl();
3921 if (attr == 'scroll') {
3922 el.scrollLeft = val[0];
3923 el.scrollTop = val[1];
3925 superclass.setAttribute.call(this, attr, val, unit);
3931 * Ext JS Library 1.1.1
3932 * Copyright(c) 2006-2007, Ext JS, LLC.
3934 * Originally Released Under LGPL - original licence link has changed is not relivant.
3937 * <script type="text/javascript">
3942 * @class Roo.DomHelper
3943 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3944 * 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>.
3947 Roo.DomHelper = function(){
3948 var tempTableEl = null;
3949 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3950 var tableRe = /^table|tbody|tr|td$/i;
3952 // build as innerHTML where available
3954 var createHtml = function(o){
3955 if(typeof o == 'string'){
3964 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3965 if(attr == "style"){
3967 if(typeof s == "function"){
3970 if(typeof s == "string"){
3971 b += ' style="' + s + '"';
3972 }else if(typeof s == "object"){
3975 if(typeof s[key] != "function"){
3976 b += key + ":" + s[key] + ";";
3983 b += ' class="' + o["cls"] + '"';
3984 }else if(attr == "htmlFor"){
3985 b += ' for="' + o["htmlFor"] + '"';
3987 b += " " + attr + '="' + o[attr] + '"';
3991 if(emptyTags.test(o.tag)){
3995 var cn = o.children || o.cn;
3997 //http://bugs.kde.org/show_bug.cgi?id=71506
3998 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
3999 for(var i = 0, len = cn.length; i < len; i++) {
4000 b += createHtml(cn[i], b);
4003 b += createHtml(cn, b);
4009 b += "</" + o.tag + ">";
4016 var createDom = function(o, parentNode){
4018 // defininition craeted..
4020 if (o.ns && o.ns != 'html') {
4022 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4023 xmlns[o.ns] = o.xmlns;
4026 if (typeof(xmlns[o.ns]) == 'undefined') {
4027 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4033 if (typeof(o) == 'string') {
4034 return parentNode.appendChild(document.createTextNode(o));
4036 o.tag = o.tag || div;
4037 if (o.ns && Roo.isIE) {
4039 o.tag = o.ns + ':' + o.tag;
4042 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4043 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4046 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4047 attr == "style" || typeof o[attr] == "function") continue;
4049 if(attr=="cls" && Roo.isIE){
4050 el.className = o["cls"];
4052 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4053 else el[attr] = o[attr];
4056 Roo.DomHelper.applyStyles(el, o.style);
4057 var cn = o.children || o.cn;
4059 //http://bugs.kde.org/show_bug.cgi?id=71506
4060 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4061 for(var i = 0, len = cn.length; i < len; i++) {
4062 createDom(cn[i], el);
4069 el.innerHTML = o.html;
4072 parentNode.appendChild(el);
4077 var ieTable = function(depth, s, h, e){
4078 tempTableEl.innerHTML = [s, h, e].join('');
4079 var i = -1, el = tempTableEl;
4086 // kill repeat to save bytes
4090 tbe = '</tbody>'+te,
4096 * Nasty code for IE's broken table implementation
4098 var insertIntoTable = function(tag, where, el, html){
4100 tempTableEl = document.createElement('div');
4105 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4108 if(where == 'beforebegin'){
4112 before = el.nextSibling;
4115 node = ieTable(4, trs, html, tre);
4117 else if(tag == 'tr'){
4118 if(where == 'beforebegin'){
4121 node = ieTable(3, tbs, html, tbe);
4122 } else if(where == 'afterend'){
4123 before = el.nextSibling;
4125 node = ieTable(3, tbs, html, tbe);
4126 } else{ // INTO a TR
4127 if(where == 'afterbegin'){
4128 before = el.firstChild;
4130 node = ieTable(4, trs, html, tre);
4132 } else if(tag == 'tbody'){
4133 if(where == 'beforebegin'){
4136 node = ieTable(2, ts, html, te);
4137 } else if(where == 'afterend'){
4138 before = el.nextSibling;
4140 node = ieTable(2, ts, html, te);
4142 if(where == 'afterbegin'){
4143 before = el.firstChild;
4145 node = ieTable(3, tbs, html, tbe);
4148 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4151 if(where == 'afterbegin'){
4152 before = el.firstChild;
4154 node = ieTable(2, ts, html, te);
4156 el.insertBefore(node, before);
4161 /** True to force the use of DOM instead of html fragments @type Boolean */
4165 * Returns the markup for the passed Element(s) config
4166 * @param {Object} o The Dom object spec (and children)
4169 markup : function(o){
4170 return createHtml(o);
4174 * Applies a style specification to an element
4175 * @param {String/HTMLElement} el The element to apply styles to
4176 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4177 * a function which returns such a specification.
4179 applyStyles : function(el, styles){
4182 if(typeof styles == "string"){
4183 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4185 while ((matches = re.exec(styles)) != null){
4186 el.setStyle(matches[1], matches[2]);
4188 }else if (typeof styles == "object"){
4189 for (var style in styles){
4190 el.setStyle(style, styles[style]);
4192 }else if (typeof styles == "function"){
4193 Roo.DomHelper.applyStyles(el, styles.call());
4199 * Inserts an HTML fragment into the Dom
4200 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4201 * @param {HTMLElement} el The context element
4202 * @param {String} html The HTML fragmenet
4203 * @return {HTMLElement} The new node
4205 insertHtml : function(where, el, html){
4206 where = where.toLowerCase();
4207 if(el.insertAdjacentHTML){
4208 if(tableRe.test(el.tagName)){
4210 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4216 el.insertAdjacentHTML('BeforeBegin', html);
4217 return el.previousSibling;
4219 el.insertAdjacentHTML('AfterBegin', html);
4220 return el.firstChild;
4222 el.insertAdjacentHTML('BeforeEnd', html);
4223 return el.lastChild;
4225 el.insertAdjacentHTML('AfterEnd', html);
4226 return el.nextSibling;
4228 throw 'Illegal insertion point -> "' + where + '"';
4230 var range = el.ownerDocument.createRange();
4234 range.setStartBefore(el);
4235 frag = range.createContextualFragment(html);
4236 el.parentNode.insertBefore(frag, el);
4237 return el.previousSibling;
4240 range.setStartBefore(el.firstChild);
4241 frag = range.createContextualFragment(html);
4242 el.insertBefore(frag, el.firstChild);
4243 return el.firstChild;
4245 el.innerHTML = html;
4246 return el.firstChild;
4250 range.setStartAfter(el.lastChild);
4251 frag = range.createContextualFragment(html);
4252 el.appendChild(frag);
4253 return el.lastChild;
4255 el.innerHTML = html;
4256 return el.lastChild;
4259 range.setStartAfter(el);
4260 frag = range.createContextualFragment(html);
4261 el.parentNode.insertBefore(frag, el.nextSibling);
4262 return el.nextSibling;
4264 throw 'Illegal insertion point -> "' + where + '"';
4268 * Creates new Dom element(s) and inserts them before el
4269 * @param {String/HTMLElement/Element} el The context element
4270 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4271 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4272 * @return {HTMLElement/Roo.Element} The new node
4274 insertBefore : function(el, o, returnElement){
4275 return this.doInsert(el, o, returnElement, "beforeBegin");
4279 * Creates new Dom element(s) and inserts them after el
4280 * @param {String/HTMLElement/Element} el The context element
4281 * @param {Object} o The Dom object spec (and children)
4282 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4283 * @return {HTMLElement/Roo.Element} The new node
4285 insertAfter : function(el, o, returnElement){
4286 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4290 * Creates new Dom element(s) and inserts them as the first child of el
4291 * @param {String/HTMLElement/Element} el The context element
4292 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4293 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4294 * @return {HTMLElement/Roo.Element} The new node
4296 insertFirst : function(el, o, returnElement){
4297 return this.doInsert(el, o, returnElement, "afterBegin");
4301 doInsert : function(el, o, returnElement, pos, sibling){
4302 el = Roo.getDom(el);
4304 if(this.useDom || o.ns){
4305 newNode = createDom(o, null);
4306 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4308 var html = createHtml(o);
4309 newNode = this.insertHtml(pos, el, html);
4311 return returnElement ? Roo.get(newNode, true) : newNode;
4315 * Creates new Dom element(s) and appends them to el
4316 * @param {String/HTMLElement/Element} el The context element
4317 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4318 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4319 * @return {HTMLElement/Roo.Element} The new node
4321 append : function(el, o, returnElement){
4322 el = Roo.getDom(el);
4324 if(this.useDom || o.ns){
4325 newNode = createDom(o, null);
4326 el.appendChild(newNode);
4328 var html = createHtml(o);
4329 newNode = this.insertHtml("beforeEnd", el, html);
4331 return returnElement ? Roo.get(newNode, true) : newNode;
4335 * Creates new Dom element(s) and overwrites the contents of el with them
4336 * @param {String/HTMLElement/Element} el The context element
4337 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4338 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4339 * @return {HTMLElement/Roo.Element} The new node
4341 overwrite : function(el, o, returnElement){
4342 el = Roo.getDom(el);
4345 while (el.childNodes.length) {
4346 el.removeChild(el.firstChild);
4350 el.innerHTML = createHtml(o);
4353 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4357 * Creates a new Roo.DomHelper.Template from the Dom object spec
4358 * @param {Object} o The Dom object spec (and children)
4359 * @return {Roo.DomHelper.Template} The new template
4361 createTemplate : function(o){
4362 var html = createHtml(o);
4363 return new Roo.Template(html);
4369 * Ext JS Library 1.1.1
4370 * Copyright(c) 2006-2007, Ext JS, LLC.
4372 * Originally Released Under LGPL - original licence link has changed is not relivant.
4375 * <script type="text/javascript">
4379 * @class Roo.Template
4380 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4381 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4384 var t = new Roo.Template(
4385 '<div name="{id}">',
4386 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4389 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4391 * 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>.
4393 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4395 Roo.Template = function(html){
4396 if(html instanceof Array){
4397 html = html.join("");
4398 }else if(arguments.length > 1){
4399 html = Array.prototype.join.call(arguments, "");
4405 Roo.Template.prototype = {
4407 * Returns an HTML fragment of this template with the specified values applied.
4408 * @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'})
4409 * @return {String} The HTML fragment
4411 applyTemplate : function(values){
4413 return this.compiled(values);
4415 var useF = this.disableFormats !== true;
4416 var fm = Roo.util.Format, tpl = this;
4417 var fn = function(m, name, format, args){
4419 if(format.substr(0, 5) == "this."){
4420 return tpl.call(format.substr(5), values[name], values);
4423 // quoted values are required for strings in compiled templates,
4424 // but for non compiled we need to strip them
4425 // quoted reversed for jsmin
4426 var re = /^\s*['"](.*)["']\s*$/;
4427 args = args.split(',');
4428 for(var i = 0, len = args.length; i < len; i++){
4429 args[i] = args[i].replace(re, "$1");
4431 args = [values[name]].concat(args);
4433 args = [values[name]];
4435 return fm[format].apply(fm, args);
4438 return values[name] !== undefined ? values[name] : "";
4441 return this.html.replace(this.re, fn);
4445 * Sets the HTML used as the template and optionally compiles it.
4446 * @param {String} html
4447 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4448 * @return {Roo.Template} this
4450 set : function(html, compile){
4452 this.compiled = null;
4460 * True to disable format functions (defaults to false)
4463 disableFormats : false,
4466 * The regular expression used to match template variables
4470 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4473 * Compiles the template into an internal function, eliminating the RegEx overhead.
4474 * @return {Roo.Template} this
4476 compile : function(){
4477 var fm = Roo.util.Format;
4478 var useF = this.disableFormats !== true;
4479 var sep = Roo.isGecko ? "+" : ",";
4480 var fn = function(m, name, format, args){
4482 args = args ? ',' + args : "";
4483 if(format.substr(0, 5) != "this."){
4484 format = "fm." + format + '(';
4486 format = 'this.call("'+ format.substr(5) + '", ';
4490 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4492 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4495 // branched to use + in gecko and [].join() in others
4497 body = "this.compiled = function(values){ return '" +
4498 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4501 body = ["this.compiled = function(values){ return ['"];
4502 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4503 body.push("'].join('');};");
4504 body = body.join('');
4514 // private function used to call members
4515 call : function(fnName, value, allValues){
4516 return this[fnName](value, allValues);
4520 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4521 * @param {String/HTMLElement/Roo.Element} el The context element
4522 * @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'})
4523 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4524 * @return {HTMLElement/Roo.Element} The new node or Element
4526 insertFirst: function(el, values, returnElement){
4527 return this.doInsert('afterBegin', el, values, returnElement);
4531 * Applies the supplied values to the template and inserts the new node(s) before el.
4532 * @param {String/HTMLElement/Roo.Element} el The context element
4533 * @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'})
4534 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4535 * @return {HTMLElement/Roo.Element} The new node or Element
4537 insertBefore: function(el, values, returnElement){
4538 return this.doInsert('beforeBegin', el, values, returnElement);
4542 * Applies the supplied values to the template and inserts the new node(s) after el.
4543 * @param {String/HTMLElement/Roo.Element} el The context element
4544 * @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'})
4545 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4546 * @return {HTMLElement/Roo.Element} The new node or Element
4548 insertAfter : function(el, values, returnElement){
4549 return this.doInsert('afterEnd', el, values, returnElement);
4553 * Applies the supplied values to the template and appends the new node(s) to el.
4554 * @param {String/HTMLElement/Roo.Element} el The context element
4555 * @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'})
4556 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4557 * @return {HTMLElement/Roo.Element} The new node or Element
4559 append : function(el, values, returnElement){
4560 return this.doInsert('beforeEnd', el, values, returnElement);
4563 doInsert : function(where, el, values, returnEl){
4564 el = Roo.getDom(el);
4565 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4566 return returnEl ? Roo.get(newNode, true) : newNode;
4570 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4571 * @param {String/HTMLElement/Roo.Element} el The context element
4572 * @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'})
4573 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4574 * @return {HTMLElement/Roo.Element} The new node or Element
4576 overwrite : function(el, values, returnElement){
4577 el = Roo.getDom(el);
4578 el.innerHTML = this.applyTemplate(values);
4579 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4583 * Alias for {@link #applyTemplate}
4586 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4589 Roo.DomHelper.Template = Roo.Template;
4592 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4593 * @param {String/HTMLElement} el A DOM element or its id
4594 * @returns {Roo.Template} The created template
4597 Roo.Template.from = function(el){
4598 el = Roo.getDom(el);
4599 return new Roo.Template(el.value || el.innerHTML);
4602 * Ext JS Library 1.1.1
4603 * Copyright(c) 2006-2007, Ext JS, LLC.
4605 * Originally Released Under LGPL - original licence link has changed is not relivant.
4608 * <script type="text/javascript">
4613 * This is code is also distributed under MIT license for use
4614 * with jQuery and prototype JavaScript libraries.
4617 * @class Roo.DomQuery
4618 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).
4620 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>
4623 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.
4625 <h4>Element Selectors:</h4>
4627 <li> <b>*</b> any element</li>
4628 <li> <b>E</b> an element with the tag E</li>
4629 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4630 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4631 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4632 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4634 <h4>Attribute Selectors:</h4>
4635 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4637 <li> <b>E[foo]</b> has an attribute "foo"</li>
4638 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4639 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4640 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4641 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4642 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4643 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4645 <h4>Pseudo Classes:</h4>
4647 <li> <b>E:first-child</b> E is the first child of its parent</li>
4648 <li> <b>E:last-child</b> E is the last child of its parent</li>
4649 <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>
4650 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4651 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4652 <li> <b>E:only-child</b> E is the only child of its parent</li>
4653 <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>
4654 <li> <b>E:first</b> the first E in the resultset</li>
4655 <li> <b>E:last</b> the last E in the resultset</li>
4656 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4657 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4658 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4659 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4660 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4661 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4662 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4663 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4664 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4666 <h4>CSS Value Selectors:</h4>
4668 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4669 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4670 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4671 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4672 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4673 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4677 Roo.DomQuery = function(){
4678 var cache = {}, simpleCache = {}, valueCache = {};
4679 var nonSpace = /\S/;
4680 var trimRe = /^\s+|\s+$/g;
4681 var tplRe = /\{(\d+)\}/g;
4682 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4683 var tagTokenRe = /^(#)?([\w-\*]+)/;
4684 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4686 function child(p, index){
4688 var n = p.firstChild;
4690 if(n.nodeType == 1){
4701 while((n = n.nextSibling) && n.nodeType != 1);
4706 while((n = n.previousSibling) && n.nodeType != 1);
4710 function children(d){
4711 var n = d.firstChild, ni = -1;
4713 var nx = n.nextSibling;
4714 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4724 function byClassName(c, a, v){
4728 var r = [], ri = -1, cn;
4729 for(var i = 0, ci; ci = c[i]; i++){
4730 if((' '+ci.className+' ').indexOf(v) != -1){
4737 function attrValue(n, attr){
4738 if(!n.tagName && typeof n.length != "undefined"){
4747 if(attr == "class" || attr == "className"){
4750 return n.getAttribute(attr) || n[attr];
4754 function getNodes(ns, mode, tagName){
4755 var result = [], ri = -1, cs;
4759 tagName = tagName || "*";
4760 if(typeof ns.getElementsByTagName != "undefined"){
4764 for(var i = 0, ni; ni = ns[i]; i++){
4765 cs = ni.getElementsByTagName(tagName);
4766 for(var j = 0, ci; ci = cs[j]; j++){
4770 }else if(mode == "/" || mode == ">"){
4771 var utag = tagName.toUpperCase();
4772 for(var i = 0, ni, cn; ni = ns[i]; i++){
4773 cn = ni.children || ni.childNodes;
4774 for(var j = 0, cj; cj = cn[j]; j++){
4775 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4780 }else if(mode == "+"){
4781 var utag = tagName.toUpperCase();
4782 for(var i = 0, n; n = ns[i]; i++){
4783 while((n = n.nextSibling) && n.nodeType != 1);
4784 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4788 }else if(mode == "~"){
4789 for(var i = 0, n; n = ns[i]; i++){
4790 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4799 function concat(a, b){
4803 for(var i = 0, l = b.length; i < l; i++){
4809 function byTag(cs, tagName){
4810 if(cs.tagName || cs == document){
4816 var r = [], ri = -1;
4817 tagName = tagName.toLowerCase();
4818 for(var i = 0, ci; ci = cs[i]; i++){
4819 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4826 function byId(cs, attr, id){
4827 if(cs.tagName || cs == document){
4833 var r = [], ri = -1;
4834 for(var i = 0,ci; ci = cs[i]; i++){
4835 if(ci && ci.id == id){
4843 function byAttribute(cs, attr, value, op, custom){
4844 var r = [], ri = -1, st = custom=="{";
4845 var f = Roo.DomQuery.operators[op];
4846 for(var i = 0, ci; ci = cs[i]; i++){
4849 a = Roo.DomQuery.getStyle(ci, attr);
4851 else if(attr == "class" || attr == "className"){
4853 }else if(attr == "for"){
4855 }else if(attr == "href"){
4856 a = ci.getAttribute("href", 2);
4858 a = ci.getAttribute(attr);
4860 if((f && f(a, value)) || (!f && a)){
4867 function byPseudo(cs, name, value){
4868 return Roo.DomQuery.pseudos[name](cs, value);
4871 // This is for IE MSXML which does not support expandos.
4872 // IE runs the same speed using setAttribute, however FF slows way down
4873 // and Safari completely fails so they need to continue to use expandos.
4874 var isIE = window.ActiveXObject ? true : false;
4876 // this eval is stop the compressor from
4877 // renaming the variable to something shorter
4879 /** eval:var:batch */
4884 function nodupIEXml(cs){
4886 cs[0].setAttribute("_nodup", d);
4888 for(var i = 1, len = cs.length; i < len; i++){
4890 if(!c.getAttribute("_nodup") != d){
4891 c.setAttribute("_nodup", d);
4895 for(var i = 0, len = cs.length; i < len; i++){
4896 cs[i].removeAttribute("_nodup");
4905 var len = cs.length, c, i, r = cs, cj, ri = -1;
4906 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4909 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4910 return nodupIEXml(cs);
4914 for(i = 1; c = cs[i]; i++){
4919 for(var j = 0; j < i; j++){
4922 for(j = i+1; cj = cs[j]; j++){
4934 function quickDiffIEXml(c1, c2){
4936 for(var i = 0, len = c1.length; i < len; i++){
4937 c1[i].setAttribute("_qdiff", d);
4940 for(var i = 0, len = c2.length; i < len; i++){
4941 if(c2[i].getAttribute("_qdiff") != d){
4942 r[r.length] = c2[i];
4945 for(var i = 0, len = c1.length; i < len; i++){
4946 c1[i].removeAttribute("_qdiff");
4951 function quickDiff(c1, c2){
4952 var len1 = c1.length;
4956 if(isIE && c1[0].selectSingleNode){
4957 return quickDiffIEXml(c1, c2);
4960 for(var i = 0; i < len1; i++){
4964 for(var i = 0, len = c2.length; i < len; i++){
4965 if(c2[i]._qdiff != d){
4966 r[r.length] = c2[i];
4972 function quickId(ns, mode, root, id){
4974 var d = root.ownerDocument || root;
4975 return d.getElementById(id);
4977 ns = getNodes(ns, mode, "*");
4978 return byId(ns, null, id);
4982 getStyle : function(el, name){
4983 return Roo.fly(el).getStyle(name);
4986 * Compiles a selector/xpath query into a reusable function. The returned function
4987 * takes one parameter "root" (optional), which is the context node from where the query should start.
4988 * @param {String} selector The selector/xpath query
4989 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4990 * @return {Function}
4992 compile : function(path, type){
4993 type = type || "select";
4995 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
4996 var q = path, mode, lq;
4997 var tk = Roo.DomQuery.matchers;
4998 var tklen = tk.length;
5001 // accept leading mode switch
5002 var lmode = q.match(modeRe);
5003 if(lmode && lmode[1]){
5004 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5005 q = q.replace(lmode[1], "");
5007 // strip leading slashes
5008 while(path.substr(0, 1)=="/"){
5009 path = path.substr(1);
5012 while(q && lq != q){
5014 var tm = q.match(tagTokenRe);
5015 if(type == "select"){
5018 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5020 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5022 q = q.replace(tm[0], "");
5023 }else if(q.substr(0, 1) != '@'){
5024 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5029 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5031 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5033 q = q.replace(tm[0], "");
5036 while(!(mm = q.match(modeRe))){
5037 var matched = false;
5038 for(var j = 0; j < tklen; j++){
5040 var m = q.match(t.re);
5042 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5045 q = q.replace(m[0], "");
5050 // prevent infinite loop on bad selector
5052 throw 'Error parsing selector, parsing failed at "' + q + '"';
5056 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5057 q = q.replace(mm[1], "");
5060 fn[fn.length] = "return nodup(n);\n}";
5063 * list of variables that need from compression as they are used by eval.
5073 * eval:var:byClassName
5075 * eval:var:byAttribute
5076 * eval:var:attrValue
5084 * Selects a group of elements.
5085 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5086 * @param {Node} root (optional) The start of the query (defaults to document).
5089 select : function(path, root, type){
5090 if(!root || root == document){
5093 if(typeof root == "string"){
5094 root = document.getElementById(root);
5096 var paths = path.split(",");
5098 for(var i = 0, len = paths.length; i < len; i++){
5099 var p = paths[i].replace(trimRe, "");
5101 cache[p] = Roo.DomQuery.compile(p);
5103 throw p + " is not a valid selector";
5106 var result = cache[p](root);
5107 if(result && result != document){
5108 results = results.concat(result);
5111 if(paths.length > 1){
5112 return nodup(results);
5118 * Selects a single element.
5119 * @param {String} selector The selector/xpath query
5120 * @param {Node} root (optional) The start of the query (defaults to document).
5123 selectNode : function(path, root){
5124 return Roo.DomQuery.select(path, root)[0];
5128 * Selects the value of a node, optionally replacing null with the defaultValue.
5129 * @param {String} selector The selector/xpath query
5130 * @param {Node} root (optional) The start of the query (defaults to document).
5131 * @param {String} defaultValue
5133 selectValue : function(path, root, defaultValue){
5134 path = path.replace(trimRe, "");
5135 if(!valueCache[path]){
5136 valueCache[path] = Roo.DomQuery.compile(path, "select");
5138 var n = valueCache[path](root);
5139 n = n[0] ? n[0] : n;
5140 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5141 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5145 * Selects the value of a node, parsing integers and floats.
5146 * @param {String} selector The selector/xpath query
5147 * @param {Node} root (optional) The start of the query (defaults to document).
5148 * @param {Number} defaultValue
5151 selectNumber : function(path, root, defaultValue){
5152 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5153 return parseFloat(v);
5157 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5158 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5159 * @param {String} selector The simple selector to test
5162 is : function(el, ss){
5163 if(typeof el == "string"){
5164 el = document.getElementById(el);
5166 var isArray = (el instanceof Array);
5167 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5168 return isArray ? (result.length == el.length) : (result.length > 0);
5172 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5173 * @param {Array} el An array of elements to filter
5174 * @param {String} selector The simple selector to test
5175 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5176 * the selector instead of the ones that match
5179 filter : function(els, ss, nonMatches){
5180 ss = ss.replace(trimRe, "");
5181 if(!simpleCache[ss]){
5182 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5184 var result = simpleCache[ss](els);
5185 return nonMatches ? quickDiff(result, els) : result;
5189 * Collection of matching regular expressions and code snippets.
5193 select: 'n = byClassName(n, null, " {1} ");'
5195 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5196 select: 'n = byPseudo(n, "{1}", "{2}");'
5198 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5199 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5202 select: 'n = byId(n, null, "{1}");'
5205 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5210 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5211 * 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, > <.
5214 "=" : function(a, v){
5217 "!=" : function(a, v){
5220 "^=" : function(a, v){
5221 return a && a.substr(0, v.length) == v;
5223 "$=" : function(a, v){
5224 return a && a.substr(a.length-v.length) == v;
5226 "*=" : function(a, v){
5227 return a && a.indexOf(v) !== -1;
5229 "%=" : function(a, v){
5230 return (a % v) == 0;
5232 "|=" : function(a, v){
5233 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5235 "~=" : function(a, v){
5236 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5241 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5242 * and the argument (if any) supplied in the selector.
5245 "first-child" : function(c){
5246 var r = [], ri = -1, n;
5247 for(var i = 0, ci; ci = n = c[i]; i++){
5248 while((n = n.previousSibling) && n.nodeType != 1);
5256 "last-child" : function(c){
5257 var r = [], ri = -1, n;
5258 for(var i = 0, ci; ci = n = c[i]; i++){
5259 while((n = n.nextSibling) && n.nodeType != 1);
5267 "nth-child" : function(c, a) {
5268 var r = [], ri = -1;
5269 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5270 var f = (m[1] || 1) - 0, l = m[2] - 0;
5271 for(var i = 0, n; n = c[i]; i++){
5272 var pn = n.parentNode;
5273 if (batch != pn._batch) {
5275 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5276 if(cn.nodeType == 1){
5283 if (l == 0 || n.nodeIndex == l){
5286 } else if ((n.nodeIndex + l) % f == 0){
5294 "only-child" : function(c){
5295 var r = [], ri = -1;;
5296 for(var i = 0, ci; ci = c[i]; i++){
5297 if(!prev(ci) && !next(ci)){
5304 "empty" : function(c){
5305 var r = [], ri = -1;
5306 for(var i = 0, ci; ci = c[i]; i++){
5307 var cns = ci.childNodes, j = 0, cn, empty = true;
5310 if(cn.nodeType == 1 || cn.nodeType == 3){
5322 "contains" : function(c, v){
5323 var r = [], ri = -1;
5324 for(var i = 0, ci; ci = c[i]; i++){
5325 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5332 "nodeValue" : function(c, v){
5333 var r = [], ri = -1;
5334 for(var i = 0, ci; ci = c[i]; i++){
5335 if(ci.firstChild && ci.firstChild.nodeValue == v){
5342 "checked" : function(c){
5343 var r = [], ri = -1;
5344 for(var i = 0, ci; ci = c[i]; i++){
5345 if(ci.checked == true){
5352 "not" : function(c, ss){
5353 return Roo.DomQuery.filter(c, ss, true);
5356 "odd" : function(c){
5357 return this["nth-child"](c, "odd");
5360 "even" : function(c){
5361 return this["nth-child"](c, "even");
5364 "nth" : function(c, a){
5365 return c[a-1] || [];
5368 "first" : function(c){
5372 "last" : function(c){
5373 return c[c.length-1] || [];
5376 "has" : function(c, ss){
5377 var s = Roo.DomQuery.select;
5378 var r = [], ri = -1;
5379 for(var i = 0, ci; ci = c[i]; i++){
5380 if(s(ss, ci).length > 0){
5387 "next" : function(c, ss){
5388 var is = Roo.DomQuery.is;
5389 var r = [], ri = -1;
5390 for(var i = 0, ci; ci = c[i]; i++){
5399 "prev" : function(c, ss){
5400 var is = Roo.DomQuery.is;
5401 var r = [], ri = -1;
5402 for(var i = 0, ci; ci = c[i]; i++){
5415 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5416 * @param {String} path The selector/xpath query
5417 * @param {Node} root (optional) The start of the query (defaults to document).
5422 Roo.query = Roo.DomQuery.select;
5425 * Ext JS Library 1.1.1
5426 * Copyright(c) 2006-2007, Ext JS, LLC.
5428 * Originally Released Under LGPL - original licence link has changed is not relivant.
5431 * <script type="text/javascript">
5435 * @class Roo.util.Observable
5436 * Base class that provides a common interface for publishing events. Subclasses are expected to
5437 * to have a property "events" with all the events defined.<br>
5440 Employee = function(name){
5447 Roo.extend(Employee, Roo.util.Observable);
5449 * @param {Object} config properties to use (incuding events / listeners)
5452 Roo.util.Observable = function(cfg){
5455 this.addEvents(cfg.events || {});
5457 delete cfg.events; // make sure
5460 Roo.apply(this, cfg);
5463 this.on(this.listeners);
5464 delete this.listeners;
5467 Roo.util.Observable.prototype = {
5469 * @cfg {Object} listeners list of events and functions to call for this object,
5473 'click' : function(e) {
5483 * Fires the specified event with the passed parameters (minus the event name).
5484 * @param {String} eventName
5485 * @param {Object...} args Variable number of parameters are passed to handlers
5486 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5488 fireEvent : function(){
5489 var ce = this.events[arguments[0].toLowerCase()];
5490 if(typeof ce == "object"){
5491 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5498 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5501 * Appends an event handler to this component
5502 * @param {String} eventName The type of event to listen for
5503 * @param {Function} handler The method the event invokes
5504 * @param {Object} scope (optional) The scope in which to execute the handler
5505 * function. The handler function's "this" context.
5506 * @param {Object} options (optional) An object containing handler configuration
5507 * properties. This may contain any of the following properties:<ul>
5508 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5509 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5510 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5511 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5512 * by the specified number of milliseconds. If the event fires again within that time, the original
5513 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5516 * <b>Combining Options</b><br>
5517 * Using the options argument, it is possible to combine different types of listeners:<br>
5519 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5521 el.on('click', this.onClick, this, {
5528 * <b>Attaching multiple handlers in 1 call</b><br>
5529 * The method also allows for a single argument to be passed which is a config object containing properties
5530 * which specify multiple handlers.
5539 fn: this.onMouseOver,
5543 fn: this.onMouseOut,
5549 * Or a shorthand syntax which passes the same scope object to all handlers:
5552 'click': this.onClick,
5553 'mouseover': this.onMouseOver,
5554 'mouseout': this.onMouseOut,
5559 addListener : function(eventName, fn, scope, o){
5560 if(typeof eventName == "object"){
5563 if(this.filterOptRe.test(e)){
5566 if(typeof o[e] == "function"){
5568 this.addListener(e, o[e], o.scope, o);
5570 // individual options
5571 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5576 o = (!o || typeof o == "boolean") ? {} : o;
5577 eventName = eventName.toLowerCase();
5578 var ce = this.events[eventName] || true;
5579 if(typeof ce == "boolean"){
5580 ce = new Roo.util.Event(this, eventName);
5581 this.events[eventName] = ce;
5583 ce.addListener(fn, scope, o);
5587 * Removes a listener
5588 * @param {String} eventName The type of event to listen for
5589 * @param {Function} handler The handler to remove
5590 * @param {Object} scope (optional) The scope (this object) for the handler
5592 removeListener : function(eventName, fn, scope){
5593 var ce = this.events[eventName.toLowerCase()];
5594 if(typeof ce == "object"){
5595 ce.removeListener(fn, scope);
5600 * Removes all listeners for this object
5602 purgeListeners : function(){
5603 for(var evt in this.events){
5604 if(typeof this.events[evt] == "object"){
5605 this.events[evt].clearListeners();
5610 relayEvents : function(o, events){
5611 var createHandler = function(ename){
5613 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5616 for(var i = 0, len = events.length; i < len; i++){
5617 var ename = events[i];
5618 if(!this.events[ename]){ this.events[ename] = true; };
5619 o.on(ename, createHandler(ename), this);
5624 * Used to define events on this Observable
5625 * @param {Object} object The object with the events defined
5627 addEvents : function(o){
5631 Roo.applyIf(this.events, o);
5635 * Checks to see if this object has any listeners for a specified event
5636 * @param {String} eventName The name of the event to check for
5637 * @return {Boolean} True if the event is being listened for, else false
5639 hasListener : function(eventName){
5640 var e = this.events[eventName];
5641 return typeof e == "object" && e.listeners.length > 0;
5645 * Appends an event handler to this element (shorthand for addListener)
5646 * @param {String} eventName The type of event to listen for
5647 * @param {Function} handler The method the event invokes
5648 * @param {Object} scope (optional) The scope in which to execute the handler
5649 * function. The handler function's "this" context.
5650 * @param {Object} options (optional)
5653 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5655 * Removes a listener (shorthand for removeListener)
5656 * @param {String} eventName The type of event to listen for
5657 * @param {Function} handler The handler to remove
5658 * @param {Object} scope (optional) The scope (this object) for the handler
5661 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5664 * Starts capture on the specified Observable. All events will be passed
5665 * to the supplied function with the event name + standard signature of the event
5666 * <b>before</b> the event is fired. If the supplied function returns false,
5667 * the event will not fire.
5668 * @param {Observable} o The Observable to capture
5669 * @param {Function} fn The function to call
5670 * @param {Object} scope (optional) The scope (this object) for the fn
5673 Roo.util.Observable.capture = function(o, fn, scope){
5674 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5678 * Removes <b>all</b> added captures from the Observable.
5679 * @param {Observable} o The Observable to release
5682 Roo.util.Observable.releaseCapture = function(o){
5683 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5688 var createBuffered = function(h, o, scope){
5689 var task = new Roo.util.DelayedTask();
5691 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5695 var createSingle = function(h, e, fn, scope){
5697 e.removeListener(fn, scope);
5698 return h.apply(scope, arguments);
5702 var createDelayed = function(h, o, scope){
5704 var args = Array.prototype.slice.call(arguments, 0);
5705 setTimeout(function(){
5706 h.apply(scope, args);
5711 Roo.util.Event = function(obj, name){
5714 this.listeners = [];
5717 Roo.util.Event.prototype = {
5718 addListener : function(fn, scope, options){
5719 var o = options || {};
5720 scope = scope || this.obj;
5721 if(!this.isListening(fn, scope)){
5722 var l = {fn: fn, scope: scope, options: o};
5725 h = createDelayed(h, o, scope);
5728 h = createSingle(h, this, fn, scope);
5731 h = createBuffered(h, o, scope);
5734 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5735 this.listeners.push(l);
5737 this.listeners = this.listeners.slice(0);
5738 this.listeners.push(l);
5743 findListener : function(fn, scope){
5744 scope = scope || this.obj;
5745 var ls = this.listeners;
5746 for(var i = 0, len = ls.length; i < len; i++){
5748 if(l.fn == fn && l.scope == scope){
5755 isListening : function(fn, scope){
5756 return this.findListener(fn, scope) != -1;
5759 removeListener : function(fn, scope){
5761 if((index = this.findListener(fn, scope)) != -1){
5763 this.listeners.splice(index, 1);
5765 this.listeners = this.listeners.slice(0);
5766 this.listeners.splice(index, 1);
5773 clearListeners : function(){
5774 this.listeners = [];
5778 var ls = this.listeners, scope, len = ls.length;
5781 var args = Array.prototype.slice.call(arguments, 0);
5782 for(var i = 0; i < len; i++){
5784 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5785 this.firing = false;
5789 this.firing = false;
5796 * Ext JS Library 1.1.1
5797 * Copyright(c) 2006-2007, Ext JS, LLC.
5799 * Originally Released Under LGPL - original licence link has changed is not relivant.
5802 * <script type="text/javascript">
5806 * @class Roo.EventManager
5807 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5808 * several useful events directly.
5809 * See {@link Roo.EventObject} for more details on normalized event objects.
5812 Roo.EventManager = function(){
5813 var docReadyEvent, docReadyProcId, docReadyState = false;
5814 var resizeEvent, resizeTask, textEvent, textSize;
5815 var E = Roo.lib.Event;
5816 var D = Roo.lib.Dom;
5819 var fireDocReady = function(){
5821 docReadyState = true;
5824 clearInterval(docReadyProcId);
5826 if(Roo.isGecko || Roo.isOpera) {
5827 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5830 var defer = document.getElementById("ie-deferred-loader");
5832 defer.onreadystatechange = null;
5833 defer.parentNode.removeChild(defer);
5837 docReadyEvent.fire();
5838 docReadyEvent.clearListeners();
5843 var initDocReady = function(){
5844 docReadyEvent = new Roo.util.Event();
5845 if(Roo.isGecko || Roo.isOpera) {
5846 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5848 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5849 var defer = document.getElementById("ie-deferred-loader");
5850 defer.onreadystatechange = function(){
5851 if(this.readyState == "complete"){
5855 }else if(Roo.isSafari){
5856 docReadyProcId = setInterval(function(){
5857 var rs = document.readyState;
5858 if(rs == "complete") {
5863 // no matter what, make sure it fires on load
5864 E.on(window, "load", fireDocReady);
5867 var createBuffered = function(h, o){
5868 var task = new Roo.util.DelayedTask(h);
5870 // create new event object impl so new events don't wipe out properties
5871 e = new Roo.EventObjectImpl(e);
5872 task.delay(o.buffer, h, null, [e]);
5876 var createSingle = function(h, el, ename, fn){
5878 Roo.EventManager.removeListener(el, ename, fn);
5883 var createDelayed = function(h, o){
5885 // create new event object impl so new events don't wipe out properties
5886 e = new Roo.EventObjectImpl(e);
5887 setTimeout(function(){
5893 var listen = function(element, ename, opt, fn, scope){
5894 var o = (!opt || typeof opt == "boolean") ? {} : opt;
5895 fn = fn || o.fn; scope = scope || o.scope;
5896 var el = Roo.getDom(element);
5898 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
5900 var h = function(e){
5901 e = Roo.EventObject.setEvent(e);
5904 t = e.getTarget(o.delegate, el);
5911 if(o.stopEvent === true){
5914 if(o.preventDefault === true){
5917 if(o.stopPropagation === true){
5918 e.stopPropagation();
5921 if(o.normalized === false){
5925 fn.call(scope || el, e, t, o);
5928 h = createDelayed(h, o);
5931 h = createSingle(h, el, ename, fn);
5934 h = createBuffered(h, o);
5936 fn._handlers = fn._handlers || [];
5937 fn._handlers.push([Roo.id(el), ename, h]);
5940 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
5941 el.addEventListener("DOMMouseScroll", h, false);
5942 E.on(window, 'unload', function(){
5943 el.removeEventListener("DOMMouseScroll", h, false);
5946 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5947 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
5952 var stopListening = function(el, ename, fn){
5953 var id = Roo.id(el), hds = fn._handlers, hd = fn;
5955 for(var i = 0, len = hds.length; i < len; i++){
5957 if(h[0] == id && h[1] == ename){
5964 E.un(el, ename, hd);
5965 el = Roo.getDom(el);
5966 if(ename == "mousewheel" && el.addEventListener){
5967 el.removeEventListener("DOMMouseScroll", hd, false);
5969 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5970 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
5974 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
5981 * @scope Roo.EventManager
5986 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
5987 * object with a Roo.EventObject
5988 * @param {Function} fn The method the event invokes
5989 * @param {Object} scope An object that becomes the scope of the handler
5990 * @param {boolean} override If true, the obj passed in becomes
5991 * the execution scope of the listener
5992 * @return {Function} The wrapped function
5995 wrap : function(fn, scope, override){
5997 Roo.EventObject.setEvent(e);
5998 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6003 * Appends an event handler to an element (shorthand for addListener)
6004 * @param {String/HTMLElement} element The html element or id to assign the
6005 * @param {String} eventName The type of event to listen for
6006 * @param {Function} handler The method the event invokes
6007 * @param {Object} scope (optional) The scope in which to execute the handler
6008 * function. The handler function's "this" context.
6009 * @param {Object} options (optional) An object containing handler configuration
6010 * properties. This may contain any of the following properties:<ul>
6011 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6012 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6013 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6014 * <li>preventDefault {Boolean} True to prevent the default action</li>
6015 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6016 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6017 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6018 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6019 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6020 * by the specified number of milliseconds. If the event fires again within that time, the original
6021 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6024 * <b>Combining Options</b><br>
6025 * Using the options argument, it is possible to combine different types of listeners:<br>
6027 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6029 el.on('click', this.onClick, this, {
6036 * <b>Attaching multiple handlers in 1 call</b><br>
6037 * The method also allows for a single argument to be passed which is a config object containing properties
6038 * which specify multiple handlers.
6048 fn: this.onMouseOver
6057 * Or a shorthand syntax:<br>
6060 'click' : this.onClick,
6061 'mouseover' : this.onMouseOver,
6062 'mouseout' : this.onMouseOut
6066 addListener : function(element, eventName, fn, scope, options){
6067 if(typeof eventName == "object"){
6073 if(typeof o[e] == "function"){
6075 listen(element, e, o, o[e], o.scope);
6077 // individual options
6078 listen(element, e, o[e]);
6083 return listen(element, eventName, options, fn, scope);
6087 * Removes an event handler
6089 * @param {String/HTMLElement} element The id or html element to remove the
6091 * @param {String} eventName The type of event
6092 * @param {Function} fn
6093 * @return {Boolean} True if a listener was actually removed
6095 removeListener : function(element, eventName, fn){
6096 return stopListening(element, eventName, fn);
6100 * Fires when the document is ready (before onload and before images are loaded). Can be
6101 * accessed shorthanded Roo.onReady().
6102 * @param {Function} fn The method the event invokes
6103 * @param {Object} scope An object that becomes the scope of the handler
6104 * @param {boolean} options
6106 onDocumentReady : function(fn, scope, options){
6107 if(docReadyState){ // if it already fired
6108 docReadyEvent.addListener(fn, scope, options);
6109 docReadyEvent.fire();
6110 docReadyEvent.clearListeners();
6116 docReadyEvent.addListener(fn, scope, options);
6120 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6121 * @param {Function} fn The method the event invokes
6122 * @param {Object} scope An object that becomes the scope of the handler
6123 * @param {boolean} options
6125 onWindowResize : function(fn, scope, options){
6127 resizeEvent = new Roo.util.Event();
6128 resizeTask = new Roo.util.DelayedTask(function(){
6129 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6131 E.on(window, "resize", function(){
6133 resizeTask.delay(50);
6135 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6139 resizeEvent.addListener(fn, scope, options);
6143 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6144 * @param {Function} fn The method the event invokes
6145 * @param {Object} scope An object that becomes the scope of the handler
6146 * @param {boolean} options
6148 onTextResize : function(fn, scope, options){
6150 textEvent = new Roo.util.Event();
6151 var textEl = new Roo.Element(document.createElement('div'));
6152 textEl.dom.className = 'x-text-resize';
6153 textEl.dom.innerHTML = 'X';
6154 textEl.appendTo(document.body);
6155 textSize = textEl.dom.offsetHeight;
6156 setInterval(function(){
6157 if(textEl.dom.offsetHeight != textSize){
6158 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6160 }, this.textResizeInterval);
6162 textEvent.addListener(fn, scope, options);
6166 * Removes the passed window resize listener.
6167 * @param {Function} fn The method the event invokes
6168 * @param {Object} scope The scope of handler
6170 removeResizeListener : function(fn, scope){
6172 resizeEvent.removeListener(fn, scope);
6177 fireResize : function(){
6179 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6183 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6187 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6189 textResizeInterval : 50
6194 * @scopeAlias pub=Roo.EventManager
6198 * Appends an event handler to an element (shorthand for addListener)
6199 * @param {String/HTMLElement} element The html element or id to assign the
6200 * @param {String} eventName The type of event to listen for
6201 * @param {Function} handler The method the event invokes
6202 * @param {Object} scope (optional) The scope in which to execute the handler
6203 * function. The handler function's "this" context.
6204 * @param {Object} options (optional) An object containing handler configuration
6205 * properties. This may contain any of the following properties:<ul>
6206 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6207 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6208 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6209 * <li>preventDefault {Boolean} True to prevent the default action</li>
6210 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6211 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6212 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6213 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6214 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6215 * by the specified number of milliseconds. If the event fires again within that time, the original
6216 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6219 * <b>Combining Options</b><br>
6220 * Using the options argument, it is possible to combine different types of listeners:<br>
6222 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6224 el.on('click', this.onClick, this, {
6231 * <b>Attaching multiple handlers in 1 call</b><br>
6232 * The method also allows for a single argument to be passed which is a config object containing properties
6233 * which specify multiple handlers.
6243 fn: this.onMouseOver
6252 * Or a shorthand syntax:<br>
6255 'click' : this.onClick,
6256 'mouseover' : this.onMouseOver,
6257 'mouseout' : this.onMouseOut
6261 pub.on = pub.addListener;
6262 pub.un = pub.removeListener;
6264 pub.stoppedMouseDownEvent = new Roo.util.Event();
6268 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6269 * @param {Function} fn The method the event invokes
6270 * @param {Object} scope An object that becomes the scope of the handler
6271 * @param {boolean} override If true, the obj passed in becomes
6272 * the execution scope of the listener
6276 Roo.onReady = Roo.EventManager.onDocumentReady;
6278 Roo.onReady(function(){
6279 var bd = Roo.get(document.body);
6284 : Roo.isGecko ? "roo-gecko"
6285 : Roo.isOpera ? "roo-opera"
6286 : Roo.isSafari ? "roo-safari" : ""];
6289 cls.push("roo-mac");
6292 cls.push("roo-linux");
6294 if(Roo.isBorderBox){
6295 cls.push('roo-border-box');
6297 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6298 var p = bd.dom.parentNode;
6300 p.className += ' roo-strict';
6303 bd.addClass(cls.join(' '));
6307 * @class Roo.EventObject
6308 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6309 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6312 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6314 var target = e.getTarget();
6317 var myDiv = Roo.get("myDiv");
6318 myDiv.on("click", handleClick);
6320 Roo.EventManager.on("myDiv", 'click', handleClick);
6321 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6325 Roo.EventObject = function(){
6327 var E = Roo.lib.Event;
6329 // safari keypress events for special keys return bad keycodes
6332 63235 : 39, // right
6335 63276 : 33, // page up
6336 63277 : 34, // page down
6337 63272 : 46, // delete
6342 // normalize button clicks
6343 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6344 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6346 Roo.EventObjectImpl = function(e){
6348 this.setEvent(e.browserEvent || e);
6351 Roo.EventObjectImpl.prototype = {
6353 * Used to fix doc tools.
6354 * @scope Roo.EventObject.prototype
6360 /** The normal browser event */
6361 browserEvent : null,
6362 /** The button pressed in a mouse event */
6364 /** True if the shift key was down during the event */
6366 /** True if the control key was down during the event */
6368 /** True if the alt key was down during the event */
6427 setEvent : function(e){
6428 if(e == this || (e && e.browserEvent)){ // already wrapped
6431 this.browserEvent = e;
6433 // normalize buttons
6434 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6435 if(e.type == 'click' && this.button == -1){
6439 this.shiftKey = e.shiftKey;
6440 // mac metaKey behaves like ctrlKey
6441 this.ctrlKey = e.ctrlKey || e.metaKey;
6442 this.altKey = e.altKey;
6443 // in getKey these will be normalized for the mac
6444 this.keyCode = e.keyCode;
6445 // keyup warnings on firefox.
6446 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6447 // cache the target for the delayed and or buffered events
6448 this.target = E.getTarget(e);
6450 this.xy = E.getXY(e);
6453 this.shiftKey = false;
6454 this.ctrlKey = false;
6455 this.altKey = false;
6465 * Stop the event (preventDefault and stopPropagation)
6467 stopEvent : function(){
6468 if(this.browserEvent){
6469 if(this.browserEvent.type == 'mousedown'){
6470 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6472 E.stopEvent(this.browserEvent);
6477 * Prevents the browsers default handling of the event.
6479 preventDefault : function(){
6480 if(this.browserEvent){
6481 E.preventDefault(this.browserEvent);
6486 isNavKeyPress : function(){
6487 var k = this.keyCode;
6488 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6489 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6492 isSpecialKey : function(){
6493 var k = this.keyCode;
6494 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6495 (k == 16) || (k == 17) ||
6496 (k >= 18 && k <= 20) ||
6497 (k >= 33 && k <= 35) ||
6498 (k >= 36 && k <= 39) ||
6499 (k >= 44 && k <= 45);
6502 * Cancels bubbling of the event.
6504 stopPropagation : function(){
6505 if(this.browserEvent){
6506 if(this.type == 'mousedown'){
6507 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6509 E.stopPropagation(this.browserEvent);
6514 * Gets the key code for the event.
6517 getCharCode : function(){
6518 return this.charCode || this.keyCode;
6522 * Returns a normalized keyCode for the event.
6523 * @return {Number} The key code
6525 getKey : function(){
6526 var k = this.keyCode || this.charCode;
6527 return Roo.isSafari ? (safariKeys[k] || k) : k;
6531 * Gets the x coordinate of the event.
6534 getPageX : function(){
6539 * Gets the y coordinate of the event.
6542 getPageY : function(){
6547 * Gets the time of the event.
6550 getTime : function(){
6551 if(this.browserEvent){
6552 return E.getTime(this.browserEvent);
6558 * Gets the page coordinates of the event.
6559 * @return {Array} The xy values like [x, y]
6566 * Gets the target for the event.
6567 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6568 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6569 search as a number or element (defaults to 10 || document.body)
6570 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6571 * @return {HTMLelement}
6573 getTarget : function(selector, maxDepth, returnEl){
6574 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6577 * Gets the related target.
6578 * @return {HTMLElement}
6580 getRelatedTarget : function(){
6581 if(this.browserEvent){
6582 return E.getRelatedTarget(this.browserEvent);
6588 * Normalizes mouse wheel delta across browsers
6589 * @return {Number} The delta
6591 getWheelDelta : function(){
6592 var e = this.browserEvent;
6594 if(e.wheelDelta){ /* IE/Opera. */
6595 delta = e.wheelDelta/120;
6596 }else if(e.detail){ /* Mozilla case. */
6597 delta = -e.detail/3;
6603 * Returns true if the control, meta, shift or alt key was pressed during this event.
6606 hasModifier : function(){
6607 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6611 * Returns true if the target of this event equals el or is a child of el
6612 * @param {String/HTMLElement/Element} el
6613 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6616 within : function(el, related){
6617 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6618 return t && Roo.fly(el).contains(t);
6621 getPoint : function(){
6622 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6626 return new Roo.EventObjectImpl();
6631 * Ext JS Library 1.1.1
6632 * Copyright(c) 2006-2007, Ext JS, LLC.
6634 * Originally Released Under LGPL - original licence link has changed is not relivant.
6637 * <script type="text/javascript">
6641 // was in Composite Element!??!?!
6644 var D = Roo.lib.Dom;
6645 var E = Roo.lib.Event;
6646 var A = Roo.lib.Anim;
6648 // local style camelizing for speed
6650 var camelRe = /(-[a-z])/gi;
6651 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6652 var view = document.defaultView;
6655 * @class Roo.Element
6656 * Represents an Element in the DOM.<br><br>
6659 var el = Roo.get("my-div");
6662 var el = getEl("my-div");
6664 // or with a DOM element
6665 var el = Roo.get(myDivElement);
6667 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6668 * each call instead of constructing a new one.<br><br>
6669 * <b>Animations</b><br />
6670 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6671 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6673 Option Default Description
6674 --------- -------- ---------------------------------------------
6675 duration .35 The duration of the animation in seconds
6676 easing easeOut The YUI easing method
6677 callback none A function to execute when the anim completes
6678 scope this The scope (this) of the callback function
6680 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6681 * manipulate the animation. Here's an example:
6683 var el = Roo.get("my-div");
6688 // default animation
6689 el.setWidth(100, true);
6691 // animation with some options set
6698 // using the "anim" property to get the Anim object
6704 el.setWidth(100, opt);
6706 if(opt.anim.isAnimated()){
6710 * <b> Composite (Collections of) Elements</b><br />
6711 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6712 * @constructor Create a new Element directly.
6713 * @param {String/HTMLElement} element
6714 * @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).
6716 Roo.Element = function(element, forceNew){
6717 var dom = typeof element == "string" ?
6718 document.getElementById(element) : element;
6719 if(!dom){ // invalid id/element
6723 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6724 return Roo.Element.cache[id];
6734 * The DOM element ID
6737 this.id = id || Roo.id(dom);
6740 var El = Roo.Element;
6744 * The element's default display mode (defaults to "")
6747 originalDisplay : "",
6751 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6756 * Sets the element's visibility mode. When setVisible() is called it
6757 * will use this to determine whether to set the visibility or the display property.
6758 * @param visMode Element.VISIBILITY or Element.DISPLAY
6759 * @return {Roo.Element} this
6761 setVisibilityMode : function(visMode){
6762 this.visibilityMode = visMode;
6766 * Convenience method for setVisibilityMode(Element.DISPLAY)
6767 * @param {String} display (optional) What to set display to when visible
6768 * @return {Roo.Element} this
6770 enableDisplayMode : function(display){
6771 this.setVisibilityMode(El.DISPLAY);
6772 if(typeof display != "undefined") this.originalDisplay = display;
6777 * 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)
6778 * @param {String} selector The simple selector to test
6779 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6780 search as a number or element (defaults to 10 || document.body)
6781 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6782 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6784 findParent : function(simpleSelector, maxDepth, returnEl){
6785 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6786 maxDepth = maxDepth || 50;
6787 if(typeof maxDepth != "number"){
6788 stopEl = Roo.getDom(maxDepth);
6791 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6792 if(dq.is(p, simpleSelector)){
6793 return returnEl ? Roo.get(p) : p;
6803 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6804 * @param {String} selector The simple selector to test
6805 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6806 search as a number or element (defaults to 10 || document.body)
6807 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6808 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6810 findParentNode : function(simpleSelector, maxDepth, returnEl){
6811 var p = Roo.fly(this.dom.parentNode, '_internal');
6812 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6816 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6817 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6818 * @param {String} selector The simple selector to test
6819 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6820 search as a number or element (defaults to 10 || document.body)
6821 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6823 up : function(simpleSelector, maxDepth){
6824 return this.findParentNode(simpleSelector, maxDepth, true);
6830 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6831 * @param {String} selector The simple selector to test
6832 * @return {Boolean} True if this element matches the selector, else false
6834 is : function(simpleSelector){
6835 return Roo.DomQuery.is(this.dom, simpleSelector);
6839 * Perform animation on this element.
6840 * @param {Object} args The YUI animation control args
6841 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6842 * @param {Function} onComplete (optional) Function to call when animation completes
6843 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6844 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6845 * @return {Roo.Element} this
6847 animate : function(args, duration, onComplete, easing, animType){
6848 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6853 * @private Internal animation call
6855 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6856 animType = animType || 'run';
6858 var anim = Roo.lib.Anim[animType](
6860 (opt.duration || defaultDur) || .35,
6861 (opt.easing || defaultEase) || 'easeOut',
6863 Roo.callback(cb, this);
6864 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6872 // private legacy anim prep
6873 preanim : function(a, i){
6874 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6878 * Removes worthless text nodes
6879 * @param {Boolean} forceReclean (optional) By default the element
6880 * keeps track if it has been cleaned already so
6881 * you can call this over and over. However, if you update the element and
6882 * need to force a reclean, you can pass true.
6884 clean : function(forceReclean){
6885 if(this.isCleaned && forceReclean !== true){
6889 var d = this.dom, n = d.firstChild, ni = -1;
6891 var nx = n.nextSibling;
6892 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
6899 this.isCleaned = true;
6904 calcOffsetsTo : function(el){
6907 var restorePos = false;
6908 if(el.getStyle('position') == 'static'){
6909 el.position('relative');
6914 while(op && op != d && op.tagName != 'HTML'){
6917 op = op.offsetParent;
6920 el.position('static');
6926 * Scrolls this element into view within the passed container.
6927 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
6928 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
6929 * @return {Roo.Element} this
6931 scrollIntoView : function(container, hscroll){
6932 var c = Roo.getDom(container) || document.body;
6935 var o = this.calcOffsetsTo(c),
6938 b = t+el.offsetHeight,
6939 r = l+el.offsetWidth;
6941 var ch = c.clientHeight;
6942 var ct = parseInt(c.scrollTop, 10);
6943 var cl = parseInt(c.scrollLeft, 10);
6945 var cr = cl + c.clientWidth;
6953 if(hscroll !== false){
6957 c.scrollLeft = r-c.clientWidth;
6964 scrollChildIntoView : function(child, hscroll){
6965 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
6969 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
6970 * the new height may not be available immediately.
6971 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
6972 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
6973 * @param {Function} onComplete (optional) Function to call when animation completes
6974 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
6975 * @return {Roo.Element} this
6977 autoHeight : function(animate, duration, onComplete, easing){
6978 var oldHeight = this.getHeight();
6980 this.setHeight(1); // force clipping
6981 setTimeout(function(){
6982 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
6984 this.setHeight(height);
6986 if(typeof onComplete == "function"){
6990 this.setHeight(oldHeight); // restore original height
6991 this.setHeight(height, animate, duration, function(){
6993 if(typeof onComplete == "function") onComplete();
6994 }.createDelegate(this), easing);
6996 }.createDelegate(this), 0);
7001 * Returns true if this element is an ancestor of the passed element
7002 * @param {HTMLElement/String} el The element to check
7003 * @return {Boolean} True if this element is an ancestor of el, else false
7005 contains : function(el){
7006 if(!el){return false;}
7007 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7011 * Checks whether the element is currently visible using both visibility and display properties.
7012 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7013 * @return {Boolean} True if the element is currently visible, else false
7015 isVisible : function(deep) {
7016 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7017 if(deep !== true || !vis){
7020 var p = this.dom.parentNode;
7021 while(p && p.tagName.toLowerCase() != "body"){
7022 if(!Roo.fly(p, '_isVisible').isVisible()){
7031 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7032 * @param {String} selector The CSS selector
7033 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7034 * @return {CompositeElement/CompositeElementLite} The composite element
7036 select : function(selector, unique){
7037 return El.select(selector, unique, this.dom);
7041 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7042 * @param {String} selector The CSS selector
7043 * @return {Array} An array of the matched nodes
7045 query : function(selector, unique){
7046 return Roo.DomQuery.select(selector, this.dom);
7050 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7051 * @param {String} selector The CSS selector
7052 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7053 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7055 child : function(selector, returnDom){
7056 var n = Roo.DomQuery.selectNode(selector, this.dom);
7057 return returnDom ? n : Roo.get(n);
7061 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7062 * @param {String} selector The CSS selector
7063 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7064 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7066 down : function(selector, returnDom){
7067 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7068 return returnDom ? n : Roo.get(n);
7072 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7073 * @param {String} group The group the DD object is member of
7074 * @param {Object} config The DD config object
7075 * @param {Object} overrides An object containing methods to override/implement on the DD object
7076 * @return {Roo.dd.DD} The DD object
7078 initDD : function(group, config, overrides){
7079 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7080 return Roo.apply(dd, overrides);
7084 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7085 * @param {String} group The group the DDProxy object is member of
7086 * @param {Object} config The DDProxy config object
7087 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7088 * @return {Roo.dd.DDProxy} The DDProxy object
7090 initDDProxy : function(group, config, overrides){
7091 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7092 return Roo.apply(dd, overrides);
7096 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7097 * @param {String} group The group the DDTarget object is member of
7098 * @param {Object} config The DDTarget config object
7099 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7100 * @return {Roo.dd.DDTarget} The DDTarget object
7102 initDDTarget : function(group, config, overrides){
7103 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7104 return Roo.apply(dd, overrides);
7108 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7109 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7110 * @param {Boolean} visible Whether the element is visible
7111 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7112 * @return {Roo.Element} this
7114 setVisible : function(visible, animate){
7116 if(this.visibilityMode == El.DISPLAY){
7117 this.setDisplayed(visible);
7120 this.dom.style.visibility = visible ? "visible" : "hidden";
7123 // closure for composites
7125 var visMode = this.visibilityMode;
7127 this.setOpacity(.01);
7128 this.setVisible(true);
7130 this.anim({opacity: { to: (visible?1:0) }},
7131 this.preanim(arguments, 1),
7132 null, .35, 'easeIn', function(){
7134 if(visMode == El.DISPLAY){
7135 dom.style.display = "none";
7137 dom.style.visibility = "hidden";
7139 Roo.get(dom).setOpacity(1);
7147 * Returns true if display is not "none"
7150 isDisplayed : function() {
7151 return this.getStyle("display") != "none";
7155 * Toggles the element's visibility or display, depending on visibility mode.
7156 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7157 * @return {Roo.Element} this
7159 toggle : function(animate){
7160 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7165 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7166 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7167 * @return {Roo.Element} this
7169 setDisplayed : function(value) {
7170 if(typeof value == "boolean"){
7171 value = value ? this.originalDisplay : "none";
7173 this.setStyle("display", value);
7178 * Tries to focus the element. Any exceptions are caught and ignored.
7179 * @return {Roo.Element} this
7181 focus : function() {
7189 * Tries to blur the element. Any exceptions are caught and ignored.
7190 * @return {Roo.Element} this
7200 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7201 * @param {String/Array} className The CSS class to add, or an array of classes
7202 * @return {Roo.Element} this
7204 addClass : function(className){
7205 if(className instanceof Array){
7206 for(var i = 0, len = className.length; i < len; i++) {
7207 this.addClass(className[i]);
7210 if(className && !this.hasClass(className)){
7211 this.dom.className = this.dom.className + " " + className;
7218 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7219 * @param {String/Array} className The CSS class to add, or an array of classes
7220 * @return {Roo.Element} this
7222 radioClass : function(className){
7223 var siblings = this.dom.parentNode.childNodes;
7224 for(var i = 0; i < siblings.length; i++) {
7225 var s = siblings[i];
7226 if(s.nodeType == 1){
7227 Roo.get(s).removeClass(className);
7230 this.addClass(className);
7235 * Removes one or more CSS classes from the element.
7236 * @param {String/Array} className The CSS class to remove, or an array of classes
7237 * @return {Roo.Element} this
7239 removeClass : function(className){
7240 if(!className || !this.dom.className){
7243 if(className instanceof Array){
7244 for(var i = 0, len = className.length; i < len; i++) {
7245 this.removeClass(className[i]);
7248 if(this.hasClass(className)){
7249 var re = this.classReCache[className];
7251 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7252 this.classReCache[className] = re;
7254 this.dom.className =
7255 this.dom.className.replace(re, " ");
7265 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7266 * @param {String} className The CSS class to toggle
7267 * @return {Roo.Element} this
7269 toggleClass : function(className){
7270 if(this.hasClass(className)){
7271 this.removeClass(className);
7273 this.addClass(className);
7279 * Checks if the specified CSS class exists on this element's DOM node.
7280 * @param {String} className The CSS class to check for
7281 * @return {Boolean} True if the class exists, else false
7283 hasClass : function(className){
7284 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7288 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7289 * @param {String} oldClassName The CSS class to replace
7290 * @param {String} newClassName The replacement CSS class
7291 * @return {Roo.Element} this
7293 replaceClass : function(oldClassName, newClassName){
7294 this.removeClass(oldClassName);
7295 this.addClass(newClassName);
7300 * Returns an object with properties matching the styles requested.
7301 * For example, el.getStyles('color', 'font-size', 'width') might return
7302 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7303 * @param {String} style1 A style name
7304 * @param {String} style2 A style name
7305 * @param {String} etc.
7306 * @return {Object} The style object
7308 getStyles : function(){
7309 var a = arguments, len = a.length, r = {};
7310 for(var i = 0; i < len; i++){
7311 r[a[i]] = this.getStyle(a[i]);
7317 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7318 * @param {String} property The style property whose value is returned.
7319 * @return {String} The current value of the style property for this element.
7321 getStyle : function(){
7322 return view && view.getComputedStyle ?
7324 var el = this.dom, v, cs, camel;
7325 if(prop == 'float'){
7328 if(el.style && (v = el.style[prop])){
7331 if(cs = view.getComputedStyle(el, "")){
7332 if(!(camel = propCache[prop])){
7333 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7340 var el = this.dom, v, cs, camel;
7341 if(prop == 'opacity'){
7342 if(typeof el.style.filter == 'string'){
7343 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7345 var fv = parseFloat(m[1]);
7347 return fv ? fv / 100 : 0;
7352 }else if(prop == 'float'){
7353 prop = "styleFloat";
7355 if(!(camel = propCache[prop])){
7356 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7358 if(v = el.style[camel]){
7361 if(cs = el.currentStyle){
7369 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7370 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7371 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7372 * @return {Roo.Element} this
7374 setStyle : function(prop, value){
7375 if(typeof prop == "string"){
7377 if(!(camel = propCache[prop])){
7378 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7380 if(camel == 'opacity') {
7381 this.setOpacity(value);
7383 this.dom.style[camel] = value;
7386 for(var style in prop){
7387 if(typeof prop[style] != "function"){
7388 this.setStyle(style, prop[style]);
7396 * More flexible version of {@link #setStyle} for setting style properties.
7397 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7398 * a function which returns such a specification.
7399 * @return {Roo.Element} this
7401 applyStyles : function(style){
7402 Roo.DomHelper.applyStyles(this.dom, style);
7407 * 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).
7408 * @return {Number} The X position of the element
7411 return D.getX(this.dom);
7415 * 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).
7416 * @return {Number} The Y position of the element
7419 return D.getY(this.dom);
7423 * 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).
7424 * @return {Array} The XY position of the element
7427 return D.getXY(this.dom);
7431 * 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).
7432 * @param {Number} The X position of the element
7433 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7434 * @return {Roo.Element} this
7436 setX : function(x, animate){
7438 D.setX(this.dom, x);
7440 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7446 * 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).
7447 * @param {Number} The Y position of the element
7448 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7449 * @return {Roo.Element} this
7451 setY : function(y, animate){
7453 D.setY(this.dom, y);
7455 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7461 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7462 * @param {String} left The left CSS property value
7463 * @return {Roo.Element} this
7465 setLeft : function(left){
7466 this.setStyle("left", this.addUnits(left));
7471 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7472 * @param {String} top The top CSS property value
7473 * @return {Roo.Element} this
7475 setTop : function(top){
7476 this.setStyle("top", this.addUnits(top));
7481 * Sets the element's CSS right style.
7482 * @param {String} right The right CSS property value
7483 * @return {Roo.Element} this
7485 setRight : function(right){
7486 this.setStyle("right", this.addUnits(right));
7491 * Sets the element's CSS bottom style.
7492 * @param {String} bottom The bottom CSS property value
7493 * @return {Roo.Element} this
7495 setBottom : function(bottom){
7496 this.setStyle("bottom", this.addUnits(bottom));
7501 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7502 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7503 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7504 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7505 * @return {Roo.Element} this
7507 setXY : function(pos, animate){
7509 D.setXY(this.dom, pos);
7511 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7517 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7518 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7519 * @param {Number} x X value for new position (coordinates are page-based)
7520 * @param {Number} y Y value for new position (coordinates are page-based)
7521 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7522 * @return {Roo.Element} this
7524 setLocation : function(x, y, animate){
7525 this.setXY([x, y], this.preanim(arguments, 2));
7530 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7531 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7532 * @param {Number} x X value for new position (coordinates are page-based)
7533 * @param {Number} y Y value for new position (coordinates are page-based)
7534 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7535 * @return {Roo.Element} this
7537 moveTo : function(x, y, animate){
7538 this.setXY([x, y], this.preanim(arguments, 2));
7543 * Returns the region of the given element.
7544 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7545 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7547 getRegion : function(){
7548 return D.getRegion(this.dom);
7552 * Returns the offset height of the element
7553 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7554 * @return {Number} The element's height
7556 getHeight : function(contentHeight){
7557 var h = this.dom.offsetHeight || 0;
7558 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7562 * Returns the offset width of the element
7563 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7564 * @return {Number} The element's width
7566 getWidth : function(contentWidth){
7567 var w = this.dom.offsetWidth || 0;
7568 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7572 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7573 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7574 * if a height has not been set using CSS.
7577 getComputedHeight : function(){
7578 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7580 h = parseInt(this.getStyle('height'), 10) || 0;
7581 if(!this.isBorderBox()){
7582 h += this.getFrameWidth('tb');
7589 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7590 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7591 * if a width has not been set using CSS.
7594 getComputedWidth : function(){
7595 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7597 w = parseInt(this.getStyle('width'), 10) || 0;
7598 if(!this.isBorderBox()){
7599 w += this.getFrameWidth('lr');
7606 * Returns the size of the element.
7607 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7608 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7610 getSize : function(contentSize){
7611 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7615 * Returns the width and height of the viewport.
7616 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7618 getViewSize : function(){
7619 var d = this.dom, doc = document, aw = 0, ah = 0;
7620 if(d == doc || d == doc.body){
7621 return {width : D.getViewWidth(), height: D.getViewHeight()};
7624 width : d.clientWidth,
7625 height: d.clientHeight
7631 * Returns the value of the "value" attribute
7632 * @param {Boolean} asNumber true to parse the value as a number
7633 * @return {String/Number}
7635 getValue : function(asNumber){
7636 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7640 adjustWidth : function(width){
7641 if(typeof width == "number"){
7642 if(this.autoBoxAdjust && !this.isBorderBox()){
7643 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7653 adjustHeight : function(height){
7654 if(typeof height == "number"){
7655 if(this.autoBoxAdjust && !this.isBorderBox()){
7656 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7666 * Set the width of the element
7667 * @param {Number} width The new width
7668 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7669 * @return {Roo.Element} this
7671 setWidth : function(width, animate){
7672 width = this.adjustWidth(width);
7674 this.dom.style.width = this.addUnits(width);
7676 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7682 * Set the height of the element
7683 * @param {Number} height The new height
7684 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7685 * @return {Roo.Element} this
7687 setHeight : function(height, animate){
7688 height = this.adjustHeight(height);
7690 this.dom.style.height = this.addUnits(height);
7692 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7698 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7699 * @param {Number} width The new width
7700 * @param {Number} height The new height
7701 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7702 * @return {Roo.Element} this
7704 setSize : function(width, height, animate){
7705 if(typeof width == "object"){ // in case of object from getSize()
7706 height = width.height; width = width.width;
7708 width = this.adjustWidth(width); height = this.adjustHeight(height);
7710 this.dom.style.width = this.addUnits(width);
7711 this.dom.style.height = this.addUnits(height);
7713 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7719 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7720 * @param {Number} x X value for new position (coordinates are page-based)
7721 * @param {Number} y Y value for new position (coordinates are page-based)
7722 * @param {Number} width The new width
7723 * @param {Number} height The new height
7724 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7725 * @return {Roo.Element} this
7727 setBounds : function(x, y, width, height, animate){
7729 this.setSize(width, height);
7730 this.setLocation(x, y);
7732 width = this.adjustWidth(width); height = this.adjustHeight(height);
7733 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7734 this.preanim(arguments, 4), 'motion');
7740 * 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.
7741 * @param {Roo.lib.Region} region The region to fill
7742 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7743 * @return {Roo.Element} this
7745 setRegion : function(region, animate){
7746 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7751 * Appends an event handler
7753 * @param {String} eventName The type of event to append
7754 * @param {Function} fn The method the event invokes
7755 * @param {Object} scope (optional) The scope (this object) of the fn
7756 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7758 addListener : function(eventName, fn, scope, options){
7759 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7763 * Removes an event handler from this element
7764 * @param {String} eventName the type of event to remove
7765 * @param {Function} fn the method the event invokes
7766 * @return {Roo.Element} this
7768 removeListener : function(eventName, fn){
7769 Roo.EventManager.removeListener(this.dom, eventName, fn);
7774 * Removes all previous added listeners from this element
7775 * @return {Roo.Element} this
7777 removeAllListeners : function(){
7778 E.purgeElement(this.dom);
7782 relayEvent : function(eventName, observable){
7783 this.on(eventName, function(e){
7784 observable.fireEvent(eventName, e);
7789 * Set the opacity of the element
7790 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7791 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7792 * @return {Roo.Element} this
7794 setOpacity : function(opacity, animate){
7796 var s = this.dom.style;
7799 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7800 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7802 s.opacity = opacity;
7805 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7811 * Gets the left X coordinate
7812 * @param {Boolean} local True to get the local css position instead of page coordinate
7815 getLeft : function(local){
7819 return parseInt(this.getStyle("left"), 10) || 0;
7824 * Gets the right X coordinate of the element (element X position + element width)
7825 * @param {Boolean} local True to get the local css position instead of page coordinate
7828 getRight : function(local){
7830 return this.getX() + this.getWidth();
7832 return (this.getLeft(true) + this.getWidth()) || 0;
7837 * Gets the top Y coordinate
7838 * @param {Boolean} local True to get the local css position instead of page coordinate
7841 getTop : function(local) {
7845 return parseInt(this.getStyle("top"), 10) || 0;
7850 * Gets the bottom Y coordinate of the element (element Y position + element height)
7851 * @param {Boolean} local True to get the local css position instead of page coordinate
7854 getBottom : function(local){
7856 return this.getY() + this.getHeight();
7858 return (this.getTop(true) + this.getHeight()) || 0;
7863 * Initializes positioning on this element. If a desired position is not passed, it will make the
7864 * the element positioned relative IF it is not already positioned.
7865 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7866 * @param {Number} zIndex (optional) The zIndex to apply
7867 * @param {Number} x (optional) Set the page X position
7868 * @param {Number} y (optional) Set the page Y position
7870 position : function(pos, zIndex, x, y){
7872 if(this.getStyle('position') == 'static'){
7873 this.setStyle('position', 'relative');
7876 this.setStyle("position", pos);
7879 this.setStyle("z-index", zIndex);
7881 if(x !== undefined && y !== undefined){
7883 }else if(x !== undefined){
7885 }else if(y !== undefined){
7891 * Clear positioning back to the default when the document was loaded
7892 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7893 * @return {Roo.Element} this
7895 clearPositioning : function(value){
7903 "position" : "static"
7909 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7910 * snapshot before performing an update and then restoring the element.
7913 getPositioning : function(){
7914 var l = this.getStyle("left");
7915 var t = this.getStyle("top");
7917 "position" : this.getStyle("position"),
7919 "right" : l ? "" : this.getStyle("right"),
7921 "bottom" : t ? "" : this.getStyle("bottom"),
7922 "z-index" : this.getStyle("z-index")
7927 * Gets the width of the border(s) for the specified side(s)
7928 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7929 * passing lr would get the border (l)eft width + the border (r)ight width.
7930 * @return {Number} The width of the sides passed added together
7932 getBorderWidth : function(side){
7933 return this.addStyles(side, El.borders);
7937 * Gets the width of the padding(s) for the specified side(s)
7938 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7939 * passing lr would get the padding (l)eft + the padding (r)ight.
7940 * @return {Number} The padding of the sides passed added together
7942 getPadding : function(side){
7943 return this.addStyles(side, El.paddings);
7947 * Set positioning with an object returned by getPositioning().
7948 * @param {Object} posCfg
7949 * @return {Roo.Element} this
7951 setPositioning : function(pc){
7952 this.applyStyles(pc);
7953 if(pc.right == "auto"){
7954 this.dom.style.right = "";
7956 if(pc.bottom == "auto"){
7957 this.dom.style.bottom = "";
7963 fixDisplay : function(){
7964 if(this.getStyle("display") == "none"){
7965 this.setStyle("visibility", "hidden");
7966 this.setStyle("display", this.originalDisplay); // first try reverting to default
7967 if(this.getStyle("display") == "none"){ // if that fails, default to block
7968 this.setStyle("display", "block");
7974 * Quick set left and top adding default units
7975 * @param {String} left The left CSS property value
7976 * @param {String} top The top CSS property value
7977 * @return {Roo.Element} this
7979 setLeftTop : function(left, top){
7980 this.dom.style.left = this.addUnits(left);
7981 this.dom.style.top = this.addUnits(top);
7986 * Move this element relative to its current position.
7987 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
7988 * @param {Number} distance How far to move the element in pixels
7989 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7990 * @return {Roo.Element} this
7992 move : function(direction, distance, animate){
7993 var xy = this.getXY();
7994 direction = direction.toLowerCase();
7998 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8002 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8007 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8012 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8019 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8020 * @return {Roo.Element} this
8023 if(!this.isClipped){
8024 this.isClipped = true;
8025 this.originalClip = {
8026 "o": this.getStyle("overflow"),
8027 "x": this.getStyle("overflow-x"),
8028 "y": this.getStyle("overflow-y")
8030 this.setStyle("overflow", "hidden");
8031 this.setStyle("overflow-x", "hidden");
8032 this.setStyle("overflow-y", "hidden");
8038 * Return clipping (overflow) to original clipping before clip() was called
8039 * @return {Roo.Element} this
8041 unclip : function(){
8043 this.isClipped = false;
8044 var o = this.originalClip;
8045 if(o.o){this.setStyle("overflow", o.o);}
8046 if(o.x){this.setStyle("overflow-x", o.x);}
8047 if(o.y){this.setStyle("overflow-y", o.y);}
8054 * Gets the x,y coordinates specified by the anchor position on the element.
8055 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8056 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8057 * {width: (target width), height: (target height)} (defaults to the element's current size)
8058 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8059 * @return {Array} [x, y] An array containing the element's x and y coordinates
8061 getAnchorXY : function(anchor, local, s){
8062 //Passing a different size is useful for pre-calculating anchors,
8063 //especially for anchored animations that change the el size.
8065 var w, h, vp = false;
8068 if(d == document.body || d == document){
8070 w = D.getViewWidth(); h = D.getViewHeight();
8072 w = this.getWidth(); h = this.getHeight();
8075 w = s.width; h = s.height;
8077 var x = 0, y = 0, r = Math.round;
8078 switch((anchor || "tl").toLowerCase()){
8120 var sc = this.getScroll();
8121 return [x + sc.left, y + sc.top];
8123 //Add the element's offset xy
8124 var o = this.getXY();
8125 return [x+o[0], y+o[1]];
8129 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8130 * supported position values.
8131 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8132 * @param {String} position The position to align to.
8133 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8134 * @return {Array} [x, y]
8136 getAlignToXY : function(el, p, o){
8140 throw "Element.alignTo with an element that doesn't exist";
8142 var c = false; //constrain to viewport
8143 var p1 = "", p2 = "";
8150 }else if(p.indexOf("-") == -1){
8153 p = p.toLowerCase();
8154 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8156 throw "Element.alignTo with an invalid alignment " + p;
8158 p1 = m[1]; p2 = m[2]; c = !!m[3];
8160 //Subtract the aligned el's internal xy from the target's offset xy
8161 //plus custom offset to get the aligned el's new offset xy
8162 var a1 = this.getAnchorXY(p1, true);
8163 var a2 = el.getAnchorXY(p2, false);
8164 var x = a2[0] - a1[0] + o[0];
8165 var y = a2[1] - a1[1] + o[1];
8167 //constrain the aligned el to viewport if necessary
8168 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8169 // 5px of margin for ie
8170 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8172 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8173 //perpendicular to the vp border, allow the aligned el to slide on that border,
8174 //otherwise swap the aligned el to the opposite border of the target.
8175 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8176 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8177 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8178 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8181 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8182 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8184 if((x+w) > dw + scrollX){
8185 x = swapX ? r.left-w : dw+scrollX-w;
8188 x = swapX ? r.right : scrollX;
8190 if((y+h) > dh + scrollY){
8191 y = swapY ? r.top-h : dh+scrollY-h;
8194 y = swapY ? r.bottom : scrollY;
8201 getConstrainToXY : function(){
8202 var os = {top:0, left:0, bottom:0, right: 0};
8204 return function(el, local, offsets, proposedXY){
8206 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8208 var vw, vh, vx = 0, vy = 0;
8209 if(el.dom == document.body || el.dom == document){
8210 vw = Roo.lib.Dom.getViewWidth();
8211 vh = Roo.lib.Dom.getViewHeight();
8213 vw = el.dom.clientWidth;
8214 vh = el.dom.clientHeight;
8216 var vxy = el.getXY();
8222 var s = el.getScroll();
8224 vx += offsets.left + s.left;
8225 vy += offsets.top + s.top;
8227 vw -= offsets.right;
8228 vh -= offsets.bottom;
8233 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8234 var x = xy[0], y = xy[1];
8235 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8237 // only move it if it needs it
8240 // first validate right/bottom
8249 // then make sure top/left isn't negative
8258 return moved ? [x, y] : false;
8263 adjustForConstraints : function(xy, parent, offsets){
8264 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8268 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8269 * document it aligns it to the viewport.
8270 * The position parameter is optional, and can be specified in any one of the following formats:
8272 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8273 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8274 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8275 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8276 * <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
8277 * element's anchor point, and the second value is used as the target's anchor point.</li>
8279 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8280 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8281 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8282 * that specified in order to enforce the viewport constraints.
8283 * Following are all of the supported anchor positions:
8286 ----- -----------------------------
8287 tl The top left corner (default)
8288 t The center of the top edge
8289 tr The top right corner
8290 l The center of the left edge
8291 c In the center of the element
8292 r The center of the right edge
8293 bl The bottom left corner
8294 b The center of the bottom edge
8295 br The bottom right corner
8299 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8300 el.alignTo("other-el");
8302 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8303 el.alignTo("other-el", "tr?");
8305 // align the bottom right corner of el with the center left edge of other-el
8306 el.alignTo("other-el", "br-l?");
8308 // align the center of el with the bottom left corner of other-el and
8309 // adjust the x position by -6 pixels (and the y position by 0)
8310 el.alignTo("other-el", "c-bl", [-6, 0]);
8312 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8313 * @param {String} position The position to align to.
8314 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8315 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8316 * @return {Roo.Element} this
8318 alignTo : function(element, position, offsets, animate){
8319 var xy = this.getAlignToXY(element, position, offsets);
8320 this.setXY(xy, this.preanim(arguments, 3));
8325 * Anchors an element to another element and realigns it when the window is resized.
8326 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8327 * @param {String} position The position to align to.
8328 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8329 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8330 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8331 * is a number, it is used as the buffer delay (defaults to 50ms).
8332 * @param {Function} callback The function to call after the animation finishes
8333 * @return {Roo.Element} this
8335 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8336 var action = function(){
8337 this.alignTo(el, alignment, offsets, animate);
8338 Roo.callback(callback, this);
8340 Roo.EventManager.onWindowResize(action, this);
8341 var tm = typeof monitorScroll;
8342 if(tm != 'undefined'){
8343 Roo.EventManager.on(window, 'scroll', action, this,
8344 {buffer: tm == 'number' ? monitorScroll : 50});
8346 action.call(this); // align immediately
8350 * Clears any opacity settings from this element. Required in some cases for IE.
8351 * @return {Roo.Element} this
8353 clearOpacity : function(){
8354 if (window.ActiveXObject) {
8355 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8356 this.dom.style.filter = "";
8359 this.dom.style.opacity = "";
8360 this.dom.style["-moz-opacity"] = "";
8361 this.dom.style["-khtml-opacity"] = "";
8367 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8368 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8369 * @return {Roo.Element} this
8371 hide : function(animate){
8372 this.setVisible(false, this.preanim(arguments, 0));
8377 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8378 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8379 * @return {Roo.Element} this
8381 show : function(animate){
8382 this.setVisible(true, this.preanim(arguments, 0));
8387 * @private Test if size has a unit, otherwise appends the default
8389 addUnits : function(size){
8390 return Roo.Element.addUnits(size, this.defaultUnit);
8394 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8395 * @return {Roo.Element} this
8397 beginMeasure : function(){
8399 if(el.offsetWidth || el.offsetHeight){
8400 return this; // offsets work already
8403 var p = this.dom, b = document.body; // start with this element
8404 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8405 var pe = Roo.get(p);
8406 if(pe.getStyle('display') == 'none'){
8407 changed.push({el: p, visibility: pe.getStyle("visibility")});
8408 p.style.visibility = "hidden";
8409 p.style.display = "block";
8413 this._measureChanged = changed;
8419 * Restores displays to before beginMeasure was called
8420 * @return {Roo.Element} this
8422 endMeasure : function(){
8423 var changed = this._measureChanged;
8425 for(var i = 0, len = changed.length; i < len; i++) {
8427 r.el.style.visibility = r.visibility;
8428 r.el.style.display = "none";
8430 this._measureChanged = null;
8436 * Update the innerHTML of this element, optionally searching for and processing scripts
8437 * @param {String} html The new HTML
8438 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8439 * @param {Function} callback For async script loading you can be noticed when the update completes
8440 * @return {Roo.Element} this
8442 update : function(html, loadScripts, callback){
8443 if(typeof html == "undefined"){
8446 if(loadScripts !== true){
8447 this.dom.innerHTML = html;
8448 if(typeof callback == "function"){
8456 html += '<span id="' + id + '"></span>';
8458 E.onAvailable(id, function(){
8459 var hd = document.getElementsByTagName("head")[0];
8460 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8461 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8462 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8465 while(match = re.exec(html)){
8466 var attrs = match[1];
8467 var srcMatch = attrs ? attrs.match(srcRe) : false;
8468 if(srcMatch && srcMatch[2]){
8469 var s = document.createElement("script");
8470 s.src = srcMatch[2];
8471 var typeMatch = attrs.match(typeRe);
8472 if(typeMatch && typeMatch[2]){
8473 s.type = typeMatch[2];
8476 }else if(match[2] && match[2].length > 0){
8477 if(window.execScript) {
8478 window.execScript(match[2]);
8486 window.eval(match[2]);
8490 var el = document.getElementById(id);
8491 if(el){el.parentNode.removeChild(el);}
8492 if(typeof callback == "function"){
8496 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8501 * Direct access to the UpdateManager update() method (takes the same parameters).
8502 * @param {String/Function} url The url for this request or a function to call to get the url
8503 * @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}
8504 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8505 * @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.
8506 * @return {Roo.Element} this
8509 var um = this.getUpdateManager();
8510 um.update.apply(um, arguments);
8515 * Gets this element's UpdateManager
8516 * @return {Roo.UpdateManager} The UpdateManager
8518 getUpdateManager : function(){
8519 if(!this.updateManager){
8520 this.updateManager = new Roo.UpdateManager(this);
8522 return this.updateManager;
8526 * Disables text selection for this element (normalized across browsers)
8527 * @return {Roo.Element} this
8529 unselectable : function(){
8530 this.dom.unselectable = "on";
8531 this.swallowEvent("selectstart", true);
8532 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8533 this.addClass("x-unselectable");
8538 * Calculates the x, y to center this element on the screen
8539 * @return {Array} The x, y values [x, y]
8541 getCenterXY : function(){
8542 return this.getAlignToXY(document, 'c-c');
8546 * Centers the Element in either the viewport, or another Element.
8547 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8549 center : function(centerIn){
8550 this.alignTo(centerIn || document, 'c-c');
8555 * Tests various css rules/browsers to determine if this element uses a border box
8558 isBorderBox : function(){
8559 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8563 * Return a box {x, y, width, height} that can be used to set another elements
8564 * size/location to match this element.
8565 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8566 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8567 * @return {Object} box An object in the format {x, y, width, height}
8569 getBox : function(contentBox, local){
8574 var left = parseInt(this.getStyle("left"), 10) || 0;
8575 var top = parseInt(this.getStyle("top"), 10) || 0;
8578 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8580 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8582 var l = this.getBorderWidth("l")+this.getPadding("l");
8583 var r = this.getBorderWidth("r")+this.getPadding("r");
8584 var t = this.getBorderWidth("t")+this.getPadding("t");
8585 var b = this.getBorderWidth("b")+this.getPadding("b");
8586 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)};
8588 bx.right = bx.x + bx.width;
8589 bx.bottom = bx.y + bx.height;
8594 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8595 for more information about the sides.
8596 * @param {String} sides
8599 getFrameWidth : function(sides, onlyContentBox){
8600 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8604 * 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.
8605 * @param {Object} box The box to fill {x, y, width, height}
8606 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8607 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8608 * @return {Roo.Element} this
8610 setBox : function(box, adjust, animate){
8611 var w = box.width, h = box.height;
8612 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8613 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8614 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8616 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8621 * Forces the browser to repaint this element
8622 * @return {Roo.Element} this
8624 repaint : function(){
8626 this.addClass("x-repaint");
8627 setTimeout(function(){
8628 Roo.get(dom).removeClass("x-repaint");
8634 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8635 * then it returns the calculated width of the sides (see getPadding)
8636 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8637 * @return {Object/Number}
8639 getMargins : function(side){
8642 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8643 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8644 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8645 right: parseInt(this.getStyle("margin-right"), 10) || 0
8648 return this.addStyles(side, El.margins);
8653 addStyles : function(sides, styles){
8655 for(var i = 0, len = sides.length; i < len; i++){
8656 v = this.getStyle(styles[sides.charAt(i)]);
8658 w = parseInt(v, 10);
8666 * Creates a proxy element of this element
8667 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8668 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8669 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8670 * @return {Roo.Element} The new proxy element
8672 createProxy : function(config, renderTo, matchBox){
8674 renderTo = Roo.getDom(renderTo);
8676 renderTo = document.body;
8678 config = typeof config == "object" ?
8679 config : {tag : "div", cls: config};
8680 var proxy = Roo.DomHelper.append(renderTo, config, true);
8682 proxy.setBox(this.getBox());
8688 * Puts a mask over this element to disable user interaction. Requires core.css.
8689 * This method can only be applied to elements which accept child nodes.
8690 * @param {String} msg (optional) A message to display in the mask
8691 * @param {String} msgCls (optional) A css class to apply to the msg element
8692 * @return {Element} The mask element
8694 mask : function(msg, msgCls){
8695 if(this.getStyle("position") == "static"){
8696 this.setStyle("position", "relative");
8699 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8701 this.addClass("x-masked");
8702 this._mask.setDisplayed(true);
8703 if(typeof msg == 'string'){
8705 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8707 var mm = this._maskMsg;
8708 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8709 mm.dom.firstChild.innerHTML = msg;
8710 mm.setDisplayed(true);
8713 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8714 this._mask.setHeight(this.getHeight());
8720 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8721 * it is cached for reuse.
8723 unmask : function(removeEl){
8725 if(removeEl === true){
8726 this._mask.remove();
8729 this._maskMsg.remove();
8730 delete this._maskMsg;
8733 this._mask.setDisplayed(false);
8735 this._maskMsg.setDisplayed(false);
8739 this.removeClass("x-masked");
8743 * Returns true if this element is masked
8746 isMasked : function(){
8747 return this._mask && this._mask.isVisible();
8751 * Creates an iframe shim for this element to keep selects and other windowed objects from
8753 * @return {Roo.Element} The new shim element
8755 createShim : function(){
8756 var el = document.createElement('iframe');
8757 el.frameBorder = 'no';
8758 el.className = 'roo-shim';
8759 if(Roo.isIE && Roo.isSecure){
8760 el.src = Roo.SSL_SECURE_URL;
8762 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8763 shim.autoBoxAdjust = false;
8768 * Removes this element from the DOM and deletes it from the cache
8770 remove : function(){
8771 if(this.dom.parentNode){
8772 this.dom.parentNode.removeChild(this.dom);
8774 delete El.cache[this.dom.id];
8778 * Sets up event handlers to add and remove a css class when the mouse is over this element
8779 * @param {String} className
8780 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8781 * mouseout events for children elements
8782 * @return {Roo.Element} this
8784 addClassOnOver : function(className, preventFlicker){
8785 this.on("mouseover", function(){
8786 Roo.fly(this, '_internal').addClass(className);
8788 var removeFn = function(e){
8789 if(preventFlicker !== true || !e.within(this, true)){
8790 Roo.fly(this, '_internal').removeClass(className);
8793 this.on("mouseout", removeFn, this.dom);
8798 * Sets up event handlers to add and remove a css class when this element has the focus
8799 * @param {String} className
8800 * @return {Roo.Element} this
8802 addClassOnFocus : function(className){
8803 this.on("focus", function(){
8804 Roo.fly(this, '_internal').addClass(className);
8806 this.on("blur", function(){
8807 Roo.fly(this, '_internal').removeClass(className);
8812 * 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)
8813 * @param {String} className
8814 * @return {Roo.Element} this
8816 addClassOnClick : function(className){
8818 this.on("mousedown", function(){
8819 Roo.fly(dom, '_internal').addClass(className);
8820 var d = Roo.get(document);
8821 var fn = function(){
8822 Roo.fly(dom, '_internal').removeClass(className);
8823 d.removeListener("mouseup", fn);
8825 d.on("mouseup", fn);
8831 * Stops the specified event from bubbling and optionally prevents the default action
8832 * @param {String} eventName
8833 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8834 * @return {Roo.Element} this
8836 swallowEvent : function(eventName, preventDefault){
8837 var fn = function(e){
8838 e.stopPropagation();
8843 if(eventName instanceof Array){
8844 for(var i = 0, len = eventName.length; i < len; i++){
8845 this.on(eventName[i], fn);
8849 this.on(eventName, fn);
8856 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8859 * Sizes this element to its parent element's dimensions performing
8860 * neccessary box adjustments.
8861 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8862 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8863 * @return {Roo.Element} this
8865 fitToParent : function(monitorResize, targetParent) {
8866 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8867 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8868 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8871 var p = Roo.get(targetParent || this.dom.parentNode);
8872 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8873 if (monitorResize === true) {
8874 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8875 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8881 * Gets the next sibling, skipping text nodes
8882 * @return {HTMLElement} The next sibling or null
8884 getNextSibling : function(){
8885 var n = this.dom.nextSibling;
8886 while(n && n.nodeType != 1){
8893 * Gets the previous sibling, skipping text nodes
8894 * @return {HTMLElement} The previous sibling or null
8896 getPrevSibling : function(){
8897 var n = this.dom.previousSibling;
8898 while(n && n.nodeType != 1){
8899 n = n.previousSibling;
8906 * Appends the passed element(s) to this element
8907 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8908 * @return {Roo.Element} this
8910 appendChild: function(el){
8917 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8918 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8919 * automatically generated with the specified attributes.
8920 * @param {HTMLElement} insertBefore (optional) a child element of this element
8921 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8922 * @return {Roo.Element} The new child element
8924 createChild: function(config, insertBefore, returnDom){
8925 config = config || {tag:'div'};
8927 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8929 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8933 * Appends this element to the passed element
8934 * @param {String/HTMLElement/Element} el The new parent element
8935 * @return {Roo.Element} this
8937 appendTo: function(el){
8938 el = Roo.getDom(el);
8939 el.appendChild(this.dom);
8944 * Inserts this element before the passed element in the DOM
8945 * @param {String/HTMLElement/Element} el The element to insert before
8946 * @return {Roo.Element} this
8948 insertBefore: function(el){
8949 el = Roo.getDom(el);
8950 el.parentNode.insertBefore(this.dom, el);
8955 * Inserts this element after the passed element in the DOM
8956 * @param {String/HTMLElement/Element} el The element to insert after
8957 * @return {Roo.Element} this
8959 insertAfter: function(el){
8960 el = Roo.getDom(el);
8961 el.parentNode.insertBefore(this.dom, el.nextSibling);
8966 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
8967 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8968 * @return {Roo.Element} The new child
8970 insertFirst: function(el, returnDom){
8972 if(typeof el == 'object' && !el.nodeType){ // dh config
8973 return this.createChild(el, this.dom.firstChild, returnDom);
8975 el = Roo.getDom(el);
8976 this.dom.insertBefore(el, this.dom.firstChild);
8977 return !returnDom ? Roo.get(el) : el;
8982 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
8983 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8984 * @param {String} where (optional) 'before' or 'after' defaults to before
8985 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8986 * @return {Roo.Element} the inserted Element
8988 insertSibling: function(el, where, returnDom){
8989 where = where ? where.toLowerCase() : 'before';
8991 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
8993 if(typeof el == 'object' && !el.nodeType){ // dh config
8994 if(where == 'after' && !this.dom.nextSibling){
8995 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
8997 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9001 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9002 where == 'before' ? this.dom : this.dom.nextSibling);
9011 * Creates and wraps this element with another element
9012 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9013 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9014 * @return {HTMLElement/Element} The newly created wrapper element
9016 wrap: function(config, returnDom){
9018 config = {tag: "div"};
9020 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9021 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9026 * Replaces the passed element with this element
9027 * @param {String/HTMLElement/Element} el The element to replace
9028 * @return {Roo.Element} this
9030 replace: function(el){
9032 this.insertBefore(el);
9038 * Inserts an html fragment into this element
9039 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9040 * @param {String} html The HTML fragment
9041 * @param {Boolean} returnEl True to return an Roo.Element
9042 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9044 insertHtml : function(where, html, returnEl){
9045 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9046 return returnEl ? Roo.get(el) : el;
9050 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9051 * @param {Object} o The object with the attributes
9052 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9053 * @return {Roo.Element} this
9055 set : function(o, useSet){
9057 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9059 if(attr == "style" || typeof o[attr] == "function") continue;
9061 el.className = o["cls"];
9063 if(useSet) el.setAttribute(attr, o[attr]);
9064 else el[attr] = o[attr];
9068 Roo.DomHelper.applyStyles(el, o.style);
9074 * Convenience method for constructing a KeyMap
9075 * @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:
9076 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9077 * @param {Function} fn The function to call
9078 * @param {Object} scope (optional) The scope of the function
9079 * @return {Roo.KeyMap} The KeyMap created
9081 addKeyListener : function(key, fn, scope){
9083 if(typeof key != "object" || key instanceof Array){
9099 return new Roo.KeyMap(this, config);
9103 * Creates a KeyMap for this element
9104 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9105 * @return {Roo.KeyMap} The KeyMap created
9107 addKeyMap : function(config){
9108 return new Roo.KeyMap(this, config);
9112 * Returns true if this element is scrollable.
9115 isScrollable : function(){
9117 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9121 * 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().
9122 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9123 * @param {Number} value The new scroll value
9124 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9125 * @return {Element} this
9128 scrollTo : function(side, value, animate){
9129 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9131 this.dom[prop] = value;
9133 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9134 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9140 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9141 * within this element's scrollable range.
9142 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9143 * @param {Number} distance How far to scroll the element in pixels
9144 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9145 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9146 * was scrolled as far as it could go.
9148 scroll : function(direction, distance, animate){
9149 if(!this.isScrollable()){
9153 var l = el.scrollLeft, t = el.scrollTop;
9154 var w = el.scrollWidth, h = el.scrollHeight;
9155 var cw = el.clientWidth, ch = el.clientHeight;
9156 direction = direction.toLowerCase();
9157 var scrolled = false;
9158 var a = this.preanim(arguments, 2);
9163 var v = Math.min(l + distance, w-cw);
9164 this.scrollTo("left", v, a);
9171 var v = Math.max(l - distance, 0);
9172 this.scrollTo("left", v, a);
9180 var v = Math.max(t - distance, 0);
9181 this.scrollTo("top", v, a);
9189 var v = Math.min(t + distance, h-ch);
9190 this.scrollTo("top", v, a);
9199 * Translates the passed page coordinates into left/top css values for this element
9200 * @param {Number/Array} x The page x or an array containing [x, y]
9201 * @param {Number} y The page y
9202 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9204 translatePoints : function(x, y){
9205 if(typeof x == 'object' || x instanceof Array){
9208 var p = this.getStyle('position');
9209 var o = this.getXY();
9211 var l = parseInt(this.getStyle('left'), 10);
9212 var t = parseInt(this.getStyle('top'), 10);
9215 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9218 t = (p == "relative") ? 0 : this.dom.offsetTop;
9221 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9225 * Returns the current scroll position of the element.
9226 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9228 getScroll : function(){
9229 var d = this.dom, doc = document;
9230 if(d == doc || d == doc.body){
9231 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9232 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9233 return {left: l, top: t};
9235 return {left: d.scrollLeft, top: d.scrollTop};
9240 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9241 * are convert to standard 6 digit hex color.
9242 * @param {String} attr The css attribute
9243 * @param {String} defaultValue The default value to use when a valid color isn't found
9244 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9247 getColor : function(attr, defaultValue, prefix){
9248 var v = this.getStyle(attr);
9249 if(!v || v == "transparent" || v == "inherit") {
9250 return defaultValue;
9252 var color = typeof prefix == "undefined" ? "#" : prefix;
9253 if(v.substr(0, 4) == "rgb("){
9254 var rvs = v.slice(4, v.length -1).split(",");
9255 for(var i = 0; i < 3; i++){
9256 var h = parseInt(rvs[i]).toString(16);
9263 if(v.substr(0, 1) == "#"){
9265 for(var i = 1; i < 4; i++){
9266 var c = v.charAt(i);
9269 }else if(v.length == 7){
9270 color += v.substr(1);
9274 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9278 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9279 * gradient background, rounded corners and a 4-way shadow.
9280 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9281 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9282 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9283 * @return {Roo.Element} this
9285 boxWrap : function(cls){
9286 cls = cls || 'x-box';
9287 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9288 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9293 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9294 * @param {String} namespace The namespace in which to look for the attribute
9295 * @param {String} name The attribute name
9296 * @return {String} The attribute value
9298 getAttributeNS : Roo.isIE ? function(ns, name){
9300 var type = typeof d[ns+":"+name];
9301 if(type != 'undefined' && type != 'unknown'){
9302 return d[ns+":"+name];
9305 } : function(ns, name){
9307 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9311 var ep = El.prototype;
9314 * Appends an event handler (Shorthand for addListener)
9315 * @param {String} eventName The type of event to append
9316 * @param {Function} fn The method the event invokes
9317 * @param {Object} scope (optional) The scope (this object) of the fn
9318 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9321 ep.on = ep.addListener;
9323 ep.mon = ep.addListener;
9326 * Removes an event handler from this element (shorthand for removeListener)
9327 * @param {String} eventName the type of event to remove
9328 * @param {Function} fn the method the event invokes
9329 * @return {Roo.Element} this
9332 ep.un = ep.removeListener;
9335 * true to automatically adjust width and height settings for box-model issues (default to true)
9337 ep.autoBoxAdjust = true;
9340 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9343 El.addUnits = function(v, defaultUnit){
9344 if(v === "" || v == "auto"){
9347 if(v === undefined){
9350 if(typeof v == "number" || !El.unitPattern.test(v)){
9351 return v + (defaultUnit || 'px');
9356 // special markup used throughout Roo when box wrapping elements
9357 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>';
9359 * Visibility mode constant - Use visibility to hide element
9365 * Visibility mode constant - Use display to hide element
9371 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9372 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9373 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9385 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9386 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9387 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9388 * @return {Element} The Element object
9391 El.get = function(el){
9393 if(!el){ return null; }
9394 if(typeof el == "string"){ // element id
9395 if(!(elm = document.getElementById(el))){
9398 if(ex = El.cache[el]){
9401 ex = El.cache[el] = new El(elm);
9404 }else if(el.tagName){ // dom element
9408 if(ex = El.cache[id]){
9411 ex = El.cache[id] = new El(el);
9414 }else if(el instanceof El){
9416 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9417 // catch case where it hasn't been appended
9418 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9421 }else if(el.isComposite){
9423 }else if(el instanceof Array){
9424 return El.select(el);
9425 }else if(el == document){
9426 // create a bogus element object representing the document object
9428 var f = function(){};
9429 f.prototype = El.prototype;
9431 docEl.dom = document;
9439 El.uncache = function(el){
9440 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9442 delete El.cache[a[i].id || a[i]];
9448 // Garbage collection - uncache elements/purge listeners on orphaned elements
9449 // so we don't hold a reference and cause the browser to retain them
9450 El.garbageCollect = function(){
9451 if(!Roo.enableGarbageCollector){
9452 clearInterval(El.collectorThread);
9455 for(var eid in El.cache){
9456 var el = El.cache[eid], d = el.dom;
9457 // -------------------------------------------------------
9458 // Determining what is garbage:
9459 // -------------------------------------------------------
9461 // dom node is null, definitely garbage
9462 // -------------------------------------------------------
9464 // no parentNode == direct orphan, definitely garbage
9465 // -------------------------------------------------------
9466 // !d.offsetParent && !document.getElementById(eid)
9467 // display none elements have no offsetParent so we will
9468 // also try to look it up by it's id. However, check
9469 // offsetParent first so we don't do unneeded lookups.
9470 // This enables collection of elements that are not orphans
9471 // directly, but somewhere up the line they have an orphan
9473 // -------------------------------------------------------
9474 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9475 delete El.cache[eid];
9476 if(d && Roo.enableListenerCollection){
9482 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9486 El.Flyweight = function(dom){
9489 El.Flyweight.prototype = El.prototype;
9491 El._flyweights = {};
9493 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9494 * the dom node can be overwritten by other code.
9495 * @param {String/HTMLElement} el The dom node or id
9496 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9497 * prevent conflicts (e.g. internally Roo uses "_internal")
9499 * @return {Element} The shared Element object
9501 El.fly = function(el, named){
9502 named = named || '_global';
9503 el = Roo.getDom(el);
9507 if(!El._flyweights[named]){
9508 El._flyweights[named] = new El.Flyweight();
9510 El._flyweights[named].dom = el;
9511 return El._flyweights[named];
9515 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9516 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9517 * Shorthand of {@link Roo.Element#get}
9518 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9519 * @return {Element} The Element object
9525 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9526 * the dom node can be overwritten by other code.
9527 * Shorthand of {@link Roo.Element#fly}
9528 * @param {String/HTMLElement} el The dom node or id
9529 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9530 * prevent conflicts (e.g. internally Roo uses "_internal")
9532 * @return {Element} The shared Element object
9538 // speedy lookup for elements never to box adjust
9539 var noBoxAdjust = Roo.isStrict ? {
9542 input:1, select:1, textarea:1
9544 if(Roo.isIE || Roo.isGecko){
9545 noBoxAdjust['button'] = 1;
9549 Roo.EventManager.on(window, 'unload', function(){
9551 delete El._flyweights;
9559 Roo.Element.selectorFunction = Roo.DomQuery.select;
9562 Roo.Element.select = function(selector, unique, root){
9564 if(typeof selector == "string"){
9565 els = Roo.Element.selectorFunction(selector, root);
9566 }else if(selector.length !== undefined){
9569 throw "Invalid selector";
9571 if(unique === true){
9572 return new Roo.CompositeElement(els);
9574 return new Roo.CompositeElementLite(els);
9578 * Selects elements based on the passed CSS selector to enable working on them as 1.
9579 * @param {String/Array} selector The CSS selector or an array of elements
9580 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9581 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9582 * @return {CompositeElementLite/CompositeElement}
9586 Roo.select = Roo.Element.select;
9603 * Ext JS Library 1.1.1
9604 * Copyright(c) 2006-2007, Ext JS, LLC.
9606 * Originally Released Under LGPL - original licence link has changed is not relivant.
9609 * <script type="text/javascript">
9614 //Notifies Element that fx methods are available
9615 Roo.enableFx = true;
9619 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9620 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9621 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9622 * Element effects to work.</p><br/>
9624 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9625 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9626 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9627 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9628 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9629 * expected results and should be done with care.</p><br/>
9631 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9632 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9635 ----- -----------------------------
9636 tl The top left corner
9637 t The center of the top edge
9638 tr The top right corner
9639 l The center of the left edge
9640 r The center of the right edge
9641 bl The bottom left corner
9642 b The center of the bottom edge
9643 br The bottom right corner
9645 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9646 * below are common options that can be passed to any Fx method.</b>
9647 * @cfg {Function} callback A function called when the effect is finished
9648 * @cfg {Object} scope The scope of the effect function
9649 * @cfg {String} easing A valid Easing value for the effect
9650 * @cfg {String} afterCls A css class to apply after the effect
9651 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9652 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9653 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9654 * effects that end with the element being visually hidden, ignored otherwise)
9655 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9656 * a function which returns such a specification that will be applied to the Element after the effect finishes
9657 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9658 * @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
9659 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9663 * Slides the element into view. An anchor point can be optionally passed to set the point of
9664 * origin for the slide effect. This function automatically handles wrapping the element with
9665 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9668 // default: slide the element in from the top
9671 // custom: slide the element in from the right with a 2-second duration
9672 el.slideIn('r', { duration: 2 });
9674 // common config options shown with default values
9680 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9681 * @param {Object} options (optional) Object literal with any of the Fx config options
9682 * @return {Roo.Element} The Element
9684 slideIn : function(anchor, o){
9685 var el = this.getFxEl();
9688 el.queueFx(o, function(){
9690 anchor = anchor || "t";
9692 // fix display to visibility
9695 // restore values after effect
9696 var r = this.getFxRestore();
9697 var b = this.getBox();
9698 // fixed size for slide
9702 var wrap = this.fxWrap(r.pos, o, "hidden");
9704 var st = this.dom.style;
9705 st.visibility = "visible";
9706 st.position = "absolute";
9708 // clear out temp styles after slide and unwrap
9709 var after = function(){
9710 el.fxUnwrap(wrap, r.pos, o);
9712 st.height = r.height;
9715 // time to calc the positions
9716 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9718 switch(anchor.toLowerCase()){
9720 wrap.setSize(b.width, 0);
9721 st.left = st.bottom = "0";
9725 wrap.setSize(0, b.height);
9726 st.right = st.top = "0";
9730 wrap.setSize(0, b.height);
9732 st.left = st.top = "0";
9733 a = {width: bw, points: pt};
9736 wrap.setSize(b.width, 0);
9737 wrap.setY(b.bottom);
9738 st.left = st.top = "0";
9739 a = {height: bh, points: pt};
9743 st.right = st.bottom = "0";
9744 a = {width: bw, height: bh};
9748 wrap.setY(b.y+b.height);
9749 st.right = st.top = "0";
9750 a = {width: bw, height: bh, points: pt};
9754 wrap.setXY([b.right, b.bottom]);
9755 st.left = st.top = "0";
9756 a = {width: bw, height: bh, points: pt};
9760 wrap.setX(b.x+b.width);
9761 st.left = st.bottom = "0";
9762 a = {width: bw, height: bh, points: pt};
9765 this.dom.style.visibility = "visible";
9768 arguments.callee.anim = wrap.fxanim(a,
9778 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9779 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9780 * 'hidden') but block elements will still take up space in the document. The element must be removed
9781 * from the DOM using the 'remove' config option if desired. This function automatically handles
9782 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9785 // default: slide the element out to the top
9788 // custom: slide the element out to the right with a 2-second duration
9789 el.slideOut('r', { duration: 2 });
9791 // common config options shown with default values
9799 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9800 * @param {Object} options (optional) Object literal with any of the Fx config options
9801 * @return {Roo.Element} The Element
9803 slideOut : function(anchor, o){
9804 var el = this.getFxEl();
9807 el.queueFx(o, function(){
9809 anchor = anchor || "t";
9811 // restore values after effect
9812 var r = this.getFxRestore();
9814 var b = this.getBox();
9815 // fixed size for slide
9819 var wrap = this.fxWrap(r.pos, o, "visible");
9821 var st = this.dom.style;
9822 st.visibility = "visible";
9823 st.position = "absolute";
9827 var after = function(){
9829 el.setDisplayed(false);
9834 el.fxUnwrap(wrap, r.pos, o);
9837 st.height = r.height;
9842 var a, zero = {to: 0};
9843 switch(anchor.toLowerCase()){
9845 st.left = st.bottom = "0";
9849 st.right = st.top = "0";
9853 st.left = st.top = "0";
9854 a = {width: zero, points: {to:[b.right, b.y]}};
9857 st.left = st.top = "0";
9858 a = {height: zero, points: {to:[b.x, b.bottom]}};
9861 st.right = st.bottom = "0";
9862 a = {width: zero, height: zero};
9865 st.right = st.top = "0";
9866 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9869 st.left = st.top = "0";
9870 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9873 st.left = st.bottom = "0";
9874 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9878 arguments.callee.anim = wrap.fxanim(a,
9888 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
9889 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
9890 * The element must be removed from the DOM using the 'remove' config option if desired.
9896 // common config options shown with default values
9904 * @param {Object} options (optional) Object literal with any of the Fx config options
9905 * @return {Roo.Element} The Element
9908 var el = this.getFxEl();
9911 el.queueFx(o, function(){
9912 this.clearOpacity();
9915 // restore values after effect
9916 var r = this.getFxRestore();
9917 var st = this.dom.style;
9919 var after = function(){
9921 el.setDisplayed(false);
9928 el.setPositioning(r.pos);
9930 st.height = r.height;
9935 var width = this.getWidth();
9936 var height = this.getHeight();
9938 arguments.callee.anim = this.fxanim({
9939 width : {to: this.adjustWidth(width * 2)},
9940 height : {to: this.adjustHeight(height * 2)},
9941 points : {by: [-(width * .5), -(height * .5)]},
9943 fontSize: {to:200, unit: "%"}
9954 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
9955 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
9956 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
9962 // all config options shown with default values
9970 * @param {Object} options (optional) Object literal with any of the Fx config options
9971 * @return {Roo.Element} The Element
9973 switchOff : function(o){
9974 var el = this.getFxEl();
9977 el.queueFx(o, function(){
9978 this.clearOpacity();
9981 // restore values after effect
9982 var r = this.getFxRestore();
9983 var st = this.dom.style;
9985 var after = function(){
9987 el.setDisplayed(false);
9993 el.setPositioning(r.pos);
9995 st.height = r.height;
10000 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10001 this.clearOpacity();
10005 points:{by:[0, this.getHeight() * .5]}
10006 }, o, 'motion', 0.3, 'easeIn', after);
10007 }).defer(100, this);
10014 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10015 * changed using the "attr" config option) and then fading back to the original color. If no original
10016 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10019 // default: highlight background to yellow
10022 // custom: highlight foreground text to blue for 2 seconds
10023 el.highlight("0000ff", { attr: 'color', duration: 2 });
10025 // common config options shown with default values
10026 el.highlight("ffff9c", {
10027 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10028 endColor: (current color) or "ffffff",
10033 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10034 * @param {Object} options (optional) Object literal with any of the Fx config options
10035 * @return {Roo.Element} The Element
10037 highlight : function(color, o){
10038 var el = this.getFxEl();
10041 el.queueFx(o, function(){
10042 color = color || "ffff9c";
10043 attr = o.attr || "backgroundColor";
10045 this.clearOpacity();
10048 var origColor = this.getColor(attr);
10049 var restoreColor = this.dom.style[attr];
10050 endColor = (o.endColor || origColor) || "ffffff";
10052 var after = function(){
10053 el.dom.style[attr] = restoreColor;
10058 a[attr] = {from: color, to: endColor};
10059 arguments.callee.anim = this.fxanim(a,
10069 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10072 // default: a single light blue ripple
10075 // custom: 3 red ripples lasting 3 seconds total
10076 el.frame("ff0000", 3, { duration: 3 });
10078 // common config options shown with default values
10079 el.frame("C3DAF9", 1, {
10080 duration: 1 //duration of entire animation (not each individual ripple)
10081 // Note: Easing is not configurable and will be ignored if included
10084 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10085 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10086 * @param {Object} options (optional) Object literal with any of the Fx config options
10087 * @return {Roo.Element} The Element
10089 frame : function(color, count, o){
10090 var el = this.getFxEl();
10093 el.queueFx(o, function(){
10094 color = color || "#C3DAF9";
10095 if(color.length == 6){
10096 color = "#" + color;
10098 count = count || 1;
10099 duration = o.duration || 1;
10102 var b = this.getBox();
10103 var animFn = function(){
10104 var proxy = this.createProxy({
10107 visbility:"hidden",
10108 position:"absolute",
10109 "z-index":"35000", // yee haw
10110 border:"0px solid " + color
10113 var scale = Roo.isBorderBox ? 2 : 1;
10115 top:{from:b.y, to:b.y - 20},
10116 left:{from:b.x, to:b.x - 20},
10117 borderWidth:{from:0, to:10},
10118 opacity:{from:1, to:0},
10119 height:{from:b.height, to:(b.height + (20*scale))},
10120 width:{from:b.width, to:(b.width + (20*scale))}
10121 }, duration, function(){
10125 animFn.defer((duration/2)*1000, this);
10136 * Creates a pause before any subsequent queued effects begin. If there are
10137 * no effects queued after the pause it will have no effect.
10142 * @param {Number} seconds The length of time to pause (in seconds)
10143 * @return {Roo.Element} The Element
10145 pause : function(seconds){
10146 var el = this.getFxEl();
10149 el.queueFx(o, function(){
10150 setTimeout(function(){
10152 }, seconds * 1000);
10158 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10159 * using the "endOpacity" config option.
10162 // default: fade in from opacity 0 to 100%
10165 // custom: fade in from opacity 0 to 75% over 2 seconds
10166 el.fadeIn({ endOpacity: .75, duration: 2});
10168 // common config options shown with default values
10170 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10175 * @param {Object} options (optional) Object literal with any of the Fx config options
10176 * @return {Roo.Element} The Element
10178 fadeIn : function(o){
10179 var el = this.getFxEl();
10181 el.queueFx(o, function(){
10182 this.setOpacity(0);
10184 this.dom.style.visibility = 'visible';
10185 var to = o.endOpacity || 1;
10186 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10187 o, null, .5, "easeOut", function(){
10189 this.clearOpacity();
10198 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10199 * using the "endOpacity" config option.
10202 // default: fade out from the element's current opacity to 0
10205 // custom: fade out from the element's current opacity to 25% over 2 seconds
10206 el.fadeOut({ endOpacity: .25, duration: 2});
10208 // common config options shown with default values
10210 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10217 * @param {Object} options (optional) Object literal with any of the Fx config options
10218 * @return {Roo.Element} The Element
10220 fadeOut : function(o){
10221 var el = this.getFxEl();
10223 el.queueFx(o, function(){
10224 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10225 o, null, .5, "easeOut", function(){
10226 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10227 this.dom.style.display = "none";
10229 this.dom.style.visibility = "hidden";
10231 this.clearOpacity();
10239 * Animates the transition of an element's dimensions from a starting height/width
10240 * to an ending height/width.
10243 // change height and width to 100x100 pixels
10244 el.scale(100, 100);
10246 // common config options shown with default values. The height and width will default to
10247 // the element's existing values if passed as null.
10250 [element's height], {
10255 * @param {Number} width The new width (pass undefined to keep the original width)
10256 * @param {Number} height The new height (pass undefined to keep the original height)
10257 * @param {Object} options (optional) Object literal with any of the Fx config options
10258 * @return {Roo.Element} The Element
10260 scale : function(w, h, o){
10261 this.shift(Roo.apply({}, o, {
10269 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10270 * Any of these properties not specified in the config object will not be changed. This effect
10271 * requires that at least one new dimension, position or opacity setting must be passed in on
10272 * the config object in order for the function to have any effect.
10275 // slide the element horizontally to x position 200 while changing the height and opacity
10276 el.shift({ x: 200, height: 50, opacity: .8 });
10278 // common config options shown with default values.
10280 width: [element's width],
10281 height: [element's height],
10282 x: [element's x position],
10283 y: [element's y position],
10284 opacity: [element's opacity],
10289 * @param {Object} options Object literal with any of the Fx config options
10290 * @return {Roo.Element} The Element
10292 shift : function(o){
10293 var el = this.getFxEl();
10295 el.queueFx(o, function(){
10296 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10297 if(w !== undefined){
10298 a.width = {to: this.adjustWidth(w)};
10300 if(h !== undefined){
10301 a.height = {to: this.adjustHeight(h)};
10303 if(x !== undefined || y !== undefined){
10305 x !== undefined ? x : this.getX(),
10306 y !== undefined ? y : this.getY()
10309 if(op !== undefined){
10310 a.opacity = {to: op};
10312 if(o.xy !== undefined){
10313 a.points = {to: o.xy};
10315 arguments.callee.anim = this.fxanim(a,
10316 o, 'motion', .35, "easeOut", function(){
10324 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10325 * ending point of the effect.
10328 // default: slide the element downward while fading out
10331 // custom: slide the element out to the right with a 2-second duration
10332 el.ghost('r', { duration: 2 });
10334 // common config options shown with default values
10342 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10343 * @param {Object} options (optional) Object literal with any of the Fx config options
10344 * @return {Roo.Element} The Element
10346 ghost : function(anchor, o){
10347 var el = this.getFxEl();
10350 el.queueFx(o, function(){
10351 anchor = anchor || "b";
10353 // restore values after effect
10354 var r = this.getFxRestore();
10355 var w = this.getWidth(),
10356 h = this.getHeight();
10358 var st = this.dom.style;
10360 var after = function(){
10362 el.setDisplayed(false);
10368 el.setPositioning(r.pos);
10369 st.width = r.width;
10370 st.height = r.height;
10375 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10376 switch(anchor.toLowerCase()){
10403 arguments.callee.anim = this.fxanim(a,
10413 * Ensures that all effects queued after syncFx is called on the element are
10414 * run concurrently. This is the opposite of {@link #sequenceFx}.
10415 * @return {Roo.Element} The Element
10417 syncFx : function(){
10418 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10427 * Ensures that all effects queued after sequenceFx is called on the element are
10428 * run in sequence. This is the opposite of {@link #syncFx}.
10429 * @return {Roo.Element} The Element
10431 sequenceFx : function(){
10432 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10434 concurrent : false,
10441 nextFx : function(){
10442 var ef = this.fxQueue[0];
10449 * Returns true if the element has any effects actively running or queued, else returns false.
10450 * @return {Boolean} True if element has active effects, else false
10452 hasActiveFx : function(){
10453 return this.fxQueue && this.fxQueue[0];
10457 * Stops any running effects and clears the element's internal effects queue if it contains
10458 * any additional effects that haven't started yet.
10459 * @return {Roo.Element} The Element
10461 stopFx : function(){
10462 if(this.hasActiveFx()){
10463 var cur = this.fxQueue[0];
10464 if(cur && cur.anim && cur.anim.isAnimated()){
10465 this.fxQueue = [cur]; // clear out others
10466 cur.anim.stop(true);
10473 beforeFx : function(o){
10474 if(this.hasActiveFx() && !o.concurrent){
10485 * Returns true if the element is currently blocking so that no other effect can be queued
10486 * until this effect is finished, else returns false if blocking is not set. This is commonly
10487 * used to ensure that an effect initiated by a user action runs to completion prior to the
10488 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10489 * @return {Boolean} True if blocking, else false
10491 hasFxBlock : function(){
10492 var q = this.fxQueue;
10493 return q && q[0] && q[0].block;
10497 queueFx : function(o, fn){
10501 if(!this.hasFxBlock()){
10502 Roo.applyIf(o, this.fxDefaults);
10504 var run = this.beforeFx(o);
10505 fn.block = o.block;
10506 this.fxQueue.push(fn);
10518 fxWrap : function(pos, o, vis){
10520 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10523 wrapXY = this.getXY();
10525 var div = document.createElement("div");
10526 div.style.visibility = vis;
10527 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10528 wrap.setPositioning(pos);
10529 if(wrap.getStyle("position") == "static"){
10530 wrap.position("relative");
10532 this.clearPositioning('auto');
10534 wrap.dom.appendChild(this.dom);
10536 wrap.setXY(wrapXY);
10543 fxUnwrap : function(wrap, pos, o){
10544 this.clearPositioning();
10545 this.setPositioning(pos);
10547 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10553 getFxRestore : function(){
10554 var st = this.dom.style;
10555 return {pos: this.getPositioning(), width: st.width, height : st.height};
10559 afterFx : function(o){
10561 this.applyStyles(o.afterStyle);
10564 this.addClass(o.afterCls);
10566 if(o.remove === true){
10569 Roo.callback(o.callback, o.scope, [this]);
10571 this.fxQueue.shift();
10577 getFxEl : function(){ // support for composite element fx
10578 return Roo.get(this.dom);
10582 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10583 animType = animType || 'run';
10585 var anim = Roo.lib.Anim[animType](
10587 (opt.duration || defaultDur) || .35,
10588 (opt.easing || defaultEase) || 'easeOut',
10590 Roo.callback(cb, this);
10599 // backwords compat
10600 Roo.Fx.resize = Roo.Fx.scale;
10602 //When included, Roo.Fx is automatically applied to Element so that all basic
10603 //effects are available directly via the Element API
10604 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10606 * Ext JS Library 1.1.1
10607 * Copyright(c) 2006-2007, Ext JS, LLC.
10609 * Originally Released Under LGPL - original licence link has changed is not relivant.
10612 * <script type="text/javascript">
10617 * @class Roo.CompositeElement
10618 * Standard composite class. Creates a Roo.Element for every element in the collection.
10620 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10621 * actions will be performed on all the elements in this collection.</b>
10623 * All methods return <i>this</i> and can be chained.
10625 var els = Roo.select("#some-el div.some-class", true);
10626 // or select directly from an existing element
10627 var el = Roo.get('some-el');
10628 el.select('div.some-class', true);
10630 els.setWidth(100); // all elements become 100 width
10631 els.hide(true); // all elements fade out and hide
10633 els.setWidth(100).hide(true);
10636 Roo.CompositeElement = function(els){
10637 this.elements = [];
10638 this.addElements(els);
10640 Roo.CompositeElement.prototype = {
10642 addElements : function(els){
10643 if(!els) return this;
10644 if(typeof els == "string"){
10645 els = Roo.Element.selectorFunction(els);
10647 var yels = this.elements;
10648 var index = yels.length-1;
10649 for(var i = 0, len = els.length; i < len; i++) {
10650 yels[++index] = Roo.get(els[i]);
10656 * Clears this composite and adds the elements returned by the passed selector.
10657 * @param {String/Array} els A string CSS selector, an array of elements or an element
10658 * @return {CompositeElement} this
10660 fill : function(els){
10661 this.elements = [];
10667 * Filters this composite to only elements that match the passed selector.
10668 * @param {String} selector A string CSS selector
10669 * @return {CompositeElement} this
10671 filter : function(selector){
10673 this.each(function(el){
10674 if(el.is(selector)){
10675 els[els.length] = el.dom;
10682 invoke : function(fn, args){
10683 var els = this.elements;
10684 for(var i = 0, len = els.length; i < len; i++) {
10685 Roo.Element.prototype[fn].apply(els[i], args);
10690 * Adds elements to this composite.
10691 * @param {String/Array} els A string CSS selector, an array of elements or an element
10692 * @return {CompositeElement} this
10694 add : function(els){
10695 if(typeof els == "string"){
10696 this.addElements(Roo.Element.selectorFunction(els));
10697 }else if(els.length !== undefined){
10698 this.addElements(els);
10700 this.addElements([els]);
10705 * Calls the passed function passing (el, this, index) for each element in this composite.
10706 * @param {Function} fn The function to call
10707 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10708 * @return {CompositeElement} this
10710 each : function(fn, scope){
10711 var els = this.elements;
10712 for(var i = 0, len = els.length; i < len; i++){
10713 if(fn.call(scope || els[i], els[i], this, i) === false) {
10721 * Returns the Element object at the specified index
10722 * @param {Number} index
10723 * @return {Roo.Element}
10725 item : function(index){
10726 return this.elements[index] || null;
10730 * Returns the first Element
10731 * @return {Roo.Element}
10733 first : function(){
10734 return this.item(0);
10738 * Returns the last Element
10739 * @return {Roo.Element}
10742 return this.item(this.elements.length-1);
10746 * Returns the number of elements in this composite
10749 getCount : function(){
10750 return this.elements.length;
10754 * Returns true if this composite contains the passed element
10757 contains : function(el){
10758 return this.indexOf(el) !== -1;
10762 * Returns true if this composite contains the passed element
10765 indexOf : function(el){
10766 return this.elements.indexOf(Roo.get(el));
10771 * Removes the specified element(s).
10772 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10773 * or an array of any of those.
10774 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10775 * @return {CompositeElement} this
10777 removeElement : function(el, removeDom){
10778 if(el instanceof Array){
10779 for(var i = 0, len = el.length; i < len; i++){
10780 this.removeElement(el[i]);
10784 var index = typeof el == 'number' ? el : this.indexOf(el);
10787 var d = this.elements[index];
10791 d.parentNode.removeChild(d);
10794 this.elements.splice(index, 1);
10800 * Replaces the specified element with the passed element.
10801 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10803 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10804 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10805 * @return {CompositeElement} this
10807 replaceElement : function(el, replacement, domReplace){
10808 var index = typeof el == 'number' ? el : this.indexOf(el);
10811 this.elements[index].replaceWith(replacement);
10813 this.elements.splice(index, 1, Roo.get(replacement))
10820 * Removes all elements.
10822 clear : function(){
10823 this.elements = [];
10827 Roo.CompositeElement.createCall = function(proto, fnName){
10828 if(!proto[fnName]){
10829 proto[fnName] = function(){
10830 return this.invoke(fnName, arguments);
10834 for(var fnName in Roo.Element.prototype){
10835 if(typeof Roo.Element.prototype[fnName] == "function"){
10836 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10842 * Ext JS Library 1.1.1
10843 * Copyright(c) 2006-2007, Ext JS, LLC.
10845 * Originally Released Under LGPL - original licence link has changed is not relivant.
10848 * <script type="text/javascript">
10852 * @class Roo.CompositeElementLite
10853 * @extends Roo.CompositeElement
10854 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10856 var els = Roo.select("#some-el div.some-class");
10857 // or select directly from an existing element
10858 var el = Roo.get('some-el');
10859 el.select('div.some-class');
10861 els.setWidth(100); // all elements become 100 width
10862 els.hide(true); // all elements fade out and hide
10864 els.setWidth(100).hide(true);
10865 </code></pre><br><br>
10866 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10867 * actions will be performed on all the elements in this collection.</b>
10869 Roo.CompositeElementLite = function(els){
10870 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10871 this.el = new Roo.Element.Flyweight();
10873 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10874 addElements : function(els){
10876 if(els instanceof Array){
10877 this.elements = this.elements.concat(els);
10879 var yels = this.elements;
10880 var index = yels.length-1;
10881 for(var i = 0, len = els.length; i < len; i++) {
10882 yels[++index] = els[i];
10888 invoke : function(fn, args){
10889 var els = this.elements;
10891 for(var i = 0, len = els.length; i < len; i++) {
10893 Roo.Element.prototype[fn].apply(el, args);
10898 * Returns a flyweight Element of the dom element object at the specified index
10899 * @param {Number} index
10900 * @return {Roo.Element}
10902 item : function(index){
10903 if(!this.elements[index]){
10906 this.el.dom = this.elements[index];
10910 // fixes scope with flyweight
10911 addListener : function(eventName, handler, scope, opt){
10912 var els = this.elements;
10913 for(var i = 0, len = els.length; i < len; i++) {
10914 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
10920 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
10921 * passed is the flyweight (shared) Roo.Element instance, so if you require a
10922 * a reference to the dom node, use el.dom.</b>
10923 * @param {Function} fn The function to call
10924 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10925 * @return {CompositeElement} this
10927 each : function(fn, scope){
10928 var els = this.elements;
10930 for(var i = 0, len = els.length; i < len; i++){
10932 if(fn.call(scope || el, el, this, i) === false){
10939 indexOf : function(el){
10940 return this.elements.indexOf(Roo.getDom(el));
10943 replaceElement : function(el, replacement, domReplace){
10944 var index = typeof el == 'number' ? el : this.indexOf(el);
10946 replacement = Roo.getDom(replacement);
10948 var d = this.elements[index];
10949 d.parentNode.insertBefore(replacement, d);
10950 d.parentNode.removeChild(d);
10952 this.elements.splice(index, 1, replacement);
10957 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
10961 * Ext JS Library 1.1.1
10962 * Copyright(c) 2006-2007, Ext JS, LLC.
10964 * Originally Released Under LGPL - original licence link has changed is not relivant.
10967 * <script type="text/javascript">
10973 * @class Roo.data.Connection
10974 * @extends Roo.util.Observable
10975 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
10976 * either to a configured URL, or to a URL specified at request time.<br><br>
10978 * Requests made by this class are asynchronous, and will return immediately. No data from
10979 * the server will be available to the statement immediately following the {@link #request} call.
10980 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
10982 * Note: If you are doing a file upload, you will not get a normal response object sent back to
10983 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
10984 * The response object is created using the innerHTML of the IFRAME's document as the responseText
10985 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
10986 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
10987 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
10988 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
10989 * standard DOM methods.
10991 * @param {Object} config a configuration object.
10993 Roo.data.Connection = function(config){
10994 Roo.apply(this, config);
10997 * @event beforerequest
10998 * Fires before a network request is made to retrieve a data object.
10999 * @param {Connection} conn This Connection object.
11000 * @param {Object} options The options config object passed to the {@link #request} method.
11002 "beforerequest" : true,
11004 * @event requestcomplete
11005 * Fires if the request was successfully completed.
11006 * @param {Connection} conn This Connection object.
11007 * @param {Object} response The XHR object containing the response data.
11008 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11009 * @param {Object} options The options config object passed to the {@link #request} method.
11011 "requestcomplete" : true,
11013 * @event requestexception
11014 * Fires if an error HTTP status was returned from the server.
11015 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11016 * @param {Connection} conn This Connection object.
11017 * @param {Object} response The XHR object containing the response data.
11018 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11019 * @param {Object} options The options config object passed to the {@link #request} method.
11021 "requestexception" : true
11023 Roo.data.Connection.superclass.constructor.call(this);
11026 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11028 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11031 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11032 * extra parameters to each request made by this object. (defaults to undefined)
11035 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11036 * to each request made by this object. (defaults to undefined)
11039 * @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)
11042 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11046 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11052 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11055 disableCaching: true,
11058 * Sends an HTTP request to a remote server.
11059 * @param {Object} options An object which may contain the following properties:<ul>
11060 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11061 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11062 * request, a url encoded string or a function to call to get either.</li>
11063 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11064 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11065 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11066 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11067 * <li>options {Object} The parameter to the request call.</li>
11068 * <li>success {Boolean} True if the request succeeded.</li>
11069 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11071 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11072 * The callback is passed the following parameters:<ul>
11073 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11074 * <li>options {Object} The parameter to the request call.</li>
11076 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11077 * The callback is passed the following parameters:<ul>
11078 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11079 * <li>options {Object} The parameter to the request call.</li>
11081 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11082 * for the callback function. Defaults to the browser window.</li>
11083 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11084 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11085 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11086 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11087 * params for the post data. Any params will be appended to the URL.</li>
11088 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11090 * @return {Number} transactionId
11092 request : function(o){
11093 if(this.fireEvent("beforerequest", this, o) !== false){
11096 if(typeof p == "function"){
11097 p = p.call(o.scope||window, o);
11099 if(typeof p == "object"){
11100 p = Roo.urlEncode(o.params);
11102 if(this.extraParams){
11103 var extras = Roo.urlEncode(this.extraParams);
11104 p = p ? (p + '&' + extras) : extras;
11107 var url = o.url || this.url;
11108 if(typeof url == 'function'){
11109 url = url.call(o.scope||window, o);
11113 var form = Roo.getDom(o.form);
11114 url = url || form.action;
11116 var enctype = form.getAttribute("enctype");
11117 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11118 return this.doFormUpload(o, p, url);
11120 var f = Roo.lib.Ajax.serializeForm(form);
11121 p = p ? (p + '&' + f) : f;
11124 var hs = o.headers;
11125 if(this.defaultHeaders){
11126 hs = Roo.apply(hs || {}, this.defaultHeaders);
11133 success: this.handleResponse,
11134 failure: this.handleFailure,
11136 argument: {options: o},
11137 timeout : this.timeout
11140 var method = o.method||this.method||(p ? "POST" : "GET");
11142 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11143 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11146 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11150 }else if(this.autoAbort !== false){
11154 if((method == 'GET' && p) || o.xmlData){
11155 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11158 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11159 return this.transId;
11161 Roo.callback(o.callback, o.scope, [o, null, null]);
11167 * Determine whether this object has a request outstanding.
11168 * @param {Number} transactionId (Optional) defaults to the last transaction
11169 * @return {Boolean} True if there is an outstanding request.
11171 isLoading : function(transId){
11173 return Roo.lib.Ajax.isCallInProgress(transId);
11175 return this.transId ? true : false;
11180 * Aborts any outstanding request.
11181 * @param {Number} transactionId (Optional) defaults to the last transaction
11183 abort : function(transId){
11184 if(transId || this.isLoading()){
11185 Roo.lib.Ajax.abort(transId || this.transId);
11190 handleResponse : function(response){
11191 this.transId = false;
11192 var options = response.argument.options;
11193 response.argument = options ? options.argument : null;
11194 this.fireEvent("requestcomplete", this, response, options);
11195 Roo.callback(options.success, options.scope, [response, options]);
11196 Roo.callback(options.callback, options.scope, [options, true, response]);
11200 handleFailure : function(response, e){
11201 this.transId = false;
11202 var options = response.argument.options;
11203 response.argument = options ? options.argument : null;
11204 this.fireEvent("requestexception", this, response, options, e);
11205 Roo.callback(options.failure, options.scope, [response, options]);
11206 Roo.callback(options.callback, options.scope, [options, false, response]);
11210 doFormUpload : function(o, ps, url){
11212 var frame = document.createElement('iframe');
11215 frame.className = 'x-hidden';
11217 frame.src = Roo.SSL_SECURE_URL;
11219 document.body.appendChild(frame);
11222 document.frames[id].name = id;
11225 var form = Roo.getDom(o.form);
11227 form.method = 'POST';
11228 form.enctype = form.encoding = 'multipart/form-data';
11234 if(ps){ // add dynamic params
11236 ps = Roo.urlDecode(ps, false);
11238 if(ps.hasOwnProperty(k)){
11239 hd = document.createElement('input');
11240 hd.type = 'hidden';
11243 form.appendChild(hd);
11250 var r = { // bogus response object
11255 r.argument = o ? o.argument : null;
11260 doc = frame.contentWindow.document;
11262 doc = (frame.contentDocument || window.frames[id].document);
11264 if(doc && doc.body){
11265 r.responseText = doc.body.innerHTML;
11267 if(doc && doc.XMLDocument){
11268 r.responseXML = doc.XMLDocument;
11270 r.responseXML = doc;
11277 Roo.EventManager.removeListener(frame, 'load', cb, this);
11279 this.fireEvent("requestcomplete", this, r, o);
11280 Roo.callback(o.success, o.scope, [r, o]);
11281 Roo.callback(o.callback, o.scope, [o, true, r]);
11283 setTimeout(function(){document.body.removeChild(frame);}, 100);
11286 Roo.EventManager.on(frame, 'load', cb, this);
11289 if(hiddens){ // remove dynamic params
11290 for(var i = 0, len = hiddens.length; i < len; i++){
11291 form.removeChild(hiddens[i]);
11299 * @extends Roo.data.Connection
11300 * Global Ajax request class.
11304 Roo.Ajax = new Roo.data.Connection({
11307 * @cfg {String} url @hide
11310 * @cfg {Object} extraParams @hide
11313 * @cfg {Object} defaultHeaders @hide
11316 * @cfg {String} method (Optional) @hide
11319 * @cfg {Number} timeout (Optional) @hide
11322 * @cfg {Boolean} autoAbort (Optional) @hide
11326 * @cfg {Boolean} disableCaching (Optional) @hide
11330 * @property disableCaching
11331 * True to add a unique cache-buster param to GET requests. (defaults to true)
11336 * The default URL to be used for requests to the server. (defaults to undefined)
11340 * @property extraParams
11341 * An object containing properties which are used as
11342 * extra parameters to each request made by this object. (defaults to undefined)
11346 * @property defaultHeaders
11347 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11352 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11356 * @property timeout
11357 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11362 * @property autoAbort
11363 * Whether a new request should abort any pending requests. (defaults to false)
11369 * Serialize the passed form into a url encoded string
11370 * @param {String/HTMLElement} form
11373 serializeForm : function(form){
11374 return Roo.lib.Ajax.serializeForm(form);
11378 * Ext JS Library 1.1.1
11379 * Copyright(c) 2006-2007, Ext JS, LLC.
11381 * Originally Released Under LGPL - original licence link has changed is not relivant.
11384 * <script type="text/javascript">
11389 * @extends Roo.data.Connection
11390 * Global Ajax request class.
11392 * @instanceOf Roo.data.Connection
11394 Roo.Ajax = new Roo.data.Connection({
11403 * @cfg {String} url @hide
11406 * @cfg {Object} extraParams @hide
11409 * @cfg {Object} defaultHeaders @hide
11412 * @cfg {String} method (Optional) @hide
11415 * @cfg {Number} timeout (Optional) @hide
11418 * @cfg {Boolean} autoAbort (Optional) @hide
11422 * @cfg {Boolean} disableCaching (Optional) @hide
11426 * @property disableCaching
11427 * True to add a unique cache-buster param to GET requests. (defaults to true)
11432 * The default URL to be used for requests to the server. (defaults to undefined)
11436 * @property extraParams
11437 * An object containing properties which are used as
11438 * extra parameters to each request made by this object. (defaults to undefined)
11442 * @property defaultHeaders
11443 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11448 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11452 * @property timeout
11453 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11458 * @property autoAbort
11459 * Whether a new request should abort any pending requests. (defaults to false)
11465 * Serialize the passed form into a url encoded string
11466 * @param {String/HTMLElement} form
11469 serializeForm : function(form){
11470 return Roo.lib.Ajax.serializeForm(form);
11474 * Ext JS Library 1.1.1
11475 * Copyright(c) 2006-2007, Ext JS, LLC.
11477 * Originally Released Under LGPL - original licence link has changed is not relivant.
11480 * <script type="text/javascript">
11485 * @class Roo.UpdateManager
11486 * @extends Roo.util.Observable
11487 * Provides AJAX-style update for Element object.<br><br>
11490 * // Get it from a Roo.Element object
11491 * var el = Roo.get("foo");
11492 * var mgr = el.getUpdateManager();
11493 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11495 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11497 * // or directly (returns the same UpdateManager instance)
11498 * var mgr = new Roo.UpdateManager("myElementId");
11499 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11500 * mgr.on("update", myFcnNeedsToKnow);
11502 // short handed call directly from the element object
11503 Roo.get("foo").load({
11507 text: "Loading Foo..."
11511 * Create new UpdateManager directly.
11512 * @param {String/HTMLElement/Roo.Element} el The element to update
11513 * @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).
11515 Roo.UpdateManager = function(el, forceNew){
11517 if(!forceNew && el.updateManager){
11518 return el.updateManager;
11521 * The Element object
11522 * @type Roo.Element
11526 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11529 this.defaultUrl = null;
11533 * @event beforeupdate
11534 * Fired before an update is made, return false from your handler and the update is cancelled.
11535 * @param {Roo.Element} el
11536 * @param {String/Object/Function} url
11537 * @param {String/Object} params
11539 "beforeupdate": true,
11542 * Fired after successful update is made.
11543 * @param {Roo.Element} el
11544 * @param {Object} oResponseObject The response Object
11549 * Fired on update failure.
11550 * @param {Roo.Element} el
11551 * @param {Object} oResponseObject The response Object
11555 var d = Roo.UpdateManager.defaults;
11557 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11560 this.sslBlankUrl = d.sslBlankUrl;
11562 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11565 this.disableCaching = d.disableCaching;
11567 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11570 this.indicatorText = d.indicatorText;
11572 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11575 this.showLoadIndicator = d.showLoadIndicator;
11577 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11580 this.timeout = d.timeout;
11583 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11586 this.loadScripts = d.loadScripts;
11589 * Transaction object of current executing transaction
11591 this.transaction = null;
11596 this.autoRefreshProcId = null;
11598 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11601 this.refreshDelegate = this.refresh.createDelegate(this);
11603 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11606 this.updateDelegate = this.update.createDelegate(this);
11608 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11611 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11615 this.successDelegate = this.processSuccess.createDelegate(this);
11619 this.failureDelegate = this.processFailure.createDelegate(this);
11621 if(!this.renderer){
11623 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11625 this.renderer = new Roo.UpdateManager.BasicRenderer();
11628 Roo.UpdateManager.superclass.constructor.call(this);
11631 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11633 * Get the Element this UpdateManager is bound to
11634 * @return {Roo.Element} The element
11636 getEl : function(){
11640 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11641 * @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:
11644 url: "your-url.php",<br/>
11645 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11646 callback: yourFunction,<br/>
11647 scope: yourObject, //(optional scope) <br/>
11648 discardUrl: false, <br/>
11649 nocache: false,<br/>
11650 text: "Loading...",<br/>
11652 scripts: false<br/>
11655 * The only required property is url. The optional properties nocache, text and scripts
11656 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11657 * @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}
11658 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11659 * @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.
11661 update : function(url, params, callback, discardUrl){
11662 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11663 var method = this.method, cfg;
11664 if(typeof url == "object"){ // must be config object
11667 params = params || cfg.params;
11668 callback = callback || cfg.callback;
11669 discardUrl = discardUrl || cfg.discardUrl;
11670 if(callback && cfg.scope){
11671 callback = callback.createDelegate(cfg.scope);
11673 if(typeof cfg.method != "undefined"){method = cfg.method;};
11674 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11675 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11676 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11677 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11679 this.showLoading();
11681 this.defaultUrl = url;
11683 if(typeof url == "function"){
11684 url = url.call(this);
11687 method = method || (params ? "POST" : "GET");
11688 if(method == "GET"){
11689 url = this.prepareUrl(url);
11692 var o = Roo.apply(cfg ||{}, {
11695 success: this.successDelegate,
11696 failure: this.failureDelegate,
11697 callback: undefined,
11698 timeout: (this.timeout*1000),
11699 argument: {"url": url, "form": null, "callback": callback, "params": params}
11702 this.transaction = Roo.Ajax.request(o);
11707 * 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.
11708 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11709 * @param {String/HTMLElement} form The form Id or form element
11710 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11711 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11712 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11714 formUpdate : function(form, url, reset, callback){
11715 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11716 if(typeof url == "function"){
11717 url = url.call(this);
11719 form = Roo.getDom(form);
11720 this.transaction = Roo.Ajax.request({
11723 success: this.successDelegate,
11724 failure: this.failureDelegate,
11725 timeout: (this.timeout*1000),
11726 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11728 this.showLoading.defer(1, this);
11733 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11734 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11736 refresh : function(callback){
11737 if(this.defaultUrl == null){
11740 this.update(this.defaultUrl, null, callback, true);
11744 * Set this element to auto refresh.
11745 * @param {Number} interval How often to update (in seconds).
11746 * @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)
11747 * @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}
11748 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11749 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11751 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11753 this.update(url || this.defaultUrl, params, callback, true);
11755 if(this.autoRefreshProcId){
11756 clearInterval(this.autoRefreshProcId);
11758 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11762 * Stop auto refresh on this element.
11764 stopAutoRefresh : function(){
11765 if(this.autoRefreshProcId){
11766 clearInterval(this.autoRefreshProcId);
11767 delete this.autoRefreshProcId;
11771 isAutoRefreshing : function(){
11772 return this.autoRefreshProcId ? true : false;
11775 * Called to update the element to "Loading" state. Override to perform custom action.
11777 showLoading : function(){
11778 if(this.showLoadIndicator){
11779 this.el.update(this.indicatorText);
11784 * Adds unique parameter to query string if disableCaching = true
11787 prepareUrl : function(url){
11788 if(this.disableCaching){
11789 var append = "_dc=" + (new Date().getTime());
11790 if(url.indexOf("?") !== -1){
11791 url += "&" + append;
11793 url += "?" + append;
11802 processSuccess : function(response){
11803 this.transaction = null;
11804 if(response.argument.form && response.argument.reset){
11805 try{ // put in try/catch since some older FF releases had problems with this
11806 response.argument.form.reset();
11809 if(this.loadScripts){
11810 this.renderer.render(this.el, response, this,
11811 this.updateComplete.createDelegate(this, [response]));
11813 this.renderer.render(this.el, response, this);
11814 this.updateComplete(response);
11818 updateComplete : function(response){
11819 this.fireEvent("update", this.el, response);
11820 if(typeof response.argument.callback == "function"){
11821 response.argument.callback(this.el, true, response);
11828 processFailure : function(response){
11829 this.transaction = null;
11830 this.fireEvent("failure", this.el, response);
11831 if(typeof response.argument.callback == "function"){
11832 response.argument.callback(this.el, false, response);
11837 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11838 * @param {Object} renderer The object implementing the render() method
11840 setRenderer : function(renderer){
11841 this.renderer = renderer;
11844 getRenderer : function(){
11845 return this.renderer;
11849 * Set the defaultUrl used for updates
11850 * @param {String/Function} defaultUrl The url or a function to call to get the url
11852 setDefaultUrl : function(defaultUrl){
11853 this.defaultUrl = defaultUrl;
11857 * Aborts the executing transaction
11859 abort : function(){
11860 if(this.transaction){
11861 Roo.Ajax.abort(this.transaction);
11866 * Returns true if an update is in progress
11867 * @return {Boolean}
11869 isUpdating : function(){
11870 if(this.transaction){
11871 return Roo.Ajax.isLoading(this.transaction);
11878 * @class Roo.UpdateManager.defaults
11879 * @static (not really - but it helps the doc tool)
11880 * The defaults collection enables customizing the default properties of UpdateManager
11882 Roo.UpdateManager.defaults = {
11884 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
11890 * True to process scripts by default (Defaults to false).
11893 loadScripts : false,
11896 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
11899 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
11901 * Whether to append unique parameter on get request to disable caching (Defaults to false).
11904 disableCaching : false,
11906 * Whether to show indicatorText when loading (Defaults to true).
11909 showLoadIndicator : true,
11911 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
11914 indicatorText : '<div class="loading-indicator">Loading...</div>'
11918 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
11920 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
11921 * @param {String/HTMLElement/Roo.Element} el The element to update
11922 * @param {String} url The url
11923 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
11924 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
11927 * @member Roo.UpdateManager
11929 Roo.UpdateManager.updateElement = function(el, url, params, options){
11930 var um = Roo.get(el, true).getUpdateManager();
11931 Roo.apply(um, options);
11932 um.update(url, params, options ? options.callback : null);
11934 // alias for backwards compat
11935 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
11937 * @class Roo.UpdateManager.BasicRenderer
11938 * Default Content renderer. Updates the elements innerHTML with the responseText.
11940 Roo.UpdateManager.BasicRenderer = function(){};
11942 Roo.UpdateManager.BasicRenderer.prototype = {
11944 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
11945 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
11946 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
11947 * @param {Roo.Element} el The element being rendered
11948 * @param {Object} response The YUI Connect response object
11949 * @param {UpdateManager} updateManager The calling update manager
11950 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
11952 render : function(el, response, updateManager, callback){
11953 el.update(response.responseText, updateManager.loadScripts, callback);
11958 * Ext JS Library 1.1.1
11959 * Copyright(c) 2006-2007, Ext JS, LLC.
11961 * Originally Released Under LGPL - original licence link has changed is not relivant.
11964 * <script type="text/javascript">
11968 * @class Roo.util.DelayedTask
11969 * Provides a convenient method of performing setTimeout where a new
11970 * timeout cancels the old timeout. An example would be performing validation on a keypress.
11971 * You can use this class to buffer
11972 * the keypress events for a certain number of milliseconds, and perform only if they stop
11973 * for that amount of time.
11974 * @constructor The parameters to this constructor serve as defaults and are not required.
11975 * @param {Function} fn (optional) The default function to timeout
11976 * @param {Object} scope (optional) The default scope of that timeout
11977 * @param {Array} args (optional) The default Array of arguments
11979 Roo.util.DelayedTask = function(fn, scope, args){
11980 var id = null, d, t;
11982 var call = function(){
11983 var now = new Date().getTime();
11987 fn.apply(scope, args || []);
11991 * Cancels any pending timeout and queues a new one
11992 * @param {Number} delay The milliseconds to delay
11993 * @param {Function} newFn (optional) Overrides function passed to constructor
11994 * @param {Object} newScope (optional) Overrides scope passed to constructor
11995 * @param {Array} newArgs (optional) Overrides args passed to constructor
11997 this.delay = function(delay, newFn, newScope, newArgs){
11998 if(id && delay != d){
12002 t = new Date().getTime();
12004 scope = newScope || scope;
12005 args = newArgs || args;
12007 id = setInterval(call, d);
12012 * Cancel the last queued timeout
12014 this.cancel = function(){
12022 * Ext JS Library 1.1.1
12023 * Copyright(c) 2006-2007, Ext JS, LLC.
12025 * Originally Released Under LGPL - original licence link has changed is not relivant.
12028 * <script type="text/javascript">
12032 Roo.util.TaskRunner = function(interval){
12033 interval = interval || 10;
12034 var tasks = [], removeQueue = [];
12036 var running = false;
12038 var stopThread = function(){
12044 var startThread = function(){
12047 id = setInterval(runTasks, interval);
12051 var removeTask = function(task){
12052 removeQueue.push(task);
12058 var runTasks = function(){
12059 if(removeQueue.length > 0){
12060 for(var i = 0, len = removeQueue.length; i < len; i++){
12061 tasks.remove(removeQueue[i]);
12064 if(tasks.length < 1){
12069 var now = new Date().getTime();
12070 for(var i = 0, len = tasks.length; i < len; ++i){
12072 var itime = now - t.taskRunTime;
12073 if(t.interval <= itime){
12074 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12075 t.taskRunTime = now;
12076 if(rt === false || t.taskRunCount === t.repeat){
12081 if(t.duration && t.duration <= (now - t.taskStartTime)){
12088 * Queues a new task.
12089 * @param {Object} task
12091 this.start = function(task){
12093 task.taskStartTime = new Date().getTime();
12094 task.taskRunTime = 0;
12095 task.taskRunCount = 0;
12100 this.stop = function(task){
12105 this.stopAll = function(){
12107 for(var i = 0, len = tasks.length; i < len; i++){
12108 if(tasks[i].onStop){
12117 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12119 * Ext JS Library 1.1.1
12120 * Copyright(c) 2006-2007, Ext JS, LLC.
12122 * Originally Released Under LGPL - original licence link has changed is not relivant.
12125 * <script type="text/javascript">
12130 * @class Roo.util.MixedCollection
12131 * @extends Roo.util.Observable
12132 * A Collection class that maintains both numeric indexes and keys and exposes events.
12134 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12135 * collection (defaults to false)
12136 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12137 * and return the key value for that item. This is used when available to look up the key on items that
12138 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12139 * equivalent to providing an implementation for the {@link #getKey} method.
12141 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12149 * Fires when the collection is cleared.
12154 * Fires when an item is added to the collection.
12155 * @param {Number} index The index at which the item was added.
12156 * @param {Object} o The item added.
12157 * @param {String} key The key associated with the added item.
12162 * Fires when an item is replaced in the collection.
12163 * @param {String} key he key associated with the new added.
12164 * @param {Object} old The item being replaced.
12165 * @param {Object} new The new item.
12170 * Fires when an item is removed from the collection.
12171 * @param {Object} o The item being removed.
12172 * @param {String} key (optional) The key associated with the removed item.
12177 this.allowFunctions = allowFunctions === true;
12179 this.getKey = keyFn;
12181 Roo.util.MixedCollection.superclass.constructor.call(this);
12184 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12185 allowFunctions : false,
12188 * Adds an item to the collection.
12189 * @param {String} key The key to associate with the item
12190 * @param {Object} o The item to add.
12191 * @return {Object} The item added.
12193 add : function(key, o){
12194 if(arguments.length == 1){
12196 key = this.getKey(o);
12198 if(typeof key == "undefined" || key === null){
12200 this.items.push(o);
12201 this.keys.push(null);
12203 var old = this.map[key];
12205 return this.replace(key, o);
12208 this.items.push(o);
12210 this.keys.push(key);
12212 this.fireEvent("add", this.length-1, o, key);
12217 * MixedCollection has a generic way to fetch keys if you implement getKey.
12220 var mc = new Roo.util.MixedCollection();
12221 mc.add(someEl.dom.id, someEl);
12222 mc.add(otherEl.dom.id, otherEl);
12226 var mc = new Roo.util.MixedCollection();
12227 mc.getKey = function(el){
12233 // or via the constructor
12234 var mc = new Roo.util.MixedCollection(false, function(el){
12240 * @param o {Object} The item for which to find the key.
12241 * @return {Object} The key for the passed item.
12243 getKey : function(o){
12248 * Replaces an item in the collection.
12249 * @param {String} key The key associated with the item to replace, or the item to replace.
12250 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12251 * @return {Object} The new item.
12253 replace : function(key, o){
12254 if(arguments.length == 1){
12256 key = this.getKey(o);
12258 var old = this.item(key);
12259 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12260 return this.add(key, o);
12262 var index = this.indexOfKey(key);
12263 this.items[index] = o;
12265 this.fireEvent("replace", key, old, o);
12270 * Adds all elements of an Array or an Object to the collection.
12271 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12272 * an Array of values, each of which are added to the collection.
12274 addAll : function(objs){
12275 if(arguments.length > 1 || objs instanceof Array){
12276 var args = arguments.length > 1 ? arguments : objs;
12277 for(var i = 0, len = args.length; i < len; i++){
12281 for(var key in objs){
12282 if(this.allowFunctions || typeof objs[key] != "function"){
12283 this.add(key, objs[key]);
12290 * Executes the specified function once for every item in the collection, passing each
12291 * item as the first and only parameter. returning false from the function will stop the iteration.
12292 * @param {Function} fn The function to execute for each item.
12293 * @param {Object} scope (optional) The scope in which to execute the function.
12295 each : function(fn, scope){
12296 var items = [].concat(this.items); // each safe for removal
12297 for(var i = 0, len = items.length; i < len; i++){
12298 if(fn.call(scope || items[i], items[i], i, len) === false){
12305 * Executes the specified function once for every key in the collection, passing each
12306 * key, and its associated item as the first two parameters.
12307 * @param {Function} fn The function to execute for each item.
12308 * @param {Object} scope (optional) The scope in which to execute the function.
12310 eachKey : function(fn, scope){
12311 for(var i = 0, len = this.keys.length; i < len; i++){
12312 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12317 * Returns the first item in the collection which elicits a true return value from the
12318 * passed selection function.
12319 * @param {Function} fn The selection function to execute for each item.
12320 * @param {Object} scope (optional) The scope in which to execute the function.
12321 * @return {Object} The first item in the collection which returned true from the selection function.
12323 find : function(fn, scope){
12324 for(var i = 0, len = this.items.length; i < len; i++){
12325 if(fn.call(scope || window, this.items[i], this.keys[i])){
12326 return this.items[i];
12333 * Inserts an item at the specified index in the collection.
12334 * @param {Number} index The index to insert the item at.
12335 * @param {String} key The key to associate with the new item, or the item itself.
12336 * @param {Object} o (optional) If the second parameter was a key, the new item.
12337 * @return {Object} The item inserted.
12339 insert : function(index, key, o){
12340 if(arguments.length == 2){
12342 key = this.getKey(o);
12344 if(index >= this.length){
12345 return this.add(key, o);
12348 this.items.splice(index, 0, o);
12349 if(typeof key != "undefined" && key != null){
12352 this.keys.splice(index, 0, key);
12353 this.fireEvent("add", index, o, key);
12358 * Removed an item from the collection.
12359 * @param {Object} o The item to remove.
12360 * @return {Object} The item removed.
12362 remove : function(o){
12363 return this.removeAt(this.indexOf(o));
12367 * Remove an item from a specified index in the collection.
12368 * @param {Number} index The index within the collection of the item to remove.
12370 removeAt : function(index){
12371 if(index < this.length && index >= 0){
12373 var o = this.items[index];
12374 this.items.splice(index, 1);
12375 var key = this.keys[index];
12376 if(typeof key != "undefined"){
12377 delete this.map[key];
12379 this.keys.splice(index, 1);
12380 this.fireEvent("remove", o, key);
12385 * Removed an item associated with the passed key fom the collection.
12386 * @param {String} key The key of the item to remove.
12388 removeKey : function(key){
12389 return this.removeAt(this.indexOfKey(key));
12393 * Returns the number of items in the collection.
12394 * @return {Number} the number of items in the collection.
12396 getCount : function(){
12397 return this.length;
12401 * Returns index within the collection of the passed Object.
12402 * @param {Object} o The item to find the index of.
12403 * @return {Number} index of the item.
12405 indexOf : function(o){
12406 if(!this.items.indexOf){
12407 for(var i = 0, len = this.items.length; i < len; i++){
12408 if(this.items[i] == o) return i;
12412 return this.items.indexOf(o);
12417 * Returns index within the collection of the passed key.
12418 * @param {String} key The key to find the index of.
12419 * @return {Number} index of the key.
12421 indexOfKey : function(key){
12422 if(!this.keys.indexOf){
12423 for(var i = 0, len = this.keys.length; i < len; i++){
12424 if(this.keys[i] == key) return i;
12428 return this.keys.indexOf(key);
12433 * Returns the item associated with the passed key OR index. Key has priority over index.
12434 * @param {String/Number} key The key or index of the item.
12435 * @return {Object} The item associated with the passed key.
12437 item : function(key){
12438 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12439 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12443 * Returns the item at the specified index.
12444 * @param {Number} index The index of the item.
12447 itemAt : function(index){
12448 return this.items[index];
12452 * Returns the item associated with the passed key.
12453 * @param {String/Number} key The key of the item.
12454 * @return {Object} The item associated with the passed key.
12456 key : function(key){
12457 return this.map[key];
12461 * Returns true if the collection contains the passed Object as an item.
12462 * @param {Object} o The Object to look for in the collection.
12463 * @return {Boolean} True if the collection contains the Object as an item.
12465 contains : function(o){
12466 return this.indexOf(o) != -1;
12470 * Returns true if the collection contains the passed Object as a key.
12471 * @param {String} key The key to look for in the collection.
12472 * @return {Boolean} True if the collection contains the Object as a key.
12474 containsKey : function(key){
12475 return typeof this.map[key] != "undefined";
12479 * Removes all items from the collection.
12481 clear : function(){
12486 this.fireEvent("clear");
12490 * Returns the first item in the collection.
12491 * @return {Object} the first item in the collection..
12493 first : function(){
12494 return this.items[0];
12498 * Returns the last item in the collection.
12499 * @return {Object} the last item in the collection..
12502 return this.items[this.length-1];
12505 _sort : function(property, dir, fn){
12506 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12507 fn = fn || function(a, b){
12510 var c = [], k = this.keys, items = this.items;
12511 for(var i = 0, len = items.length; i < len; i++){
12512 c[c.length] = {key: k[i], value: items[i], index: i};
12514 c.sort(function(a, b){
12515 var v = fn(a[property], b[property]) * dsc;
12517 v = (a.index < b.index ? -1 : 1);
12521 for(var i = 0, len = c.length; i < len; i++){
12522 items[i] = c[i].value;
12525 this.fireEvent("sort", this);
12529 * Sorts this collection with the passed comparison function
12530 * @param {String} direction (optional) "ASC" or "DESC"
12531 * @param {Function} fn (optional) comparison function
12533 sort : function(dir, fn){
12534 this._sort("value", dir, fn);
12538 * Sorts this collection by keys
12539 * @param {String} direction (optional) "ASC" or "DESC"
12540 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12542 keySort : function(dir, fn){
12543 this._sort("key", dir, fn || function(a, b){
12544 return String(a).toUpperCase()-String(b).toUpperCase();
12549 * Returns a range of items in this collection
12550 * @param {Number} startIndex (optional) defaults to 0
12551 * @param {Number} endIndex (optional) default to the last item
12552 * @return {Array} An array of items
12554 getRange : function(start, end){
12555 var items = this.items;
12556 if(items.length < 1){
12559 start = start || 0;
12560 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12563 for(var i = start; i <= end; i++) {
12564 r[r.length] = items[i];
12567 for(var i = start; i >= end; i--) {
12568 r[r.length] = items[i];
12575 * Filter the <i>objects</i> in this collection by a specific property.
12576 * Returns a new collection that has been filtered.
12577 * @param {String} property A property on your objects
12578 * @param {String/RegExp} value Either string that the property values
12579 * should start with or a RegExp to test against the property
12580 * @return {MixedCollection} The new filtered collection
12582 filter : function(property, value){
12583 if(!value.exec){ // not a regex
12584 value = String(value);
12585 if(value.length == 0){
12586 return this.clone();
12588 value = new RegExp("^" + Roo.escapeRe(value), "i");
12590 return this.filterBy(function(o){
12591 return o && value.test(o[property]);
12596 * Filter by a function. * Returns a new collection that has been filtered.
12597 * The passed function will be called with each
12598 * object in the collection. If the function returns true, the value is included
12599 * otherwise it is filtered.
12600 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12601 * @param {Object} scope (optional) The scope of the function (defaults to this)
12602 * @return {MixedCollection} The new filtered collection
12604 filterBy : function(fn, scope){
12605 var r = new Roo.util.MixedCollection();
12606 r.getKey = this.getKey;
12607 var k = this.keys, it = this.items;
12608 for(var i = 0, len = it.length; i < len; i++){
12609 if(fn.call(scope||this, it[i], k[i])){
12610 r.add(k[i], it[i]);
12617 * Creates a duplicate of this collection
12618 * @return {MixedCollection}
12620 clone : function(){
12621 var r = new Roo.util.MixedCollection();
12622 var k = this.keys, it = this.items;
12623 for(var i = 0, len = it.length; i < len; i++){
12624 r.add(k[i], it[i]);
12626 r.getKey = this.getKey;
12631 * Returns the item associated with the passed key or index.
12633 * @param {String/Number} key The key or index of the item.
12634 * @return {Object} The item associated with the passed key.
12636 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12638 * Ext JS Library 1.1.1
12639 * Copyright(c) 2006-2007, Ext JS, LLC.
12641 * Originally Released Under LGPL - original licence link has changed is not relivant.
12644 * <script type="text/javascript">
12647 * @class Roo.util.JSON
12648 * Modified version of Douglas Crockford"s json.js that doesn"t
12649 * mess with the Object prototype
12650 * http://www.json.org/js.html
12653 Roo.util.JSON = new (function(){
12654 var useHasOwn = {}.hasOwnProperty ? true : false;
12656 // crashes Safari in some instances
12657 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12659 var pad = function(n) {
12660 return n < 10 ? "0" + n : n;
12673 var encodeString = function(s){
12674 if (/["\\\x00-\x1f]/.test(s)) {
12675 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12680 c = b.charCodeAt();
12682 Math.floor(c / 16).toString(16) +
12683 (c % 16).toString(16);
12686 return '"' + s + '"';
12689 var encodeArray = function(o){
12690 var a = ["["], b, i, l = o.length, v;
12691 for (i = 0; i < l; i += 1) {
12693 switch (typeof v) {
12702 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12710 var encodeDate = function(o){
12711 return '"' + o.getFullYear() + "-" +
12712 pad(o.getMonth() + 1) + "-" +
12713 pad(o.getDate()) + "T" +
12714 pad(o.getHours()) + ":" +
12715 pad(o.getMinutes()) + ":" +
12716 pad(o.getSeconds()) + '"';
12720 * Encodes an Object, Array or other value
12721 * @param {Mixed} o The variable to encode
12722 * @return {String} The JSON string
12724 this.encode = function(o){
12725 if(typeof o == "undefined" || o === null){
12727 }else if(o instanceof Array){
12728 return encodeArray(o);
12729 }else if(o instanceof Date){
12730 return encodeDate(o);
12731 }else if(typeof o == "string"){
12732 return encodeString(o);
12733 }else if(typeof o == "number"){
12734 return isFinite(o) ? String(o) : "null";
12735 }else if(typeof o == "boolean"){
12738 var a = ["{"], b, i, v;
12740 if(!useHasOwn || o.hasOwnProperty(i)) {
12742 switch (typeof v) {
12751 a.push(this.encode(i), ":",
12752 v === null ? "null" : this.encode(v));
12763 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12764 * @param {String} json The JSON string
12765 * @return {Object} The resulting object
12767 this.decode = function(json){
12771 return eval("(" + json + ')');
12775 * Shorthand for {@link Roo.util.JSON#encode}
12776 * @member Roo encode
12778 Roo.encode = Roo.util.JSON.encode;
12780 * Shorthand for {@link Roo.util.JSON#decode}
12781 * @member Roo decode
12783 Roo.decode = Roo.util.JSON.decode;
12786 * Ext JS Library 1.1.1
12787 * Copyright(c) 2006-2007, Ext JS, LLC.
12789 * Originally Released Under LGPL - original licence link has changed is not relivant.
12792 * <script type="text/javascript">
12796 * @class Roo.util.Format
12797 * Reusable data formatting functions
12800 Roo.util.Format = function(){
12801 var trimRe = /^\s+|\s+$/g;
12804 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12805 * @param {String} value The string to truncate
12806 * @param {Number} length The maximum length to allow before truncating
12807 * @return {String} The converted text
12809 ellipsis : function(value, len){
12810 if(value && value.length > len){
12811 return value.substr(0, len-3)+"...";
12817 * Checks a reference and converts it to empty string if it is undefined
12818 * @param {Mixed} value Reference to check
12819 * @return {Mixed} Empty string if converted, otherwise the original value
12821 undef : function(value){
12822 return typeof value != "undefined" ? value : "";
12826 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12827 * @param {String} value The string to encode
12828 * @return {String} The encoded text
12830 htmlEncode : function(value){
12831 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12835 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12836 * @param {String} value The string to decode
12837 * @return {String} The decoded text
12839 htmlDecode : function(value){
12840 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12844 * Trims any whitespace from either side of a string
12845 * @param {String} value The text to trim
12846 * @return {String} The trimmed text
12848 trim : function(value){
12849 return String(value).replace(trimRe, "");
12853 * Returns a substring from within an original string
12854 * @param {String} value The original text
12855 * @param {Number} start The start index of the substring
12856 * @param {Number} length The length of the substring
12857 * @return {String} The substring
12859 substr : function(value, start, length){
12860 return String(value).substr(start, length);
12864 * Converts a string to all lower case letters
12865 * @param {String} value The text to convert
12866 * @return {String} The converted text
12868 lowercase : function(value){
12869 return String(value).toLowerCase();
12873 * Converts a string to all upper case letters
12874 * @param {String} value The text to convert
12875 * @return {String} The converted text
12877 uppercase : function(value){
12878 return String(value).toUpperCase();
12882 * Converts the first character only of a string to upper case
12883 * @param {String} value The text to convert
12884 * @return {String} The converted text
12886 capitalize : function(value){
12887 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
12891 call : function(value, fn){
12892 if(arguments.length > 2){
12893 var args = Array.prototype.slice.call(arguments, 2);
12894 args.unshift(value);
12896 return /** eval:var:value */ eval(fn).apply(window, args);
12898 /** eval:var:value */
12899 return /** eval:var:value */ eval(fn).call(window, value);
12904 * Format a number as US currency
12905 * @param {Number/String} value The numeric value to format
12906 * @return {String} The formatted currency string
12908 usMoney : function(v){
12909 v = (Math.round((v-0)*100))/100;
12910 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
12912 var ps = v.split('.');
12914 var sub = ps[1] ? '.'+ ps[1] : '.00';
12915 var r = /(\d+)(\d{3})/;
12916 while (r.test(whole)) {
12917 whole = whole.replace(r, '$1' + ',' + '$2');
12919 return "$" + whole + sub ;
12923 * Parse a value into a formatted date using the specified format pattern.
12924 * @param {Mixed} value The value to format
12925 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
12926 * @return {String} The formatted date string
12928 date : function(v, format){
12932 if(!(v instanceof Date)){
12933 v = new Date(Date.parse(v));
12935 return v.dateFormat(format || "m/d/Y");
12939 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
12940 * @param {String} format Any valid date format string
12941 * @return {Function} The date formatting function
12943 dateRenderer : function(format){
12944 return function(v){
12945 return Roo.util.Format.date(v, format);
12950 stripTagsRE : /<\/?[^>]+>/gi,
12953 * Strips all HTML tags
12954 * @param {Mixed} value The text from which to strip tags
12955 * @return {String} The stripped text
12957 stripTags : function(v){
12958 return !v ? v : String(v).replace(this.stripTagsRE, "");
12963 * Ext JS Library 1.1.1
12964 * Copyright(c) 2006-2007, Ext JS, LLC.
12966 * Originally Released Under LGPL - original licence link has changed is not relivant.
12969 * <script type="text/javascript">
12976 * @class Roo.MasterTemplate
12977 * @extends Roo.Template
12978 * Provides a template that can have child templates. The syntax is:
12980 var t = new Roo.MasterTemplate(
12981 '<select name="{name}">',
12982 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
12985 t.add('options', {value: 'foo', text: 'bar'});
12986 // or you can add multiple child elements in one shot
12987 t.addAll('options', [
12988 {value: 'foo', text: 'bar'},
12989 {value: 'foo2', text: 'bar2'},
12990 {value: 'foo3', text: 'bar3'}
12992 // then append, applying the master template values
12993 t.append('my-form', {name: 'my-select'});
12995 * A name attribute for the child template is not required if you have only one child
12996 * template or you want to refer to them by index.
12998 Roo.MasterTemplate = function(){
12999 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13000 this.originalHtml = this.html;
13002 var m, re = this.subTemplateRe;
13005 while(m = re.exec(this.html)){
13006 var name = m[1], content = m[2];
13011 tpl : new Roo.Template(content)
13014 st[name] = st[subIndex];
13016 st[subIndex].tpl.compile();
13017 st[subIndex].tpl.call = this.call.createDelegate(this);
13020 this.subCount = subIndex;
13023 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13025 * The regular expression used to match sub templates
13029 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13032 * Applies the passed values to a child template.
13033 * @param {String/Number} name (optional) The name or index of the child template
13034 * @param {Array/Object} values The values to be applied to the template
13035 * @return {MasterTemplate} this
13037 add : function(name, values){
13038 if(arguments.length == 1){
13039 values = arguments[0];
13042 var s = this.subs[name];
13043 s.buffer[s.buffer.length] = s.tpl.apply(values);
13048 * Applies all the passed values to a child template.
13049 * @param {String/Number} name (optional) The name or index of the child template
13050 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13051 * @param {Boolean} reset (optional) True to reset the template first
13052 * @return {MasterTemplate} this
13054 fill : function(name, values, reset){
13056 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13064 for(var i = 0, len = values.length; i < len; i++){
13065 this.add(name, values[i]);
13071 * Resets the template for reuse
13072 * @return {MasterTemplate} this
13074 reset : function(){
13076 for(var i = 0; i < this.subCount; i++){
13082 applyTemplate : function(values){
13084 var replaceIndex = -1;
13085 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13086 return s[++replaceIndex].buffer.join("");
13088 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13091 apply : function(){
13092 return this.applyTemplate.apply(this, arguments);
13095 compile : function(){return this;}
13099 * Alias for fill().
13102 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13104 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13105 * var tpl = Roo.MasterTemplate.from('element-id');
13106 * @param {String/HTMLElement} el
13107 * @param {Object} config
13110 Roo.MasterTemplate.from = function(el, config){
13111 el = Roo.getDom(el);
13112 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13115 * Ext JS Library 1.1.1
13116 * Copyright(c) 2006-2007, Ext JS, LLC.
13118 * Originally Released Under LGPL - original licence link has changed is not relivant.
13121 * <script type="text/javascript">
13126 * @class Roo.util.CSS
13127 * Utility class for manipulating CSS rules
13130 Roo.util.CSS = function(){
13132 var doc = document;
13134 var camelRe = /(-[a-z])/gi;
13135 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13139 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13140 * tag and appended to the HEAD of the document.
13141 * @param {String} cssText The text containing the css rules
13142 * @param {String} id An id to add to the stylesheet for later removal
13143 * @return {StyleSheet}
13145 createStyleSheet : function(cssText, id){
13147 var head = doc.getElementsByTagName("head")[0];
13148 var rules = doc.createElement("style");
13149 rules.setAttribute("type", "text/css");
13151 rules.setAttribute("id", id);
13154 head.appendChild(rules);
13155 ss = rules.styleSheet;
13156 ss.cssText = cssText;
13159 rules.appendChild(doc.createTextNode(cssText));
13161 rules.cssText = cssText;
13163 head.appendChild(rules);
13164 ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13166 this.cacheStyleSheet(ss);
13171 * Removes a style or link tag by id
13172 * @param {String} id The id of the tag
13174 removeStyleSheet : function(id){
13175 var existing = doc.getElementById(id);
13177 existing.parentNode.removeChild(existing);
13182 * Dynamically swaps an existing stylesheet reference for a new one
13183 * @param {String} id The id of an existing link tag to remove
13184 * @param {String} url The href of the new stylesheet to include
13186 swapStyleSheet : function(id, url){
13187 this.removeStyleSheet(id);
13188 var ss = doc.createElement("link");
13189 ss.setAttribute("rel", "stylesheet");
13190 ss.setAttribute("type", "text/css");
13191 ss.setAttribute("id", id);
13192 ss.setAttribute("href", url);
13193 doc.getElementsByTagName("head")[0].appendChild(ss);
13197 * Refresh the rule cache if you have dynamically added stylesheets
13198 * @return {Object} An object (hash) of rules indexed by selector
13200 refreshCache : function(){
13201 return this.getRules(true);
13205 cacheStyleSheet : function(ss){
13209 try{// try catch for cross domain access issue
13210 var ssRules = ss.cssRules || ss.rules;
13211 for(var j = ssRules.length-1; j >= 0; --j){
13212 rules[ssRules[j].selectorText] = ssRules[j];
13218 * Gets all css rules for the document
13219 * @param {Boolean} refreshCache true to refresh the internal cache
13220 * @return {Object} An object (hash) of rules indexed by selector
13222 getRules : function(refreshCache){
13223 if(rules == null || refreshCache){
13225 var ds = doc.styleSheets;
13226 for(var i =0, len = ds.length; i < len; i++){
13228 this.cacheStyleSheet(ds[i]);
13236 * Gets an an individual CSS rule by selector(s)
13237 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13238 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13239 * @return {CSSRule} The CSS rule or null if one is not found
13241 getRule : function(selector, refreshCache){
13242 var rs = this.getRules(refreshCache);
13243 if(!(selector instanceof Array)){
13244 return rs[selector];
13246 for(var i = 0; i < selector.length; i++){
13247 if(rs[selector[i]]){
13248 return rs[selector[i]];
13256 * Updates a rule property
13257 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13258 * @param {String} property The css property
13259 * @param {String} value The new value for the property
13260 * @return {Boolean} true If a rule was found and updated
13262 updateRule : function(selector, property, value){
13263 if(!(selector instanceof Array)){
13264 var rule = this.getRule(selector);
13266 rule.style[property.replace(camelRe, camelFn)] = value;
13270 for(var i = 0; i < selector.length; i++){
13271 if(this.updateRule(selector[i], property, value)){
13281 * Ext JS Library 1.1.1
13282 * Copyright(c) 2006-2007, Ext JS, LLC.
13284 * Originally Released Under LGPL - original licence link has changed is not relivant.
13287 * <script type="text/javascript">
13293 * @class Roo.util.ClickRepeater
13294 * @extends Roo.util.Observable
13296 * A wrapper class which can be applied to any element. Fires a "click" event while the
13297 * mouse is pressed. The interval between firings may be specified in the config but
13298 * defaults to 10 milliseconds.
13300 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13302 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13303 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13304 * Similar to an autorepeat key delay.
13305 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13306 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13307 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13308 * "interval" and "delay" are ignored. "immediate" is honored.
13309 * @cfg {Boolean} preventDefault True to prevent the default click event
13310 * @cfg {Boolean} stopDefault True to stop the default click event
13313 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13314 * 2007-02-02 jvs Renamed to ClickRepeater
13315 * 2007-02-03 jvs Modifications for FF Mac and Safari
13318 * @param {String/HTMLElement/Element} el The element to listen on
13319 * @param {Object} config
13321 Roo.util.ClickRepeater = function(el, config)
13323 this.el = Roo.get(el);
13324 this.el.unselectable();
13326 Roo.apply(this, config);
13331 * Fires when the mouse button is depressed.
13332 * @param {Roo.util.ClickRepeater} this
13334 "mousedown" : true,
13337 * Fires on a specified interval during the time the element is pressed.
13338 * @param {Roo.util.ClickRepeater} this
13343 * Fires when the mouse key is released.
13344 * @param {Roo.util.ClickRepeater} this
13349 this.el.on("mousedown", this.handleMouseDown, this);
13350 if(this.preventDefault || this.stopDefault){
13351 this.el.on("click", function(e){
13352 if(this.preventDefault){
13353 e.preventDefault();
13355 if(this.stopDefault){
13361 // allow inline handler
13363 this.on("click", this.handler, this.scope || this);
13366 Roo.util.ClickRepeater.superclass.constructor.call(this);
13369 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13372 preventDefault : true,
13373 stopDefault : false,
13377 handleMouseDown : function(){
13378 clearTimeout(this.timer);
13380 if(this.pressClass){
13381 this.el.addClass(this.pressClass);
13383 this.mousedownTime = new Date();
13385 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13386 this.el.on("mouseout", this.handleMouseOut, this);
13388 this.fireEvent("mousedown", this);
13389 this.fireEvent("click", this);
13391 this.timer = this.click.defer(this.delay || this.interval, this);
13395 click : function(){
13396 this.fireEvent("click", this);
13397 this.timer = this.click.defer(this.getInterval(), this);
13401 getInterval: function(){
13402 if(!this.accelerate){
13403 return this.interval;
13405 var pressTime = this.mousedownTime.getElapsed();
13406 if(pressTime < 500){
13408 }else if(pressTime < 1700){
13410 }else if(pressTime < 2600){
13412 }else if(pressTime < 3500){
13414 }else if(pressTime < 4400){
13416 }else if(pressTime < 5300){
13418 }else if(pressTime < 6200){
13426 handleMouseOut : function(){
13427 clearTimeout(this.timer);
13428 if(this.pressClass){
13429 this.el.removeClass(this.pressClass);
13431 this.el.on("mouseover", this.handleMouseReturn, this);
13435 handleMouseReturn : function(){
13436 this.el.un("mouseover", this.handleMouseReturn);
13437 if(this.pressClass){
13438 this.el.addClass(this.pressClass);
13444 handleMouseUp : function(){
13445 clearTimeout(this.timer);
13446 this.el.un("mouseover", this.handleMouseReturn);
13447 this.el.un("mouseout", this.handleMouseOut);
13448 Roo.get(document).un("mouseup", this.handleMouseUp);
13449 this.el.removeClass(this.pressClass);
13450 this.fireEvent("mouseup", this);
13454 * Ext JS Library 1.1.1
13455 * Copyright(c) 2006-2007, Ext JS, LLC.
13457 * Originally Released Under LGPL - original licence link has changed is not relivant.
13460 * <script type="text/javascript">
13465 * @class Roo.KeyNav
13466 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13467 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13468 * way to implement custom navigation schemes for any UI component.</p>
13469 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13470 * pageUp, pageDown, del, home, end. Usage:</p>
13472 var nav = new Roo.KeyNav("my-element", {
13473 "left" : function(e){
13474 this.moveLeft(e.ctrlKey);
13476 "right" : function(e){
13477 this.moveRight(e.ctrlKey);
13479 "enter" : function(e){
13486 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13487 * @param {Object} config The config
13489 Roo.KeyNav = function(el, config){
13490 this.el = Roo.get(el);
13491 Roo.apply(this, config);
13492 if(!this.disabled){
13493 this.disabled = true;
13498 Roo.KeyNav.prototype = {
13500 * @cfg {Boolean} disabled
13501 * True to disable this KeyNav instance (defaults to false)
13505 * @cfg {String} defaultEventAction
13506 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13507 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13508 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13510 defaultEventAction: "stopEvent",
13512 * @cfg {Boolean} forceKeyDown
13513 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13514 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13515 * handle keydown instead of keypress.
13517 forceKeyDown : false,
13520 prepareEvent : function(e){
13521 var k = e.getKey();
13522 var h = this.keyToHandler[k];
13523 //if(h && this[h]){
13524 // e.stopPropagation();
13526 if(Roo.isSafari && h && k >= 37 && k <= 40){
13532 relay : function(e){
13533 var k = e.getKey();
13534 var h = this.keyToHandler[k];
13536 if(this.doRelay(e, this[h], h) !== true){
13537 e[this.defaultEventAction]();
13543 doRelay : function(e, h, hname){
13544 return h.call(this.scope || this, e);
13547 // possible handlers
13561 // quick lookup hash
13578 * Enable this KeyNav
13580 enable: function(){
13582 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13583 // the EventObject will normalize Safari automatically
13584 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13585 this.el.on("keydown", this.relay, this);
13587 this.el.on("keydown", this.prepareEvent, this);
13588 this.el.on("keypress", this.relay, this);
13590 this.disabled = false;
13595 * Disable this KeyNav
13597 disable: function(){
13598 if(!this.disabled){
13599 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13600 this.el.un("keydown", this.relay);
13602 this.el.un("keydown", this.prepareEvent);
13603 this.el.un("keypress", this.relay);
13605 this.disabled = true;
13610 * Ext JS Library 1.1.1
13611 * Copyright(c) 2006-2007, Ext JS, LLC.
13613 * Originally Released Under LGPL - original licence link has changed is not relivant.
13616 * <script type="text/javascript">
13621 * @class Roo.KeyMap
13622 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13623 * The constructor accepts the same config object as defined by {@link #addBinding}.
13624 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13625 * combination it will call the function with this signature (if the match is a multi-key
13626 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13627 * A KeyMap can also handle a string representation of keys.<br />
13630 // map one key by key code
13631 var map = new Roo.KeyMap("my-element", {
13632 key: 13, // or Roo.EventObject.ENTER
13637 // map multiple keys to one action by string
13638 var map = new Roo.KeyMap("my-element", {
13644 // map multiple keys to multiple actions by strings and array of codes
13645 var map = new Roo.KeyMap("my-element", [
13648 fn: function(){ alert("Return was pressed"); }
13651 fn: function(){ alert('a, b or c was pressed'); }
13656 fn: function(){ alert('Control + shift + tab was pressed.'); }
13660 * <b>Note: A KeyMap starts enabled</b>
13662 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13663 * @param {Object} config The config (see {@link #addBinding})
13664 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13666 Roo.KeyMap = function(el, config, eventName){
13667 this.el = Roo.get(el);
13668 this.eventName = eventName || "keydown";
13669 this.bindings = [];
13671 this.addBinding(config);
13676 Roo.KeyMap.prototype = {
13678 * True to stop the event from bubbling and prevent the default browser action if the
13679 * key was handled by the KeyMap (defaults to false)
13685 * Add a new binding to this KeyMap. The following config object properties are supported:
13687 Property Type Description
13688 ---------- --------------- ----------------------------------------------------------------------
13689 key String/Array A single keycode or an array of keycodes to handle
13690 shift Boolean True to handle key only when shift is pressed (defaults to false)
13691 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13692 alt Boolean True to handle key only when alt is pressed (defaults to false)
13693 fn Function The function to call when KeyMap finds the expected key combination
13694 scope Object The scope of the callback function
13700 var map = new Roo.KeyMap(document, {
13701 key: Roo.EventObject.ENTER,
13706 //Add a new binding to the existing KeyMap later
13714 * @param {Object/Array} config A single KeyMap config or an array of configs
13716 addBinding : function(config){
13717 if(config instanceof Array){
13718 for(var i = 0, len = config.length; i < len; i++){
13719 this.addBinding(config[i]);
13723 var keyCode = config.key,
13724 shift = config.shift,
13725 ctrl = config.ctrl,
13728 scope = config.scope;
13729 if(typeof keyCode == "string"){
13731 var keyString = keyCode.toUpperCase();
13732 for(var j = 0, len = keyString.length; j < len; j++){
13733 ks.push(keyString.charCodeAt(j));
13737 var keyArray = keyCode instanceof Array;
13738 var handler = function(e){
13739 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13740 var k = e.getKey();
13742 for(var i = 0, len = keyCode.length; i < len; i++){
13743 if(keyCode[i] == k){
13744 if(this.stopEvent){
13747 fn.call(scope || window, k, e);
13753 if(this.stopEvent){
13756 fn.call(scope || window, k, e);
13761 this.bindings.push(handler);
13765 * Shorthand for adding a single key listener
13766 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13767 * following options:
13768 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13769 * @param {Function} fn The function to call
13770 * @param {Object} scope (optional) The scope of the function
13772 on : function(key, fn, scope){
13773 var keyCode, shift, ctrl, alt;
13774 if(typeof key == "object" && !(key instanceof Array)){
13793 handleKeyDown : function(e){
13794 if(this.enabled){ //just in case
13795 var b = this.bindings;
13796 for(var i = 0, len = b.length; i < len; i++){
13797 b[i].call(this, e);
13803 * Returns true if this KeyMap is enabled
13804 * @return {Boolean}
13806 isEnabled : function(){
13807 return this.enabled;
13811 * Enables this KeyMap
13813 enable: function(){
13815 this.el.on(this.eventName, this.handleKeyDown, this);
13816 this.enabled = true;
13821 * Disable this KeyMap
13823 disable: function(){
13825 this.el.removeListener(this.eventName, this.handleKeyDown, this);
13826 this.enabled = false;
13831 * Ext JS Library 1.1.1
13832 * Copyright(c) 2006-2007, Ext JS, LLC.
13834 * Originally Released Under LGPL - original licence link has changed is not relivant.
13837 * <script type="text/javascript">
13842 * @class Roo.util.TextMetrics
13843 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
13844 * wide, in pixels, a given block of text will be.
13847 Roo.util.TextMetrics = function(){
13851 * Measures the size of the specified text
13852 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
13853 * that can affect the size of the rendered text
13854 * @param {String} text The text to measure
13855 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13856 * in order to accurately measure the text height
13857 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13859 measure : function(el, text, fixedWidth){
13861 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
13864 shared.setFixedWidth(fixedWidth || 'auto');
13865 return shared.getSize(text);
13869 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
13870 * the overhead of multiple calls to initialize the style properties on each measurement.
13871 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
13872 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13873 * in order to accurately measure the text height
13874 * @return {Roo.util.TextMetrics.Instance} instance The new instance
13876 createInstance : function(el, fixedWidth){
13877 return Roo.util.TextMetrics.Instance(el, fixedWidth);
13884 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
13885 var ml = new Roo.Element(document.createElement('div'));
13886 document.body.appendChild(ml.dom);
13887 ml.position('absolute');
13888 ml.setLeftTop(-1000, -1000);
13892 ml.setWidth(fixedWidth);
13897 * Returns the size of the specified text based on the internal element's style and width properties
13898 * @memberOf Roo.util.TextMetrics.Instance#
13899 * @param {String} text The text to measure
13900 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13902 getSize : function(text){
13904 var s = ml.getSize();
13910 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
13911 * that can affect the size of the rendered text
13912 * @memberOf Roo.util.TextMetrics.Instance#
13913 * @param {String/HTMLElement} el The element, dom node or id
13915 bind : function(el){
13917 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
13922 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
13923 * to set a fixed width in order to accurately measure the text height.
13924 * @memberOf Roo.util.TextMetrics.Instance#
13925 * @param {Number} width The width to set on the element
13927 setFixedWidth : function(width){
13928 ml.setWidth(width);
13932 * Returns the measured width of the specified text
13933 * @memberOf Roo.util.TextMetrics.Instance#
13934 * @param {String} text The text to measure
13935 * @return {Number} width The width in pixels
13937 getWidth : function(text){
13938 ml.dom.style.width = 'auto';
13939 return this.getSize(text).width;
13943 * Returns the measured height of the specified text. For multiline text, be sure to call
13944 * {@link #setFixedWidth} if necessary.
13945 * @memberOf Roo.util.TextMetrics.Instance#
13946 * @param {String} text The text to measure
13947 * @return {Number} height The height in pixels
13949 getHeight : function(text){
13950 return this.getSize(text).height;
13954 instance.bind(bindTo);
13959 // backwards compat
13960 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
13962 * Ext JS Library 1.1.1
13963 * Copyright(c) 2006-2007, Ext JS, LLC.
13965 * Originally Released Under LGPL - original licence link has changed is not relivant.
13968 * <script type="text/javascript">
13972 * @class Roo.state.Provider
13973 * Abstract base class for state provider implementations. This class provides methods
13974 * for encoding and decoding <b>typed</b> variables including dates and defines the
13975 * Provider interface.
13977 Roo.state.Provider = function(){
13979 * @event statechange
13980 * Fires when a state change occurs.
13981 * @param {Provider} this This state provider
13982 * @param {String} key The state key which was changed
13983 * @param {String} value The encoded value for the state
13986 "statechange": true
13989 Roo.state.Provider.superclass.constructor.call(this);
13991 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
13993 * Returns the current value for a key
13994 * @param {String} name The key name
13995 * @param {Mixed} defaultValue A default value to return if the key's value is not found
13996 * @return {Mixed} The state data
13998 get : function(name, defaultValue){
13999 return typeof this.state[name] == "undefined" ?
14000 defaultValue : this.state[name];
14004 * Clears a value from the state
14005 * @param {String} name The key name
14007 clear : function(name){
14008 delete this.state[name];
14009 this.fireEvent("statechange", this, name, null);
14013 * Sets the value for a key
14014 * @param {String} name The key name
14015 * @param {Mixed} value The value to set
14017 set : function(name, value){
14018 this.state[name] = value;
14019 this.fireEvent("statechange", this, name, value);
14023 * Decodes a string previously encoded with {@link #encodeValue}.
14024 * @param {String} value The value to decode
14025 * @return {Mixed} The decoded value
14027 decodeValue : function(cookie){
14028 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14029 var matches = re.exec(unescape(cookie));
14030 if(!matches || !matches[1]) return; // non state cookie
14031 var type = matches[1];
14032 var v = matches[2];
14035 return parseFloat(v);
14037 return new Date(Date.parse(v));
14042 var values = v.split("^");
14043 for(var i = 0, len = values.length; i < len; i++){
14044 all.push(this.decodeValue(values[i]));
14049 var values = v.split("^");
14050 for(var i = 0, len = values.length; i < len; i++){
14051 var kv = values[i].split("=");
14052 all[kv[0]] = this.decodeValue(kv[1]);
14061 * Encodes a value including type information. Decode with {@link #decodeValue}.
14062 * @param {Mixed} value The value to encode
14063 * @return {String} The encoded value
14065 encodeValue : function(v){
14067 if(typeof v == "number"){
14069 }else if(typeof v == "boolean"){
14070 enc = "b:" + (v ? "1" : "0");
14071 }else if(v instanceof Date){
14072 enc = "d:" + v.toGMTString();
14073 }else if(v instanceof Array){
14075 for(var i = 0, len = v.length; i < len; i++){
14076 flat += this.encodeValue(v[i]);
14077 if(i != len-1) flat += "^";
14080 }else if(typeof v == "object"){
14083 if(typeof v[key] != "function"){
14084 flat += key + "=" + this.encodeValue(v[key]) + "^";
14087 enc = "o:" + flat.substring(0, flat.length-1);
14091 return escape(enc);
14097 * Ext JS Library 1.1.1
14098 * Copyright(c) 2006-2007, Ext JS, LLC.
14100 * Originally Released Under LGPL - original licence link has changed is not relivant.
14103 * <script type="text/javascript">
14106 * @class Roo.state.Manager
14107 * This is the global state manager. By default all components that are "state aware" check this class
14108 * for state information if you don't pass them a custom state provider. In order for this class
14109 * to be useful, it must be initialized with a provider when your application initializes.
14111 // in your initialization function
14113 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14115 // supposed you have a {@link Roo.BorderLayout}
14116 var layout = new Roo.BorderLayout(...);
14117 layout.restoreState();
14118 // or a {Roo.BasicDialog}
14119 var dialog = new Roo.BasicDialog(...);
14120 dialog.restoreState();
14124 Roo.state.Manager = function(){
14125 var provider = new Roo.state.Provider();
14129 * Configures the default state provider for your application
14130 * @param {Provider} stateProvider The state provider to set
14132 setProvider : function(stateProvider){
14133 provider = stateProvider;
14137 * Returns the current value for a key
14138 * @param {String} name The key name
14139 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14140 * @return {Mixed} The state data
14142 get : function(key, defaultValue){
14143 return provider.get(key, defaultValue);
14147 * Sets the value for a key
14148 * @param {String} name The key name
14149 * @param {Mixed} value The state data
14151 set : function(key, value){
14152 provider.set(key, value);
14156 * Clears a value from the state
14157 * @param {String} name The key name
14159 clear : function(key){
14160 provider.clear(key);
14164 * Gets the currently configured state provider
14165 * @return {Provider} The state provider
14167 getProvider : function(){
14174 * Ext JS Library 1.1.1
14175 * Copyright(c) 2006-2007, Ext JS, LLC.
14177 * Originally Released Under LGPL - original licence link has changed is not relivant.
14180 * <script type="text/javascript">
14183 * @class Roo.state.CookieProvider
14184 * @extends Roo.state.Provider
14185 * The default Provider implementation which saves state via cookies.
14188 var cp = new Roo.state.CookieProvider({
14190 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14191 domain: "roojs.com"
14193 Roo.state.Manager.setProvider(cp);
14195 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14196 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14197 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14198 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14199 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14200 * domain the page is running on including the 'www' like 'www.roojs.com')
14201 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14203 * Create a new CookieProvider
14204 * @param {Object} config The configuration object
14206 Roo.state.CookieProvider = function(config){
14207 Roo.state.CookieProvider.superclass.constructor.call(this);
14209 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14210 this.domain = null;
14211 this.secure = false;
14212 Roo.apply(this, config);
14213 this.state = this.readCookies();
14216 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14218 set : function(name, value){
14219 if(typeof value == "undefined" || value === null){
14223 this.setCookie(name, value);
14224 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14228 clear : function(name){
14229 this.clearCookie(name);
14230 Roo.state.CookieProvider.superclass.clear.call(this, name);
14234 readCookies : function(){
14236 var c = document.cookie + ";";
14237 var re = /\s?(.*?)=(.*?);/g;
14239 while((matches = re.exec(c)) != null){
14240 var name = matches[1];
14241 var value = matches[2];
14242 if(name && name.substring(0,3) == "ys-"){
14243 cookies[name.substr(3)] = this.decodeValue(value);
14250 setCookie : function(name, value){
14251 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14252 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14253 ((this.path == null) ? "" : ("; path=" + this.path)) +
14254 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14255 ((this.secure == true) ? "; secure" : "");
14259 clearCookie : function(name){
14260 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14261 ((this.path == null) ? "" : ("; path=" + this.path)) +
14262 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14263 ((this.secure == true) ? "; secure" : "");