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 (prop == 'float') {
7378 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7383 if(!(camel = propCache[prop])){
7384 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7387 if(camel == 'opacity') {
7388 this.setOpacity(value);
7390 this.dom.style[camel] = value;
7393 for(var style in prop){
7394 if(typeof prop[style] != "function"){
7395 this.setStyle(style, prop[style]);
7403 * More flexible version of {@link #setStyle} for setting style properties.
7404 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7405 * a function which returns such a specification.
7406 * @return {Roo.Element} this
7408 applyStyles : function(style){
7409 Roo.DomHelper.applyStyles(this.dom, style);
7414 * 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).
7415 * @return {Number} The X position of the element
7418 return D.getX(this.dom);
7422 * 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).
7423 * @return {Number} The Y position of the element
7426 return D.getY(this.dom);
7430 * 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).
7431 * @return {Array} The XY position of the element
7434 return D.getXY(this.dom);
7438 * 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).
7439 * @param {Number} The X position of the element
7440 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7441 * @return {Roo.Element} this
7443 setX : function(x, animate){
7445 D.setX(this.dom, x);
7447 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7453 * 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).
7454 * @param {Number} The Y position of the element
7455 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7456 * @return {Roo.Element} this
7458 setY : function(y, animate){
7460 D.setY(this.dom, y);
7462 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7468 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7469 * @param {String} left The left CSS property value
7470 * @return {Roo.Element} this
7472 setLeft : function(left){
7473 this.setStyle("left", this.addUnits(left));
7478 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7479 * @param {String} top The top CSS property value
7480 * @return {Roo.Element} this
7482 setTop : function(top){
7483 this.setStyle("top", this.addUnits(top));
7488 * Sets the element's CSS right style.
7489 * @param {String} right The right CSS property value
7490 * @return {Roo.Element} this
7492 setRight : function(right){
7493 this.setStyle("right", this.addUnits(right));
7498 * Sets the element's CSS bottom style.
7499 * @param {String} bottom The bottom CSS property value
7500 * @return {Roo.Element} this
7502 setBottom : function(bottom){
7503 this.setStyle("bottom", this.addUnits(bottom));
7508 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7509 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7510 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7511 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7512 * @return {Roo.Element} this
7514 setXY : function(pos, animate){
7516 D.setXY(this.dom, pos);
7518 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7524 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7525 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7526 * @param {Number} x X value for new position (coordinates are page-based)
7527 * @param {Number} y Y value for new position (coordinates are page-based)
7528 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7529 * @return {Roo.Element} this
7531 setLocation : function(x, y, animate){
7532 this.setXY([x, y], this.preanim(arguments, 2));
7537 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7538 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7539 * @param {Number} x X value for new position (coordinates are page-based)
7540 * @param {Number} y Y value for new position (coordinates are page-based)
7541 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7542 * @return {Roo.Element} this
7544 moveTo : function(x, y, animate){
7545 this.setXY([x, y], this.preanim(arguments, 2));
7550 * Returns the region of the given element.
7551 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7552 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7554 getRegion : function(){
7555 return D.getRegion(this.dom);
7559 * Returns the offset height of the element
7560 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7561 * @return {Number} The element's height
7563 getHeight : function(contentHeight){
7564 var h = this.dom.offsetHeight || 0;
7565 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7569 * Returns the offset width of the element
7570 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7571 * @return {Number} The element's width
7573 getWidth : function(contentWidth){
7574 var w = this.dom.offsetWidth || 0;
7575 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7579 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7580 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7581 * if a height has not been set using CSS.
7584 getComputedHeight : function(){
7585 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7587 h = parseInt(this.getStyle('height'), 10) || 0;
7588 if(!this.isBorderBox()){
7589 h += this.getFrameWidth('tb');
7596 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7597 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7598 * if a width has not been set using CSS.
7601 getComputedWidth : function(){
7602 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7604 w = parseInt(this.getStyle('width'), 10) || 0;
7605 if(!this.isBorderBox()){
7606 w += this.getFrameWidth('lr');
7613 * Returns the size of the element.
7614 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7615 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7617 getSize : function(contentSize){
7618 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7622 * Returns the width and height of the viewport.
7623 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7625 getViewSize : function(){
7626 var d = this.dom, doc = document, aw = 0, ah = 0;
7627 if(d == doc || d == doc.body){
7628 return {width : D.getViewWidth(), height: D.getViewHeight()};
7631 width : d.clientWidth,
7632 height: d.clientHeight
7638 * Returns the value of the "value" attribute
7639 * @param {Boolean} asNumber true to parse the value as a number
7640 * @return {String/Number}
7642 getValue : function(asNumber){
7643 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7647 adjustWidth : function(width){
7648 if(typeof width == "number"){
7649 if(this.autoBoxAdjust && !this.isBorderBox()){
7650 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7660 adjustHeight : function(height){
7661 if(typeof height == "number"){
7662 if(this.autoBoxAdjust && !this.isBorderBox()){
7663 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7673 * Set the width of the element
7674 * @param {Number} width The new width
7675 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7676 * @return {Roo.Element} this
7678 setWidth : function(width, animate){
7679 width = this.adjustWidth(width);
7681 this.dom.style.width = this.addUnits(width);
7683 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7689 * Set the height of the element
7690 * @param {Number} height The new height
7691 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7692 * @return {Roo.Element} this
7694 setHeight : function(height, animate){
7695 height = this.adjustHeight(height);
7697 this.dom.style.height = this.addUnits(height);
7699 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7705 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7706 * @param {Number} width The new width
7707 * @param {Number} height The new height
7708 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7709 * @return {Roo.Element} this
7711 setSize : function(width, height, animate){
7712 if(typeof width == "object"){ // in case of object from getSize()
7713 height = width.height; width = width.width;
7715 width = this.adjustWidth(width); height = this.adjustHeight(height);
7717 this.dom.style.width = this.addUnits(width);
7718 this.dom.style.height = this.addUnits(height);
7720 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7726 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7727 * @param {Number} x X value for new position (coordinates are page-based)
7728 * @param {Number} y Y value for new position (coordinates are page-based)
7729 * @param {Number} width The new width
7730 * @param {Number} height The new height
7731 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7732 * @return {Roo.Element} this
7734 setBounds : function(x, y, width, height, animate){
7736 this.setSize(width, height);
7737 this.setLocation(x, y);
7739 width = this.adjustWidth(width); height = this.adjustHeight(height);
7740 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7741 this.preanim(arguments, 4), 'motion');
7747 * 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.
7748 * @param {Roo.lib.Region} region The region to fill
7749 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7750 * @return {Roo.Element} this
7752 setRegion : function(region, animate){
7753 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7758 * Appends an event handler
7760 * @param {String} eventName The type of event to append
7761 * @param {Function} fn The method the event invokes
7762 * @param {Object} scope (optional) The scope (this object) of the fn
7763 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7765 addListener : function(eventName, fn, scope, options){
7766 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7770 * Removes an event handler from this element
7771 * @param {String} eventName the type of event to remove
7772 * @param {Function} fn the method the event invokes
7773 * @return {Roo.Element} this
7775 removeListener : function(eventName, fn){
7776 Roo.EventManager.removeListener(this.dom, eventName, fn);
7781 * Removes all previous added listeners from this element
7782 * @return {Roo.Element} this
7784 removeAllListeners : function(){
7785 E.purgeElement(this.dom);
7789 relayEvent : function(eventName, observable){
7790 this.on(eventName, function(e){
7791 observable.fireEvent(eventName, e);
7796 * Set the opacity of the element
7797 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7798 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7799 * @return {Roo.Element} this
7801 setOpacity : function(opacity, animate){
7803 var s = this.dom.style;
7806 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7807 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7809 s.opacity = opacity;
7812 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7818 * Gets the left X coordinate
7819 * @param {Boolean} local True to get the local css position instead of page coordinate
7822 getLeft : function(local){
7826 return parseInt(this.getStyle("left"), 10) || 0;
7831 * Gets the right X coordinate of the element (element X position + element width)
7832 * @param {Boolean} local True to get the local css position instead of page coordinate
7835 getRight : function(local){
7837 return this.getX() + this.getWidth();
7839 return (this.getLeft(true) + this.getWidth()) || 0;
7844 * Gets the top Y coordinate
7845 * @param {Boolean} local True to get the local css position instead of page coordinate
7848 getTop : function(local) {
7852 return parseInt(this.getStyle("top"), 10) || 0;
7857 * Gets the bottom Y coordinate of the element (element Y position + element height)
7858 * @param {Boolean} local True to get the local css position instead of page coordinate
7861 getBottom : function(local){
7863 return this.getY() + this.getHeight();
7865 return (this.getTop(true) + this.getHeight()) || 0;
7870 * Initializes positioning on this element. If a desired position is not passed, it will make the
7871 * the element positioned relative IF it is not already positioned.
7872 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7873 * @param {Number} zIndex (optional) The zIndex to apply
7874 * @param {Number} x (optional) Set the page X position
7875 * @param {Number} y (optional) Set the page Y position
7877 position : function(pos, zIndex, x, y){
7879 if(this.getStyle('position') == 'static'){
7880 this.setStyle('position', 'relative');
7883 this.setStyle("position", pos);
7886 this.setStyle("z-index", zIndex);
7888 if(x !== undefined && y !== undefined){
7890 }else if(x !== undefined){
7892 }else if(y !== undefined){
7898 * Clear positioning back to the default when the document was loaded
7899 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7900 * @return {Roo.Element} this
7902 clearPositioning : function(value){
7910 "position" : "static"
7916 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7917 * snapshot before performing an update and then restoring the element.
7920 getPositioning : function(){
7921 var l = this.getStyle("left");
7922 var t = this.getStyle("top");
7924 "position" : this.getStyle("position"),
7926 "right" : l ? "" : this.getStyle("right"),
7928 "bottom" : t ? "" : this.getStyle("bottom"),
7929 "z-index" : this.getStyle("z-index")
7934 * Gets the width of the border(s) for the specified side(s)
7935 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7936 * passing lr would get the border (l)eft width + the border (r)ight width.
7937 * @return {Number} The width of the sides passed added together
7939 getBorderWidth : function(side){
7940 return this.addStyles(side, El.borders);
7944 * Gets the width of the padding(s) for the specified side(s)
7945 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7946 * passing lr would get the padding (l)eft + the padding (r)ight.
7947 * @return {Number} The padding of the sides passed added together
7949 getPadding : function(side){
7950 return this.addStyles(side, El.paddings);
7954 * Set positioning with an object returned by getPositioning().
7955 * @param {Object} posCfg
7956 * @return {Roo.Element} this
7958 setPositioning : function(pc){
7959 this.applyStyles(pc);
7960 if(pc.right == "auto"){
7961 this.dom.style.right = "";
7963 if(pc.bottom == "auto"){
7964 this.dom.style.bottom = "";
7970 fixDisplay : function(){
7971 if(this.getStyle("display") == "none"){
7972 this.setStyle("visibility", "hidden");
7973 this.setStyle("display", this.originalDisplay); // first try reverting to default
7974 if(this.getStyle("display") == "none"){ // if that fails, default to block
7975 this.setStyle("display", "block");
7981 * Quick set left and top adding default units
7982 * @param {String} left The left CSS property value
7983 * @param {String} top The top CSS property value
7984 * @return {Roo.Element} this
7986 setLeftTop : function(left, top){
7987 this.dom.style.left = this.addUnits(left);
7988 this.dom.style.top = this.addUnits(top);
7993 * Move this element relative to its current position.
7994 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
7995 * @param {Number} distance How far to move the element in pixels
7996 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7997 * @return {Roo.Element} this
7999 move : function(direction, distance, animate){
8000 var xy = this.getXY();
8001 direction = direction.toLowerCase();
8005 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8009 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8014 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8019 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8026 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8027 * @return {Roo.Element} this
8030 if(!this.isClipped){
8031 this.isClipped = true;
8032 this.originalClip = {
8033 "o": this.getStyle("overflow"),
8034 "x": this.getStyle("overflow-x"),
8035 "y": this.getStyle("overflow-y")
8037 this.setStyle("overflow", "hidden");
8038 this.setStyle("overflow-x", "hidden");
8039 this.setStyle("overflow-y", "hidden");
8045 * Return clipping (overflow) to original clipping before clip() was called
8046 * @return {Roo.Element} this
8048 unclip : function(){
8050 this.isClipped = false;
8051 var o = this.originalClip;
8052 if(o.o){this.setStyle("overflow", o.o);}
8053 if(o.x){this.setStyle("overflow-x", o.x);}
8054 if(o.y){this.setStyle("overflow-y", o.y);}
8061 * Gets the x,y coordinates specified by the anchor position on the element.
8062 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8063 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8064 * {width: (target width), height: (target height)} (defaults to the element's current size)
8065 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8066 * @return {Array} [x, y] An array containing the element's x and y coordinates
8068 getAnchorXY : function(anchor, local, s){
8069 //Passing a different size is useful for pre-calculating anchors,
8070 //especially for anchored animations that change the el size.
8072 var w, h, vp = false;
8075 if(d == document.body || d == document){
8077 w = D.getViewWidth(); h = D.getViewHeight();
8079 w = this.getWidth(); h = this.getHeight();
8082 w = s.width; h = s.height;
8084 var x = 0, y = 0, r = Math.round;
8085 switch((anchor || "tl").toLowerCase()){
8127 var sc = this.getScroll();
8128 return [x + sc.left, y + sc.top];
8130 //Add the element's offset xy
8131 var o = this.getXY();
8132 return [x+o[0], y+o[1]];
8136 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8137 * supported position values.
8138 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8139 * @param {String} position The position to align to.
8140 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8141 * @return {Array} [x, y]
8143 getAlignToXY : function(el, p, o){
8147 throw "Element.alignTo with an element that doesn't exist";
8149 var c = false; //constrain to viewport
8150 var p1 = "", p2 = "";
8157 }else if(p.indexOf("-") == -1){
8160 p = p.toLowerCase();
8161 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8163 throw "Element.alignTo with an invalid alignment " + p;
8165 p1 = m[1]; p2 = m[2]; c = !!m[3];
8167 //Subtract the aligned el's internal xy from the target's offset xy
8168 //plus custom offset to get the aligned el's new offset xy
8169 var a1 = this.getAnchorXY(p1, true);
8170 var a2 = el.getAnchorXY(p2, false);
8171 var x = a2[0] - a1[0] + o[0];
8172 var y = a2[1] - a1[1] + o[1];
8174 //constrain the aligned el to viewport if necessary
8175 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8176 // 5px of margin for ie
8177 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8179 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8180 //perpendicular to the vp border, allow the aligned el to slide on that border,
8181 //otherwise swap the aligned el to the opposite border of the target.
8182 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8183 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8184 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8185 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8188 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8189 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8191 if((x+w) > dw + scrollX){
8192 x = swapX ? r.left-w : dw+scrollX-w;
8195 x = swapX ? r.right : scrollX;
8197 if((y+h) > dh + scrollY){
8198 y = swapY ? r.top-h : dh+scrollY-h;
8201 y = swapY ? r.bottom : scrollY;
8208 getConstrainToXY : function(){
8209 var os = {top:0, left:0, bottom:0, right: 0};
8211 return function(el, local, offsets, proposedXY){
8213 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8215 var vw, vh, vx = 0, vy = 0;
8216 if(el.dom == document.body || el.dom == document){
8217 vw = Roo.lib.Dom.getViewWidth();
8218 vh = Roo.lib.Dom.getViewHeight();
8220 vw = el.dom.clientWidth;
8221 vh = el.dom.clientHeight;
8223 var vxy = el.getXY();
8229 var s = el.getScroll();
8231 vx += offsets.left + s.left;
8232 vy += offsets.top + s.top;
8234 vw -= offsets.right;
8235 vh -= offsets.bottom;
8240 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8241 var x = xy[0], y = xy[1];
8242 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8244 // only move it if it needs it
8247 // first validate right/bottom
8256 // then make sure top/left isn't negative
8265 return moved ? [x, y] : false;
8270 adjustForConstraints : function(xy, parent, offsets){
8271 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8275 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8276 * document it aligns it to the viewport.
8277 * The position parameter is optional, and can be specified in any one of the following formats:
8279 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8280 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8281 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8282 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8283 * <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
8284 * element's anchor point, and the second value is used as the target's anchor point.</li>
8286 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8287 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8288 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8289 * that specified in order to enforce the viewport constraints.
8290 * Following are all of the supported anchor positions:
8293 ----- -----------------------------
8294 tl The top left corner (default)
8295 t The center of the top edge
8296 tr The top right corner
8297 l The center of the left edge
8298 c In the center of the element
8299 r The center of the right edge
8300 bl The bottom left corner
8301 b The center of the bottom edge
8302 br The bottom right corner
8306 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8307 el.alignTo("other-el");
8309 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8310 el.alignTo("other-el", "tr?");
8312 // align the bottom right corner of el with the center left edge of other-el
8313 el.alignTo("other-el", "br-l?");
8315 // align the center of el with the bottom left corner of other-el and
8316 // adjust the x position by -6 pixels (and the y position by 0)
8317 el.alignTo("other-el", "c-bl", [-6, 0]);
8319 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8320 * @param {String} position The position to align to.
8321 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8322 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8323 * @return {Roo.Element} this
8325 alignTo : function(element, position, offsets, animate){
8326 var xy = this.getAlignToXY(element, position, offsets);
8327 this.setXY(xy, this.preanim(arguments, 3));
8332 * Anchors an element to another element and realigns it when the window is resized.
8333 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8334 * @param {String} position The position to align to.
8335 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8336 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8337 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8338 * is a number, it is used as the buffer delay (defaults to 50ms).
8339 * @param {Function} callback The function to call after the animation finishes
8340 * @return {Roo.Element} this
8342 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8343 var action = function(){
8344 this.alignTo(el, alignment, offsets, animate);
8345 Roo.callback(callback, this);
8347 Roo.EventManager.onWindowResize(action, this);
8348 var tm = typeof monitorScroll;
8349 if(tm != 'undefined'){
8350 Roo.EventManager.on(window, 'scroll', action, this,
8351 {buffer: tm == 'number' ? monitorScroll : 50});
8353 action.call(this); // align immediately
8357 * Clears any opacity settings from this element. Required in some cases for IE.
8358 * @return {Roo.Element} this
8360 clearOpacity : function(){
8361 if (window.ActiveXObject) {
8362 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8363 this.dom.style.filter = "";
8366 this.dom.style.opacity = "";
8367 this.dom.style["-moz-opacity"] = "";
8368 this.dom.style["-khtml-opacity"] = "";
8374 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8375 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8376 * @return {Roo.Element} this
8378 hide : function(animate){
8379 this.setVisible(false, this.preanim(arguments, 0));
8384 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8385 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8386 * @return {Roo.Element} this
8388 show : function(animate){
8389 this.setVisible(true, this.preanim(arguments, 0));
8394 * @private Test if size has a unit, otherwise appends the default
8396 addUnits : function(size){
8397 return Roo.Element.addUnits(size, this.defaultUnit);
8401 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8402 * @return {Roo.Element} this
8404 beginMeasure : function(){
8406 if(el.offsetWidth || el.offsetHeight){
8407 return this; // offsets work already
8410 var p = this.dom, b = document.body; // start with this element
8411 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8412 var pe = Roo.get(p);
8413 if(pe.getStyle('display') == 'none'){
8414 changed.push({el: p, visibility: pe.getStyle("visibility")});
8415 p.style.visibility = "hidden";
8416 p.style.display = "block";
8420 this._measureChanged = changed;
8426 * Restores displays to before beginMeasure was called
8427 * @return {Roo.Element} this
8429 endMeasure : function(){
8430 var changed = this._measureChanged;
8432 for(var i = 0, len = changed.length; i < len; i++) {
8434 r.el.style.visibility = r.visibility;
8435 r.el.style.display = "none";
8437 this._measureChanged = null;
8443 * Update the innerHTML of this element, optionally searching for and processing scripts
8444 * @param {String} html The new HTML
8445 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8446 * @param {Function} callback For async script loading you can be noticed when the update completes
8447 * @return {Roo.Element} this
8449 update : function(html, loadScripts, callback){
8450 if(typeof html == "undefined"){
8453 if(loadScripts !== true){
8454 this.dom.innerHTML = html;
8455 if(typeof callback == "function"){
8463 html += '<span id="' + id + '"></span>';
8465 E.onAvailable(id, function(){
8466 var hd = document.getElementsByTagName("head")[0];
8467 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8468 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8469 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8472 while(match = re.exec(html)){
8473 var attrs = match[1];
8474 var srcMatch = attrs ? attrs.match(srcRe) : false;
8475 if(srcMatch && srcMatch[2]){
8476 var s = document.createElement("script");
8477 s.src = srcMatch[2];
8478 var typeMatch = attrs.match(typeRe);
8479 if(typeMatch && typeMatch[2]){
8480 s.type = typeMatch[2];
8483 }else if(match[2] && match[2].length > 0){
8484 if(window.execScript) {
8485 window.execScript(match[2]);
8493 window.eval(match[2]);
8497 var el = document.getElementById(id);
8498 if(el){el.parentNode.removeChild(el);}
8499 if(typeof callback == "function"){
8503 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8508 * Direct access to the UpdateManager update() method (takes the same parameters).
8509 * @param {String/Function} url The url for this request or a function to call to get the url
8510 * @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}
8511 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8512 * @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.
8513 * @return {Roo.Element} this
8516 var um = this.getUpdateManager();
8517 um.update.apply(um, arguments);
8522 * Gets this element's UpdateManager
8523 * @return {Roo.UpdateManager} The UpdateManager
8525 getUpdateManager : function(){
8526 if(!this.updateManager){
8527 this.updateManager = new Roo.UpdateManager(this);
8529 return this.updateManager;
8533 * Disables text selection for this element (normalized across browsers)
8534 * @return {Roo.Element} this
8536 unselectable : function(){
8537 this.dom.unselectable = "on";
8538 this.swallowEvent("selectstart", true);
8539 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8540 this.addClass("x-unselectable");
8545 * Calculates the x, y to center this element on the screen
8546 * @return {Array} The x, y values [x, y]
8548 getCenterXY : function(){
8549 return this.getAlignToXY(document, 'c-c');
8553 * Centers the Element in either the viewport, or another Element.
8554 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8556 center : function(centerIn){
8557 this.alignTo(centerIn || document, 'c-c');
8562 * Tests various css rules/browsers to determine if this element uses a border box
8565 isBorderBox : function(){
8566 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8570 * Return a box {x, y, width, height} that can be used to set another elements
8571 * size/location to match this element.
8572 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8573 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8574 * @return {Object} box An object in the format {x, y, width, height}
8576 getBox : function(contentBox, local){
8581 var left = parseInt(this.getStyle("left"), 10) || 0;
8582 var top = parseInt(this.getStyle("top"), 10) || 0;
8585 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8587 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8589 var l = this.getBorderWidth("l")+this.getPadding("l");
8590 var r = this.getBorderWidth("r")+this.getPadding("r");
8591 var t = this.getBorderWidth("t")+this.getPadding("t");
8592 var b = this.getBorderWidth("b")+this.getPadding("b");
8593 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)};
8595 bx.right = bx.x + bx.width;
8596 bx.bottom = bx.y + bx.height;
8601 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8602 for more information about the sides.
8603 * @param {String} sides
8606 getFrameWidth : function(sides, onlyContentBox){
8607 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8611 * 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.
8612 * @param {Object} box The box to fill {x, y, width, height}
8613 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8614 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8615 * @return {Roo.Element} this
8617 setBox : function(box, adjust, animate){
8618 var w = box.width, h = box.height;
8619 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8620 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8621 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8623 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8628 * Forces the browser to repaint this element
8629 * @return {Roo.Element} this
8631 repaint : function(){
8633 this.addClass("x-repaint");
8634 setTimeout(function(){
8635 Roo.get(dom).removeClass("x-repaint");
8641 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8642 * then it returns the calculated width of the sides (see getPadding)
8643 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8644 * @return {Object/Number}
8646 getMargins : function(side){
8649 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8650 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8651 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8652 right: parseInt(this.getStyle("margin-right"), 10) || 0
8655 return this.addStyles(side, El.margins);
8660 addStyles : function(sides, styles){
8662 for(var i = 0, len = sides.length; i < len; i++){
8663 v = this.getStyle(styles[sides.charAt(i)]);
8665 w = parseInt(v, 10);
8673 * Creates a proxy element of this element
8674 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8675 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8676 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8677 * @return {Roo.Element} The new proxy element
8679 createProxy : function(config, renderTo, matchBox){
8681 renderTo = Roo.getDom(renderTo);
8683 renderTo = document.body;
8685 config = typeof config == "object" ?
8686 config : {tag : "div", cls: config};
8687 var proxy = Roo.DomHelper.append(renderTo, config, true);
8689 proxy.setBox(this.getBox());
8695 * Puts a mask over this element to disable user interaction. Requires core.css.
8696 * This method can only be applied to elements which accept child nodes.
8697 * @param {String} msg (optional) A message to display in the mask
8698 * @param {String} msgCls (optional) A css class to apply to the msg element
8699 * @return {Element} The mask element
8701 mask : function(msg, msgCls){
8702 if(this.getStyle("position") == "static"){
8703 this.setStyle("position", "relative");
8706 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8708 this.addClass("x-masked");
8709 this._mask.setDisplayed(true);
8710 if(typeof msg == 'string'){
8712 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8714 var mm = this._maskMsg;
8715 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8716 mm.dom.firstChild.innerHTML = msg;
8717 mm.setDisplayed(true);
8720 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8721 this._mask.setHeight(this.getHeight());
8727 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8728 * it is cached for reuse.
8730 unmask : function(removeEl){
8732 if(removeEl === true){
8733 this._mask.remove();
8736 this._maskMsg.remove();
8737 delete this._maskMsg;
8740 this._mask.setDisplayed(false);
8742 this._maskMsg.setDisplayed(false);
8746 this.removeClass("x-masked");
8750 * Returns true if this element is masked
8753 isMasked : function(){
8754 return this._mask && this._mask.isVisible();
8758 * Creates an iframe shim for this element to keep selects and other windowed objects from
8760 * @return {Roo.Element} The new shim element
8762 createShim : function(){
8763 var el = document.createElement('iframe');
8764 el.frameBorder = 'no';
8765 el.className = 'roo-shim';
8766 if(Roo.isIE && Roo.isSecure){
8767 el.src = Roo.SSL_SECURE_URL;
8769 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8770 shim.autoBoxAdjust = false;
8775 * Removes this element from the DOM and deletes it from the cache
8777 remove : function(){
8778 if(this.dom.parentNode){
8779 this.dom.parentNode.removeChild(this.dom);
8781 delete El.cache[this.dom.id];
8785 * Sets up event handlers to add and remove a css class when the mouse is over this element
8786 * @param {String} className
8787 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8788 * mouseout events for children elements
8789 * @return {Roo.Element} this
8791 addClassOnOver : function(className, preventFlicker){
8792 this.on("mouseover", function(){
8793 Roo.fly(this, '_internal').addClass(className);
8795 var removeFn = function(e){
8796 if(preventFlicker !== true || !e.within(this, true)){
8797 Roo.fly(this, '_internal').removeClass(className);
8800 this.on("mouseout", removeFn, this.dom);
8805 * Sets up event handlers to add and remove a css class when this element has the focus
8806 * @param {String} className
8807 * @return {Roo.Element} this
8809 addClassOnFocus : function(className){
8810 this.on("focus", function(){
8811 Roo.fly(this, '_internal').addClass(className);
8813 this.on("blur", function(){
8814 Roo.fly(this, '_internal').removeClass(className);
8819 * 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)
8820 * @param {String} className
8821 * @return {Roo.Element} this
8823 addClassOnClick : function(className){
8825 this.on("mousedown", function(){
8826 Roo.fly(dom, '_internal').addClass(className);
8827 var d = Roo.get(document);
8828 var fn = function(){
8829 Roo.fly(dom, '_internal').removeClass(className);
8830 d.removeListener("mouseup", fn);
8832 d.on("mouseup", fn);
8838 * Stops the specified event from bubbling and optionally prevents the default action
8839 * @param {String} eventName
8840 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8841 * @return {Roo.Element} this
8843 swallowEvent : function(eventName, preventDefault){
8844 var fn = function(e){
8845 e.stopPropagation();
8850 if(eventName instanceof Array){
8851 for(var i = 0, len = eventName.length; i < len; i++){
8852 this.on(eventName[i], fn);
8856 this.on(eventName, fn);
8863 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8866 * Sizes this element to its parent element's dimensions performing
8867 * neccessary box adjustments.
8868 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8869 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8870 * @return {Roo.Element} this
8872 fitToParent : function(monitorResize, targetParent) {
8873 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8874 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8875 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8878 var p = Roo.get(targetParent || this.dom.parentNode);
8879 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8880 if (monitorResize === true) {
8881 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8882 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8888 * Gets the next sibling, skipping text nodes
8889 * @return {HTMLElement} The next sibling or null
8891 getNextSibling : function(){
8892 var n = this.dom.nextSibling;
8893 while(n && n.nodeType != 1){
8900 * Gets the previous sibling, skipping text nodes
8901 * @return {HTMLElement} The previous sibling or null
8903 getPrevSibling : function(){
8904 var n = this.dom.previousSibling;
8905 while(n && n.nodeType != 1){
8906 n = n.previousSibling;
8913 * Appends the passed element(s) to this element
8914 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8915 * @return {Roo.Element} this
8917 appendChild: function(el){
8924 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8925 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8926 * automatically generated with the specified attributes.
8927 * @param {HTMLElement} insertBefore (optional) a child element of this element
8928 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8929 * @return {Roo.Element} The new child element
8931 createChild: function(config, insertBefore, returnDom){
8932 config = config || {tag:'div'};
8934 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8936 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8940 * Appends this element to the passed element
8941 * @param {String/HTMLElement/Element} el The new parent element
8942 * @return {Roo.Element} this
8944 appendTo: function(el){
8945 el = Roo.getDom(el);
8946 el.appendChild(this.dom);
8951 * Inserts this element before the passed element in the DOM
8952 * @param {String/HTMLElement/Element} el The element to insert before
8953 * @return {Roo.Element} this
8955 insertBefore: function(el){
8956 el = Roo.getDom(el);
8957 el.parentNode.insertBefore(this.dom, el);
8962 * Inserts this element after the passed element in the DOM
8963 * @param {String/HTMLElement/Element} el The element to insert after
8964 * @return {Roo.Element} this
8966 insertAfter: function(el){
8967 el = Roo.getDom(el);
8968 el.parentNode.insertBefore(this.dom, el.nextSibling);
8973 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
8974 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8975 * @return {Roo.Element} The new child
8977 insertFirst: function(el, returnDom){
8979 if(typeof el == 'object' && !el.nodeType){ // dh config
8980 return this.createChild(el, this.dom.firstChild, returnDom);
8982 el = Roo.getDom(el);
8983 this.dom.insertBefore(el, this.dom.firstChild);
8984 return !returnDom ? Roo.get(el) : el;
8989 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
8990 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8991 * @param {String} where (optional) 'before' or 'after' defaults to before
8992 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8993 * @return {Roo.Element} the inserted Element
8995 insertSibling: function(el, where, returnDom){
8996 where = where ? where.toLowerCase() : 'before';
8998 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9000 if(typeof el == 'object' && !el.nodeType){ // dh config
9001 if(where == 'after' && !this.dom.nextSibling){
9002 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9004 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9008 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9009 where == 'before' ? this.dom : this.dom.nextSibling);
9018 * Creates and wraps this element with another element
9019 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9020 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9021 * @return {HTMLElement/Element} The newly created wrapper element
9023 wrap: function(config, returnDom){
9025 config = {tag: "div"};
9027 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9028 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9033 * Replaces the passed element with this element
9034 * @param {String/HTMLElement/Element} el The element to replace
9035 * @return {Roo.Element} this
9037 replace: function(el){
9039 this.insertBefore(el);
9045 * Inserts an html fragment into this element
9046 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9047 * @param {String} html The HTML fragment
9048 * @param {Boolean} returnEl True to return an Roo.Element
9049 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9051 insertHtml : function(where, html, returnEl){
9052 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9053 return returnEl ? Roo.get(el) : el;
9057 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9058 * @param {Object} o The object with the attributes
9059 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9060 * @return {Roo.Element} this
9062 set : function(o, useSet){
9064 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9066 if(attr == "style" || typeof o[attr] == "function") continue;
9068 el.className = o["cls"];
9070 if(useSet) el.setAttribute(attr, o[attr]);
9071 else el[attr] = o[attr];
9075 Roo.DomHelper.applyStyles(el, o.style);
9081 * Convenience method for constructing a KeyMap
9082 * @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:
9083 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9084 * @param {Function} fn The function to call
9085 * @param {Object} scope (optional) The scope of the function
9086 * @return {Roo.KeyMap} The KeyMap created
9088 addKeyListener : function(key, fn, scope){
9090 if(typeof key != "object" || key instanceof Array){
9106 return new Roo.KeyMap(this, config);
9110 * Creates a KeyMap for this element
9111 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9112 * @return {Roo.KeyMap} The KeyMap created
9114 addKeyMap : function(config){
9115 return new Roo.KeyMap(this, config);
9119 * Returns true if this element is scrollable.
9122 isScrollable : function(){
9124 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9128 * 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().
9129 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9130 * @param {Number} value The new scroll value
9131 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9132 * @return {Element} this
9135 scrollTo : function(side, value, animate){
9136 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9138 this.dom[prop] = value;
9140 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9141 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9147 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9148 * within this element's scrollable range.
9149 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9150 * @param {Number} distance How far to scroll the element in pixels
9151 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9152 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9153 * was scrolled as far as it could go.
9155 scroll : function(direction, distance, animate){
9156 if(!this.isScrollable()){
9160 var l = el.scrollLeft, t = el.scrollTop;
9161 var w = el.scrollWidth, h = el.scrollHeight;
9162 var cw = el.clientWidth, ch = el.clientHeight;
9163 direction = direction.toLowerCase();
9164 var scrolled = false;
9165 var a = this.preanim(arguments, 2);
9170 var v = Math.min(l + distance, w-cw);
9171 this.scrollTo("left", v, a);
9178 var v = Math.max(l - distance, 0);
9179 this.scrollTo("left", v, a);
9187 var v = Math.max(t - distance, 0);
9188 this.scrollTo("top", v, a);
9196 var v = Math.min(t + distance, h-ch);
9197 this.scrollTo("top", v, a);
9206 * Translates the passed page coordinates into left/top css values for this element
9207 * @param {Number/Array} x The page x or an array containing [x, y]
9208 * @param {Number} y The page y
9209 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9211 translatePoints : function(x, y){
9212 if(typeof x == 'object' || x instanceof Array){
9215 var p = this.getStyle('position');
9216 var o = this.getXY();
9218 var l = parseInt(this.getStyle('left'), 10);
9219 var t = parseInt(this.getStyle('top'), 10);
9222 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9225 t = (p == "relative") ? 0 : this.dom.offsetTop;
9228 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9232 * Returns the current scroll position of the element.
9233 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9235 getScroll : function(){
9236 var d = this.dom, doc = document;
9237 if(d == doc || d == doc.body){
9238 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9239 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9240 return {left: l, top: t};
9242 return {left: d.scrollLeft, top: d.scrollTop};
9247 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9248 * are convert to standard 6 digit hex color.
9249 * @param {String} attr The css attribute
9250 * @param {String} defaultValue The default value to use when a valid color isn't found
9251 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9254 getColor : function(attr, defaultValue, prefix){
9255 var v = this.getStyle(attr);
9256 if(!v || v == "transparent" || v == "inherit") {
9257 return defaultValue;
9259 var color = typeof prefix == "undefined" ? "#" : prefix;
9260 if(v.substr(0, 4) == "rgb("){
9261 var rvs = v.slice(4, v.length -1).split(",");
9262 for(var i = 0; i < 3; i++){
9263 var h = parseInt(rvs[i]).toString(16);
9270 if(v.substr(0, 1) == "#"){
9272 for(var i = 1; i < 4; i++){
9273 var c = v.charAt(i);
9276 }else if(v.length == 7){
9277 color += v.substr(1);
9281 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9285 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9286 * gradient background, rounded corners and a 4-way shadow.
9287 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9288 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9289 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9290 * @return {Roo.Element} this
9292 boxWrap : function(cls){
9293 cls = cls || 'x-box';
9294 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9295 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9300 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9301 * @param {String} namespace The namespace in which to look for the attribute
9302 * @param {String} name The attribute name
9303 * @return {String} The attribute value
9305 getAttributeNS : Roo.isIE ? function(ns, name){
9307 var type = typeof d[ns+":"+name];
9308 if(type != 'undefined' && type != 'unknown'){
9309 return d[ns+":"+name];
9312 } : function(ns, name){
9314 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9318 var ep = El.prototype;
9321 * Appends an event handler (Shorthand for addListener)
9322 * @param {String} eventName The type of event to append
9323 * @param {Function} fn The method the event invokes
9324 * @param {Object} scope (optional) The scope (this object) of the fn
9325 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9328 ep.on = ep.addListener;
9330 ep.mon = ep.addListener;
9333 * Removes an event handler from this element (shorthand for removeListener)
9334 * @param {String} eventName the type of event to remove
9335 * @param {Function} fn the method the event invokes
9336 * @return {Roo.Element} this
9339 ep.un = ep.removeListener;
9342 * true to automatically adjust width and height settings for box-model issues (default to true)
9344 ep.autoBoxAdjust = true;
9347 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9350 El.addUnits = function(v, defaultUnit){
9351 if(v === "" || v == "auto"){
9354 if(v === undefined){
9357 if(typeof v == "number" || !El.unitPattern.test(v)){
9358 return v + (defaultUnit || 'px');
9363 // special markup used throughout Roo when box wrapping elements
9364 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>';
9366 * Visibility mode constant - Use visibility to hide element
9372 * Visibility mode constant - Use display to hide element
9378 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9379 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9380 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9392 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9393 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9394 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9395 * @return {Element} The Element object
9398 El.get = function(el){
9400 if(!el){ return null; }
9401 if(typeof el == "string"){ // element id
9402 if(!(elm = document.getElementById(el))){
9405 if(ex = El.cache[el]){
9408 ex = El.cache[el] = new El(elm);
9411 }else if(el.tagName){ // dom element
9415 if(ex = El.cache[id]){
9418 ex = El.cache[id] = new El(el);
9421 }else if(el instanceof El){
9423 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9424 // catch case where it hasn't been appended
9425 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9428 }else if(el.isComposite){
9430 }else if(el instanceof Array){
9431 return El.select(el);
9432 }else if(el == document){
9433 // create a bogus element object representing the document object
9435 var f = function(){};
9436 f.prototype = El.prototype;
9438 docEl.dom = document;
9446 El.uncache = function(el){
9447 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9449 delete El.cache[a[i].id || a[i]];
9455 // Garbage collection - uncache elements/purge listeners on orphaned elements
9456 // so we don't hold a reference and cause the browser to retain them
9457 El.garbageCollect = function(){
9458 if(!Roo.enableGarbageCollector){
9459 clearInterval(El.collectorThread);
9462 for(var eid in El.cache){
9463 var el = El.cache[eid], d = el.dom;
9464 // -------------------------------------------------------
9465 // Determining what is garbage:
9466 // -------------------------------------------------------
9468 // dom node is null, definitely garbage
9469 // -------------------------------------------------------
9471 // no parentNode == direct orphan, definitely garbage
9472 // -------------------------------------------------------
9473 // !d.offsetParent && !document.getElementById(eid)
9474 // display none elements have no offsetParent so we will
9475 // also try to look it up by it's id. However, check
9476 // offsetParent first so we don't do unneeded lookups.
9477 // This enables collection of elements that are not orphans
9478 // directly, but somewhere up the line they have an orphan
9480 // -------------------------------------------------------
9481 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9482 delete El.cache[eid];
9483 if(d && Roo.enableListenerCollection){
9489 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9493 El.Flyweight = function(dom){
9496 El.Flyweight.prototype = El.prototype;
9498 El._flyweights = {};
9500 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9501 * the dom node can be overwritten by other code.
9502 * @param {String/HTMLElement} el The dom node or id
9503 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9504 * prevent conflicts (e.g. internally Roo uses "_internal")
9506 * @return {Element} The shared Element object
9508 El.fly = function(el, named){
9509 named = named || '_global';
9510 el = Roo.getDom(el);
9514 if(!El._flyweights[named]){
9515 El._flyweights[named] = new El.Flyweight();
9517 El._flyweights[named].dom = el;
9518 return El._flyweights[named];
9522 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9523 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9524 * Shorthand of {@link Roo.Element#get}
9525 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9526 * @return {Element} The Element object
9532 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9533 * the dom node can be overwritten by other code.
9534 * Shorthand of {@link Roo.Element#fly}
9535 * @param {String/HTMLElement} el The dom node or id
9536 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9537 * prevent conflicts (e.g. internally Roo uses "_internal")
9539 * @return {Element} The shared Element object
9545 // speedy lookup for elements never to box adjust
9546 var noBoxAdjust = Roo.isStrict ? {
9549 input:1, select:1, textarea:1
9551 if(Roo.isIE || Roo.isGecko){
9552 noBoxAdjust['button'] = 1;
9556 Roo.EventManager.on(window, 'unload', function(){
9558 delete El._flyweights;
9566 Roo.Element.selectorFunction = Roo.DomQuery.select;
9569 Roo.Element.select = function(selector, unique, root){
9571 if(typeof selector == "string"){
9572 els = Roo.Element.selectorFunction(selector, root);
9573 }else if(selector.length !== undefined){
9576 throw "Invalid selector";
9578 if(unique === true){
9579 return new Roo.CompositeElement(els);
9581 return new Roo.CompositeElementLite(els);
9585 * Selects elements based on the passed CSS selector to enable working on them as 1.
9586 * @param {String/Array} selector The CSS selector or an array of elements
9587 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9588 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9589 * @return {CompositeElementLite/CompositeElement}
9593 Roo.select = Roo.Element.select;
9610 * Ext JS Library 1.1.1
9611 * Copyright(c) 2006-2007, Ext JS, LLC.
9613 * Originally Released Under LGPL - original licence link has changed is not relivant.
9616 * <script type="text/javascript">
9621 //Notifies Element that fx methods are available
9622 Roo.enableFx = true;
9626 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9627 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9628 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9629 * Element effects to work.</p><br/>
9631 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9632 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9633 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9634 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9635 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9636 * expected results and should be done with care.</p><br/>
9638 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9639 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9642 ----- -----------------------------
9643 tl The top left corner
9644 t The center of the top edge
9645 tr The top right corner
9646 l The center of the left edge
9647 r The center of the right edge
9648 bl The bottom left corner
9649 b The center of the bottom edge
9650 br The bottom right corner
9652 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9653 * below are common options that can be passed to any Fx method.</b>
9654 * @cfg {Function} callback A function called when the effect is finished
9655 * @cfg {Object} scope The scope of the effect function
9656 * @cfg {String} easing A valid Easing value for the effect
9657 * @cfg {String} afterCls A css class to apply after the effect
9658 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9659 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9660 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9661 * effects that end with the element being visually hidden, ignored otherwise)
9662 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9663 * a function which returns such a specification that will be applied to the Element after the effect finishes
9664 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9665 * @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
9666 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9670 * Slides the element into view. An anchor point can be optionally passed to set the point of
9671 * origin for the slide effect. This function automatically handles wrapping the element with
9672 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9675 // default: slide the element in from the top
9678 // custom: slide the element in from the right with a 2-second duration
9679 el.slideIn('r', { duration: 2 });
9681 // common config options shown with default values
9687 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9688 * @param {Object} options (optional) Object literal with any of the Fx config options
9689 * @return {Roo.Element} The Element
9691 slideIn : function(anchor, o){
9692 var el = this.getFxEl();
9695 el.queueFx(o, function(){
9697 anchor = anchor || "t";
9699 // fix display to visibility
9702 // restore values after effect
9703 var r = this.getFxRestore();
9704 var b = this.getBox();
9705 // fixed size for slide
9709 var wrap = this.fxWrap(r.pos, o, "hidden");
9711 var st = this.dom.style;
9712 st.visibility = "visible";
9713 st.position = "absolute";
9715 // clear out temp styles after slide and unwrap
9716 var after = function(){
9717 el.fxUnwrap(wrap, r.pos, o);
9719 st.height = r.height;
9722 // time to calc the positions
9723 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9725 switch(anchor.toLowerCase()){
9727 wrap.setSize(b.width, 0);
9728 st.left = st.bottom = "0";
9732 wrap.setSize(0, b.height);
9733 st.right = st.top = "0";
9737 wrap.setSize(0, b.height);
9739 st.left = st.top = "0";
9740 a = {width: bw, points: pt};
9743 wrap.setSize(b.width, 0);
9744 wrap.setY(b.bottom);
9745 st.left = st.top = "0";
9746 a = {height: bh, points: pt};
9750 st.right = st.bottom = "0";
9751 a = {width: bw, height: bh};
9755 wrap.setY(b.y+b.height);
9756 st.right = st.top = "0";
9757 a = {width: bw, height: bh, points: pt};
9761 wrap.setXY([b.right, b.bottom]);
9762 st.left = st.top = "0";
9763 a = {width: bw, height: bh, points: pt};
9767 wrap.setX(b.x+b.width);
9768 st.left = st.bottom = "0";
9769 a = {width: bw, height: bh, points: pt};
9772 this.dom.style.visibility = "visible";
9775 arguments.callee.anim = wrap.fxanim(a,
9785 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9786 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9787 * 'hidden') but block elements will still take up space in the document. The element must be removed
9788 * from the DOM using the 'remove' config option if desired. This function automatically handles
9789 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9792 // default: slide the element out to the top
9795 // custom: slide the element out to the right with a 2-second duration
9796 el.slideOut('r', { duration: 2 });
9798 // common config options shown with default values
9806 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9807 * @param {Object} options (optional) Object literal with any of the Fx config options
9808 * @return {Roo.Element} The Element
9810 slideOut : function(anchor, o){
9811 var el = this.getFxEl();
9814 el.queueFx(o, function(){
9816 anchor = anchor || "t";
9818 // restore values after effect
9819 var r = this.getFxRestore();
9821 var b = this.getBox();
9822 // fixed size for slide
9826 var wrap = this.fxWrap(r.pos, o, "visible");
9828 var st = this.dom.style;
9829 st.visibility = "visible";
9830 st.position = "absolute";
9834 var after = function(){
9836 el.setDisplayed(false);
9841 el.fxUnwrap(wrap, r.pos, o);
9844 st.height = r.height;
9849 var a, zero = {to: 0};
9850 switch(anchor.toLowerCase()){
9852 st.left = st.bottom = "0";
9856 st.right = st.top = "0";
9860 st.left = st.top = "0";
9861 a = {width: zero, points: {to:[b.right, b.y]}};
9864 st.left = st.top = "0";
9865 a = {height: zero, points: {to:[b.x, b.bottom]}};
9868 st.right = st.bottom = "0";
9869 a = {width: zero, height: zero};
9872 st.right = st.top = "0";
9873 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9876 st.left = st.top = "0";
9877 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9880 st.left = st.bottom = "0";
9881 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9885 arguments.callee.anim = wrap.fxanim(a,
9895 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
9896 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
9897 * The element must be removed from the DOM using the 'remove' config option if desired.
9903 // common config options shown with default values
9911 * @param {Object} options (optional) Object literal with any of the Fx config options
9912 * @return {Roo.Element} The Element
9915 var el = this.getFxEl();
9918 el.queueFx(o, function(){
9919 this.clearOpacity();
9922 // restore values after effect
9923 var r = this.getFxRestore();
9924 var st = this.dom.style;
9926 var after = function(){
9928 el.setDisplayed(false);
9935 el.setPositioning(r.pos);
9937 st.height = r.height;
9942 var width = this.getWidth();
9943 var height = this.getHeight();
9945 arguments.callee.anim = this.fxanim({
9946 width : {to: this.adjustWidth(width * 2)},
9947 height : {to: this.adjustHeight(height * 2)},
9948 points : {by: [-(width * .5), -(height * .5)]},
9950 fontSize: {to:200, unit: "%"}
9961 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
9962 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
9963 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
9969 // all config options shown with default values
9977 * @param {Object} options (optional) Object literal with any of the Fx config options
9978 * @return {Roo.Element} The Element
9980 switchOff : function(o){
9981 var el = this.getFxEl();
9984 el.queueFx(o, function(){
9985 this.clearOpacity();
9988 // restore values after effect
9989 var r = this.getFxRestore();
9990 var st = this.dom.style;
9992 var after = function(){
9994 el.setDisplayed(false);
10000 el.setPositioning(r.pos);
10001 st.width = r.width;
10002 st.height = r.height;
10007 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10008 this.clearOpacity();
10012 points:{by:[0, this.getHeight() * .5]}
10013 }, o, 'motion', 0.3, 'easeIn', after);
10014 }).defer(100, this);
10021 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10022 * changed using the "attr" config option) and then fading back to the original color. If no original
10023 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10026 // default: highlight background to yellow
10029 // custom: highlight foreground text to blue for 2 seconds
10030 el.highlight("0000ff", { attr: 'color', duration: 2 });
10032 // common config options shown with default values
10033 el.highlight("ffff9c", {
10034 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10035 endColor: (current color) or "ffffff",
10040 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10041 * @param {Object} options (optional) Object literal with any of the Fx config options
10042 * @return {Roo.Element} The Element
10044 highlight : function(color, o){
10045 var el = this.getFxEl();
10048 el.queueFx(o, function(){
10049 color = color || "ffff9c";
10050 attr = o.attr || "backgroundColor";
10052 this.clearOpacity();
10055 var origColor = this.getColor(attr);
10056 var restoreColor = this.dom.style[attr];
10057 endColor = (o.endColor || origColor) || "ffffff";
10059 var after = function(){
10060 el.dom.style[attr] = restoreColor;
10065 a[attr] = {from: color, to: endColor};
10066 arguments.callee.anim = this.fxanim(a,
10076 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10079 // default: a single light blue ripple
10082 // custom: 3 red ripples lasting 3 seconds total
10083 el.frame("ff0000", 3, { duration: 3 });
10085 // common config options shown with default values
10086 el.frame("C3DAF9", 1, {
10087 duration: 1 //duration of entire animation (not each individual ripple)
10088 // Note: Easing is not configurable and will be ignored if included
10091 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10092 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10093 * @param {Object} options (optional) Object literal with any of the Fx config options
10094 * @return {Roo.Element} The Element
10096 frame : function(color, count, o){
10097 var el = this.getFxEl();
10100 el.queueFx(o, function(){
10101 color = color || "#C3DAF9";
10102 if(color.length == 6){
10103 color = "#" + color;
10105 count = count || 1;
10106 duration = o.duration || 1;
10109 var b = this.getBox();
10110 var animFn = function(){
10111 var proxy = this.createProxy({
10114 visbility:"hidden",
10115 position:"absolute",
10116 "z-index":"35000", // yee haw
10117 border:"0px solid " + color
10120 var scale = Roo.isBorderBox ? 2 : 1;
10122 top:{from:b.y, to:b.y - 20},
10123 left:{from:b.x, to:b.x - 20},
10124 borderWidth:{from:0, to:10},
10125 opacity:{from:1, to:0},
10126 height:{from:b.height, to:(b.height + (20*scale))},
10127 width:{from:b.width, to:(b.width + (20*scale))}
10128 }, duration, function(){
10132 animFn.defer((duration/2)*1000, this);
10143 * Creates a pause before any subsequent queued effects begin. If there are
10144 * no effects queued after the pause it will have no effect.
10149 * @param {Number} seconds The length of time to pause (in seconds)
10150 * @return {Roo.Element} The Element
10152 pause : function(seconds){
10153 var el = this.getFxEl();
10156 el.queueFx(o, function(){
10157 setTimeout(function(){
10159 }, seconds * 1000);
10165 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10166 * using the "endOpacity" config option.
10169 // default: fade in from opacity 0 to 100%
10172 // custom: fade in from opacity 0 to 75% over 2 seconds
10173 el.fadeIn({ endOpacity: .75, duration: 2});
10175 // common config options shown with default values
10177 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10182 * @param {Object} options (optional) Object literal with any of the Fx config options
10183 * @return {Roo.Element} The Element
10185 fadeIn : function(o){
10186 var el = this.getFxEl();
10188 el.queueFx(o, function(){
10189 this.setOpacity(0);
10191 this.dom.style.visibility = 'visible';
10192 var to = o.endOpacity || 1;
10193 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10194 o, null, .5, "easeOut", function(){
10196 this.clearOpacity();
10205 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10206 * using the "endOpacity" config option.
10209 // default: fade out from the element's current opacity to 0
10212 // custom: fade out from the element's current opacity to 25% over 2 seconds
10213 el.fadeOut({ endOpacity: .25, duration: 2});
10215 // common config options shown with default values
10217 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10224 * @param {Object} options (optional) Object literal with any of the Fx config options
10225 * @return {Roo.Element} The Element
10227 fadeOut : function(o){
10228 var el = this.getFxEl();
10230 el.queueFx(o, function(){
10231 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10232 o, null, .5, "easeOut", function(){
10233 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10234 this.dom.style.display = "none";
10236 this.dom.style.visibility = "hidden";
10238 this.clearOpacity();
10246 * Animates the transition of an element's dimensions from a starting height/width
10247 * to an ending height/width.
10250 // change height and width to 100x100 pixels
10251 el.scale(100, 100);
10253 // common config options shown with default values. The height and width will default to
10254 // the element's existing values if passed as null.
10257 [element's height], {
10262 * @param {Number} width The new width (pass undefined to keep the original width)
10263 * @param {Number} height The new height (pass undefined to keep the original height)
10264 * @param {Object} options (optional) Object literal with any of the Fx config options
10265 * @return {Roo.Element} The Element
10267 scale : function(w, h, o){
10268 this.shift(Roo.apply({}, o, {
10276 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10277 * Any of these properties not specified in the config object will not be changed. This effect
10278 * requires that at least one new dimension, position or opacity setting must be passed in on
10279 * the config object in order for the function to have any effect.
10282 // slide the element horizontally to x position 200 while changing the height and opacity
10283 el.shift({ x: 200, height: 50, opacity: .8 });
10285 // common config options shown with default values.
10287 width: [element's width],
10288 height: [element's height],
10289 x: [element's x position],
10290 y: [element's y position],
10291 opacity: [element's opacity],
10296 * @param {Object} options Object literal with any of the Fx config options
10297 * @return {Roo.Element} The Element
10299 shift : function(o){
10300 var el = this.getFxEl();
10302 el.queueFx(o, function(){
10303 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10304 if(w !== undefined){
10305 a.width = {to: this.adjustWidth(w)};
10307 if(h !== undefined){
10308 a.height = {to: this.adjustHeight(h)};
10310 if(x !== undefined || y !== undefined){
10312 x !== undefined ? x : this.getX(),
10313 y !== undefined ? y : this.getY()
10316 if(op !== undefined){
10317 a.opacity = {to: op};
10319 if(o.xy !== undefined){
10320 a.points = {to: o.xy};
10322 arguments.callee.anim = this.fxanim(a,
10323 o, 'motion', .35, "easeOut", function(){
10331 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10332 * ending point of the effect.
10335 // default: slide the element downward while fading out
10338 // custom: slide the element out to the right with a 2-second duration
10339 el.ghost('r', { duration: 2 });
10341 // common config options shown with default values
10349 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10350 * @param {Object} options (optional) Object literal with any of the Fx config options
10351 * @return {Roo.Element} The Element
10353 ghost : function(anchor, o){
10354 var el = this.getFxEl();
10357 el.queueFx(o, function(){
10358 anchor = anchor || "b";
10360 // restore values after effect
10361 var r = this.getFxRestore();
10362 var w = this.getWidth(),
10363 h = this.getHeight();
10365 var st = this.dom.style;
10367 var after = function(){
10369 el.setDisplayed(false);
10375 el.setPositioning(r.pos);
10376 st.width = r.width;
10377 st.height = r.height;
10382 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10383 switch(anchor.toLowerCase()){
10410 arguments.callee.anim = this.fxanim(a,
10420 * Ensures that all effects queued after syncFx is called on the element are
10421 * run concurrently. This is the opposite of {@link #sequenceFx}.
10422 * @return {Roo.Element} The Element
10424 syncFx : function(){
10425 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10434 * Ensures that all effects queued after sequenceFx is called on the element are
10435 * run in sequence. This is the opposite of {@link #syncFx}.
10436 * @return {Roo.Element} The Element
10438 sequenceFx : function(){
10439 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10441 concurrent : false,
10448 nextFx : function(){
10449 var ef = this.fxQueue[0];
10456 * Returns true if the element has any effects actively running or queued, else returns false.
10457 * @return {Boolean} True if element has active effects, else false
10459 hasActiveFx : function(){
10460 return this.fxQueue && this.fxQueue[0];
10464 * Stops any running effects and clears the element's internal effects queue if it contains
10465 * any additional effects that haven't started yet.
10466 * @return {Roo.Element} The Element
10468 stopFx : function(){
10469 if(this.hasActiveFx()){
10470 var cur = this.fxQueue[0];
10471 if(cur && cur.anim && cur.anim.isAnimated()){
10472 this.fxQueue = [cur]; // clear out others
10473 cur.anim.stop(true);
10480 beforeFx : function(o){
10481 if(this.hasActiveFx() && !o.concurrent){
10492 * Returns true if the element is currently blocking so that no other effect can be queued
10493 * until this effect is finished, else returns false if blocking is not set. This is commonly
10494 * used to ensure that an effect initiated by a user action runs to completion prior to the
10495 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10496 * @return {Boolean} True if blocking, else false
10498 hasFxBlock : function(){
10499 var q = this.fxQueue;
10500 return q && q[0] && q[0].block;
10504 queueFx : function(o, fn){
10508 if(!this.hasFxBlock()){
10509 Roo.applyIf(o, this.fxDefaults);
10511 var run = this.beforeFx(o);
10512 fn.block = o.block;
10513 this.fxQueue.push(fn);
10525 fxWrap : function(pos, o, vis){
10527 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10530 wrapXY = this.getXY();
10532 var div = document.createElement("div");
10533 div.style.visibility = vis;
10534 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10535 wrap.setPositioning(pos);
10536 if(wrap.getStyle("position") == "static"){
10537 wrap.position("relative");
10539 this.clearPositioning('auto');
10541 wrap.dom.appendChild(this.dom);
10543 wrap.setXY(wrapXY);
10550 fxUnwrap : function(wrap, pos, o){
10551 this.clearPositioning();
10552 this.setPositioning(pos);
10554 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10560 getFxRestore : function(){
10561 var st = this.dom.style;
10562 return {pos: this.getPositioning(), width: st.width, height : st.height};
10566 afterFx : function(o){
10568 this.applyStyles(o.afterStyle);
10571 this.addClass(o.afterCls);
10573 if(o.remove === true){
10576 Roo.callback(o.callback, o.scope, [this]);
10578 this.fxQueue.shift();
10584 getFxEl : function(){ // support for composite element fx
10585 return Roo.get(this.dom);
10589 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10590 animType = animType || 'run';
10592 var anim = Roo.lib.Anim[animType](
10594 (opt.duration || defaultDur) || .35,
10595 (opt.easing || defaultEase) || 'easeOut',
10597 Roo.callback(cb, this);
10606 // backwords compat
10607 Roo.Fx.resize = Roo.Fx.scale;
10609 //When included, Roo.Fx is automatically applied to Element so that all basic
10610 //effects are available directly via the Element API
10611 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10613 * Ext JS Library 1.1.1
10614 * Copyright(c) 2006-2007, Ext JS, LLC.
10616 * Originally Released Under LGPL - original licence link has changed is not relivant.
10619 * <script type="text/javascript">
10624 * @class Roo.CompositeElement
10625 * Standard composite class. Creates a Roo.Element for every element in the collection.
10627 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10628 * actions will be performed on all the elements in this collection.</b>
10630 * All methods return <i>this</i> and can be chained.
10632 var els = Roo.select("#some-el div.some-class", true);
10633 // or select directly from an existing element
10634 var el = Roo.get('some-el');
10635 el.select('div.some-class', true);
10637 els.setWidth(100); // all elements become 100 width
10638 els.hide(true); // all elements fade out and hide
10640 els.setWidth(100).hide(true);
10643 Roo.CompositeElement = function(els){
10644 this.elements = [];
10645 this.addElements(els);
10647 Roo.CompositeElement.prototype = {
10649 addElements : function(els){
10650 if(!els) return this;
10651 if(typeof els == "string"){
10652 els = Roo.Element.selectorFunction(els);
10654 var yels = this.elements;
10655 var index = yels.length-1;
10656 for(var i = 0, len = els.length; i < len; i++) {
10657 yels[++index] = Roo.get(els[i]);
10663 * Clears this composite and adds the elements returned by the passed selector.
10664 * @param {String/Array} els A string CSS selector, an array of elements or an element
10665 * @return {CompositeElement} this
10667 fill : function(els){
10668 this.elements = [];
10674 * Filters this composite to only elements that match the passed selector.
10675 * @param {String} selector A string CSS selector
10676 * @return {CompositeElement} this
10678 filter : function(selector){
10680 this.each(function(el){
10681 if(el.is(selector)){
10682 els[els.length] = el.dom;
10689 invoke : function(fn, args){
10690 var els = this.elements;
10691 for(var i = 0, len = els.length; i < len; i++) {
10692 Roo.Element.prototype[fn].apply(els[i], args);
10697 * Adds elements to this composite.
10698 * @param {String/Array} els A string CSS selector, an array of elements or an element
10699 * @return {CompositeElement} this
10701 add : function(els){
10702 if(typeof els == "string"){
10703 this.addElements(Roo.Element.selectorFunction(els));
10704 }else if(els.length !== undefined){
10705 this.addElements(els);
10707 this.addElements([els]);
10712 * Calls the passed function passing (el, this, index) for each element in this composite.
10713 * @param {Function} fn The function to call
10714 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10715 * @return {CompositeElement} this
10717 each : function(fn, scope){
10718 var els = this.elements;
10719 for(var i = 0, len = els.length; i < len; i++){
10720 if(fn.call(scope || els[i], els[i], this, i) === false) {
10728 * Returns the Element object at the specified index
10729 * @param {Number} index
10730 * @return {Roo.Element}
10732 item : function(index){
10733 return this.elements[index] || null;
10737 * Returns the first Element
10738 * @return {Roo.Element}
10740 first : function(){
10741 return this.item(0);
10745 * Returns the last Element
10746 * @return {Roo.Element}
10749 return this.item(this.elements.length-1);
10753 * Returns the number of elements in this composite
10756 getCount : function(){
10757 return this.elements.length;
10761 * Returns true if this composite contains the passed element
10764 contains : function(el){
10765 return this.indexOf(el) !== -1;
10769 * Returns true if this composite contains the passed element
10772 indexOf : function(el){
10773 return this.elements.indexOf(Roo.get(el));
10778 * Removes the specified element(s).
10779 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10780 * or an array of any of those.
10781 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10782 * @return {CompositeElement} this
10784 removeElement : function(el, removeDom){
10785 if(el instanceof Array){
10786 for(var i = 0, len = el.length; i < len; i++){
10787 this.removeElement(el[i]);
10791 var index = typeof el == 'number' ? el : this.indexOf(el);
10794 var d = this.elements[index];
10798 d.parentNode.removeChild(d);
10801 this.elements.splice(index, 1);
10807 * Replaces the specified element with the passed element.
10808 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10810 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10811 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10812 * @return {CompositeElement} this
10814 replaceElement : function(el, replacement, domReplace){
10815 var index = typeof el == 'number' ? el : this.indexOf(el);
10818 this.elements[index].replaceWith(replacement);
10820 this.elements.splice(index, 1, Roo.get(replacement))
10827 * Removes all elements.
10829 clear : function(){
10830 this.elements = [];
10834 Roo.CompositeElement.createCall = function(proto, fnName){
10835 if(!proto[fnName]){
10836 proto[fnName] = function(){
10837 return this.invoke(fnName, arguments);
10841 for(var fnName in Roo.Element.prototype){
10842 if(typeof Roo.Element.prototype[fnName] == "function"){
10843 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10849 * Ext JS Library 1.1.1
10850 * Copyright(c) 2006-2007, Ext JS, LLC.
10852 * Originally Released Under LGPL - original licence link has changed is not relivant.
10855 * <script type="text/javascript">
10859 * @class Roo.CompositeElementLite
10860 * @extends Roo.CompositeElement
10861 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10863 var els = Roo.select("#some-el div.some-class");
10864 // or select directly from an existing element
10865 var el = Roo.get('some-el');
10866 el.select('div.some-class');
10868 els.setWidth(100); // all elements become 100 width
10869 els.hide(true); // all elements fade out and hide
10871 els.setWidth(100).hide(true);
10872 </code></pre><br><br>
10873 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10874 * actions will be performed on all the elements in this collection.</b>
10876 Roo.CompositeElementLite = function(els){
10877 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10878 this.el = new Roo.Element.Flyweight();
10880 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10881 addElements : function(els){
10883 if(els instanceof Array){
10884 this.elements = this.elements.concat(els);
10886 var yels = this.elements;
10887 var index = yels.length-1;
10888 for(var i = 0, len = els.length; i < len; i++) {
10889 yels[++index] = els[i];
10895 invoke : function(fn, args){
10896 var els = this.elements;
10898 for(var i = 0, len = els.length; i < len; i++) {
10900 Roo.Element.prototype[fn].apply(el, args);
10905 * Returns a flyweight Element of the dom element object at the specified index
10906 * @param {Number} index
10907 * @return {Roo.Element}
10909 item : function(index){
10910 if(!this.elements[index]){
10913 this.el.dom = this.elements[index];
10917 // fixes scope with flyweight
10918 addListener : function(eventName, handler, scope, opt){
10919 var els = this.elements;
10920 for(var i = 0, len = els.length; i < len; i++) {
10921 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
10927 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
10928 * passed is the flyweight (shared) Roo.Element instance, so if you require a
10929 * a reference to the dom node, use el.dom.</b>
10930 * @param {Function} fn The function to call
10931 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10932 * @return {CompositeElement} this
10934 each : function(fn, scope){
10935 var els = this.elements;
10937 for(var i = 0, len = els.length; i < len; i++){
10939 if(fn.call(scope || el, el, this, i) === false){
10946 indexOf : function(el){
10947 return this.elements.indexOf(Roo.getDom(el));
10950 replaceElement : function(el, replacement, domReplace){
10951 var index = typeof el == 'number' ? el : this.indexOf(el);
10953 replacement = Roo.getDom(replacement);
10955 var d = this.elements[index];
10956 d.parentNode.insertBefore(replacement, d);
10957 d.parentNode.removeChild(d);
10959 this.elements.splice(index, 1, replacement);
10964 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
10968 * Ext JS Library 1.1.1
10969 * Copyright(c) 2006-2007, Ext JS, LLC.
10971 * Originally Released Under LGPL - original licence link has changed is not relivant.
10974 * <script type="text/javascript">
10980 * @class Roo.data.Connection
10981 * @extends Roo.util.Observable
10982 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
10983 * either to a configured URL, or to a URL specified at request time.<br><br>
10985 * Requests made by this class are asynchronous, and will return immediately. No data from
10986 * the server will be available to the statement immediately following the {@link #request} call.
10987 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
10989 * Note: If you are doing a file upload, you will not get a normal response object sent back to
10990 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
10991 * The response object is created using the innerHTML of the IFRAME's document as the responseText
10992 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
10993 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
10994 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
10995 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
10996 * standard DOM methods.
10998 * @param {Object} config a configuration object.
11000 Roo.data.Connection = function(config){
11001 Roo.apply(this, config);
11004 * @event beforerequest
11005 * Fires before a network request is made to retrieve a data object.
11006 * @param {Connection} conn This Connection object.
11007 * @param {Object} options The options config object passed to the {@link #request} method.
11009 "beforerequest" : true,
11011 * @event requestcomplete
11012 * Fires if the request was successfully completed.
11013 * @param {Connection} conn This Connection object.
11014 * @param {Object} response The XHR object containing the response data.
11015 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11016 * @param {Object} options The options config object passed to the {@link #request} method.
11018 "requestcomplete" : true,
11020 * @event requestexception
11021 * Fires if an error HTTP status was returned from the server.
11022 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11023 * @param {Connection} conn This Connection object.
11024 * @param {Object} response The XHR object containing the response data.
11025 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11026 * @param {Object} options The options config object passed to the {@link #request} method.
11028 "requestexception" : true
11030 Roo.data.Connection.superclass.constructor.call(this);
11033 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11035 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11038 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11039 * extra parameters to each request made by this object. (defaults to undefined)
11042 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11043 * to each request made by this object. (defaults to undefined)
11046 * @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)
11049 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11053 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11059 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11062 disableCaching: true,
11065 * Sends an HTTP request to a remote server.
11066 * @param {Object} options An object which may contain the following properties:<ul>
11067 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11068 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11069 * request, a url encoded string or a function to call to get either.</li>
11070 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11071 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11072 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11073 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11074 * <li>options {Object} The parameter to the request call.</li>
11075 * <li>success {Boolean} True if the request succeeded.</li>
11076 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11078 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11079 * The callback is passed the following parameters:<ul>
11080 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11081 * <li>options {Object} The parameter to the request call.</li>
11083 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11084 * The callback is passed the following parameters:<ul>
11085 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11086 * <li>options {Object} The parameter to the request call.</li>
11088 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11089 * for the callback function. Defaults to the browser window.</li>
11090 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11091 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11092 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11093 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11094 * params for the post data. Any params will be appended to the URL.</li>
11095 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11097 * @return {Number} transactionId
11099 request : function(o){
11100 if(this.fireEvent("beforerequest", this, o) !== false){
11103 if(typeof p == "function"){
11104 p = p.call(o.scope||window, o);
11106 if(typeof p == "object"){
11107 p = Roo.urlEncode(o.params);
11109 if(this.extraParams){
11110 var extras = Roo.urlEncode(this.extraParams);
11111 p = p ? (p + '&' + extras) : extras;
11114 var url = o.url || this.url;
11115 if(typeof url == 'function'){
11116 url = url.call(o.scope||window, o);
11120 var form = Roo.getDom(o.form);
11121 url = url || form.action;
11123 var enctype = form.getAttribute("enctype");
11124 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11125 return this.doFormUpload(o, p, url);
11127 var f = Roo.lib.Ajax.serializeForm(form);
11128 p = p ? (p + '&' + f) : f;
11131 var hs = o.headers;
11132 if(this.defaultHeaders){
11133 hs = Roo.apply(hs || {}, this.defaultHeaders);
11140 success: this.handleResponse,
11141 failure: this.handleFailure,
11143 argument: {options: o},
11144 timeout : this.timeout
11147 var method = o.method||this.method||(p ? "POST" : "GET");
11149 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11150 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11153 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11157 }else if(this.autoAbort !== false){
11161 if((method == 'GET' && p) || o.xmlData){
11162 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11165 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11166 return this.transId;
11168 Roo.callback(o.callback, o.scope, [o, null, null]);
11174 * Determine whether this object has a request outstanding.
11175 * @param {Number} transactionId (Optional) defaults to the last transaction
11176 * @return {Boolean} True if there is an outstanding request.
11178 isLoading : function(transId){
11180 return Roo.lib.Ajax.isCallInProgress(transId);
11182 return this.transId ? true : false;
11187 * Aborts any outstanding request.
11188 * @param {Number} transactionId (Optional) defaults to the last transaction
11190 abort : function(transId){
11191 if(transId || this.isLoading()){
11192 Roo.lib.Ajax.abort(transId || this.transId);
11197 handleResponse : function(response){
11198 this.transId = false;
11199 var options = response.argument.options;
11200 response.argument = options ? options.argument : null;
11201 this.fireEvent("requestcomplete", this, response, options);
11202 Roo.callback(options.success, options.scope, [response, options]);
11203 Roo.callback(options.callback, options.scope, [options, true, response]);
11207 handleFailure : function(response, e){
11208 this.transId = false;
11209 var options = response.argument.options;
11210 response.argument = options ? options.argument : null;
11211 this.fireEvent("requestexception", this, response, options, e);
11212 Roo.callback(options.failure, options.scope, [response, options]);
11213 Roo.callback(options.callback, options.scope, [options, false, response]);
11217 doFormUpload : function(o, ps, url){
11219 var frame = document.createElement('iframe');
11222 frame.className = 'x-hidden';
11224 frame.src = Roo.SSL_SECURE_URL;
11226 document.body.appendChild(frame);
11229 document.frames[id].name = id;
11232 var form = Roo.getDom(o.form);
11234 form.method = 'POST';
11235 form.enctype = form.encoding = 'multipart/form-data';
11241 if(ps){ // add dynamic params
11243 ps = Roo.urlDecode(ps, false);
11245 if(ps.hasOwnProperty(k)){
11246 hd = document.createElement('input');
11247 hd.type = 'hidden';
11250 form.appendChild(hd);
11257 var r = { // bogus response object
11262 r.argument = o ? o.argument : null;
11267 doc = frame.contentWindow.document;
11269 doc = (frame.contentDocument || window.frames[id].document);
11271 if(doc && doc.body){
11272 r.responseText = doc.body.innerHTML;
11274 if(doc && doc.XMLDocument){
11275 r.responseXML = doc.XMLDocument;
11277 r.responseXML = doc;
11284 Roo.EventManager.removeListener(frame, 'load', cb, this);
11286 this.fireEvent("requestcomplete", this, r, o);
11287 Roo.callback(o.success, o.scope, [r, o]);
11288 Roo.callback(o.callback, o.scope, [o, true, r]);
11290 setTimeout(function(){document.body.removeChild(frame);}, 100);
11293 Roo.EventManager.on(frame, 'load', cb, this);
11296 if(hiddens){ // remove dynamic params
11297 for(var i = 0, len = hiddens.length; i < len; i++){
11298 form.removeChild(hiddens[i]);
11306 * @extends Roo.data.Connection
11307 * Global Ajax request class.
11311 Roo.Ajax = new Roo.data.Connection({
11314 * @cfg {String} url @hide
11317 * @cfg {Object} extraParams @hide
11320 * @cfg {Object} defaultHeaders @hide
11323 * @cfg {String} method (Optional) @hide
11326 * @cfg {Number} timeout (Optional) @hide
11329 * @cfg {Boolean} autoAbort (Optional) @hide
11333 * @cfg {Boolean} disableCaching (Optional) @hide
11337 * @property disableCaching
11338 * True to add a unique cache-buster param to GET requests. (defaults to true)
11343 * The default URL to be used for requests to the server. (defaults to undefined)
11347 * @property extraParams
11348 * An object containing properties which are used as
11349 * extra parameters to each request made by this object. (defaults to undefined)
11353 * @property defaultHeaders
11354 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11359 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11363 * @property timeout
11364 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11369 * @property autoAbort
11370 * Whether a new request should abort any pending requests. (defaults to false)
11376 * Serialize the passed form into a url encoded string
11377 * @param {String/HTMLElement} form
11380 serializeForm : function(form){
11381 return Roo.lib.Ajax.serializeForm(form);
11385 * Ext JS Library 1.1.1
11386 * Copyright(c) 2006-2007, Ext JS, LLC.
11388 * Originally Released Under LGPL - original licence link has changed is not relivant.
11391 * <script type="text/javascript">
11396 * @extends Roo.data.Connection
11397 * Global Ajax request class.
11399 * @instanceOf Roo.data.Connection
11401 Roo.Ajax = new Roo.data.Connection({
11410 * @cfg {String} url @hide
11413 * @cfg {Object} extraParams @hide
11416 * @cfg {Object} defaultHeaders @hide
11419 * @cfg {String} method (Optional) @hide
11422 * @cfg {Number} timeout (Optional) @hide
11425 * @cfg {Boolean} autoAbort (Optional) @hide
11429 * @cfg {Boolean} disableCaching (Optional) @hide
11433 * @property disableCaching
11434 * True to add a unique cache-buster param to GET requests. (defaults to true)
11439 * The default URL to be used for requests to the server. (defaults to undefined)
11443 * @property extraParams
11444 * An object containing properties which are used as
11445 * extra parameters to each request made by this object. (defaults to undefined)
11449 * @property defaultHeaders
11450 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11455 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11459 * @property timeout
11460 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11465 * @property autoAbort
11466 * Whether a new request should abort any pending requests. (defaults to false)
11472 * Serialize the passed form into a url encoded string
11473 * @param {String/HTMLElement} form
11476 serializeForm : function(form){
11477 return Roo.lib.Ajax.serializeForm(form);
11481 * Ext JS Library 1.1.1
11482 * Copyright(c) 2006-2007, Ext JS, LLC.
11484 * Originally Released Under LGPL - original licence link has changed is not relivant.
11487 * <script type="text/javascript">
11492 * @class Roo.UpdateManager
11493 * @extends Roo.util.Observable
11494 * Provides AJAX-style update for Element object.<br><br>
11497 * // Get it from a Roo.Element object
11498 * var el = Roo.get("foo");
11499 * var mgr = el.getUpdateManager();
11500 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11502 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11504 * // or directly (returns the same UpdateManager instance)
11505 * var mgr = new Roo.UpdateManager("myElementId");
11506 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11507 * mgr.on("update", myFcnNeedsToKnow);
11509 // short handed call directly from the element object
11510 Roo.get("foo").load({
11514 text: "Loading Foo..."
11518 * Create new UpdateManager directly.
11519 * @param {String/HTMLElement/Roo.Element} el The element to update
11520 * @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).
11522 Roo.UpdateManager = function(el, forceNew){
11524 if(!forceNew && el.updateManager){
11525 return el.updateManager;
11528 * The Element object
11529 * @type Roo.Element
11533 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11536 this.defaultUrl = null;
11540 * @event beforeupdate
11541 * Fired before an update is made, return false from your handler and the update is cancelled.
11542 * @param {Roo.Element} el
11543 * @param {String/Object/Function} url
11544 * @param {String/Object} params
11546 "beforeupdate": true,
11549 * Fired after successful update is made.
11550 * @param {Roo.Element} el
11551 * @param {Object} oResponseObject The response Object
11556 * Fired on update failure.
11557 * @param {Roo.Element} el
11558 * @param {Object} oResponseObject The response Object
11562 var d = Roo.UpdateManager.defaults;
11564 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11567 this.sslBlankUrl = d.sslBlankUrl;
11569 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11572 this.disableCaching = d.disableCaching;
11574 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11577 this.indicatorText = d.indicatorText;
11579 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11582 this.showLoadIndicator = d.showLoadIndicator;
11584 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11587 this.timeout = d.timeout;
11590 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11593 this.loadScripts = d.loadScripts;
11596 * Transaction object of current executing transaction
11598 this.transaction = null;
11603 this.autoRefreshProcId = null;
11605 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11608 this.refreshDelegate = this.refresh.createDelegate(this);
11610 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11613 this.updateDelegate = this.update.createDelegate(this);
11615 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11618 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11622 this.successDelegate = this.processSuccess.createDelegate(this);
11626 this.failureDelegate = this.processFailure.createDelegate(this);
11628 if(!this.renderer){
11630 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11632 this.renderer = new Roo.UpdateManager.BasicRenderer();
11635 Roo.UpdateManager.superclass.constructor.call(this);
11638 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11640 * Get the Element this UpdateManager is bound to
11641 * @return {Roo.Element} The element
11643 getEl : function(){
11647 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11648 * @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:
11651 url: "your-url.php",<br/>
11652 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11653 callback: yourFunction,<br/>
11654 scope: yourObject, //(optional scope) <br/>
11655 discardUrl: false, <br/>
11656 nocache: false,<br/>
11657 text: "Loading...",<br/>
11659 scripts: false<br/>
11662 * The only required property is url. The optional properties nocache, text and scripts
11663 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11664 * @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}
11665 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11666 * @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.
11668 update : function(url, params, callback, discardUrl){
11669 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11670 var method = this.method, cfg;
11671 if(typeof url == "object"){ // must be config object
11674 params = params || cfg.params;
11675 callback = callback || cfg.callback;
11676 discardUrl = discardUrl || cfg.discardUrl;
11677 if(callback && cfg.scope){
11678 callback = callback.createDelegate(cfg.scope);
11680 if(typeof cfg.method != "undefined"){method = cfg.method;};
11681 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11682 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11683 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11684 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11686 this.showLoading();
11688 this.defaultUrl = url;
11690 if(typeof url == "function"){
11691 url = url.call(this);
11694 method = method || (params ? "POST" : "GET");
11695 if(method == "GET"){
11696 url = this.prepareUrl(url);
11699 var o = Roo.apply(cfg ||{}, {
11702 success: this.successDelegate,
11703 failure: this.failureDelegate,
11704 callback: undefined,
11705 timeout: (this.timeout*1000),
11706 argument: {"url": url, "form": null, "callback": callback, "params": params}
11709 this.transaction = Roo.Ajax.request(o);
11714 * 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.
11715 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11716 * @param {String/HTMLElement} form The form Id or form element
11717 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11718 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11719 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11721 formUpdate : function(form, url, reset, callback){
11722 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11723 if(typeof url == "function"){
11724 url = url.call(this);
11726 form = Roo.getDom(form);
11727 this.transaction = Roo.Ajax.request({
11730 success: this.successDelegate,
11731 failure: this.failureDelegate,
11732 timeout: (this.timeout*1000),
11733 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11735 this.showLoading.defer(1, this);
11740 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11741 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11743 refresh : function(callback){
11744 if(this.defaultUrl == null){
11747 this.update(this.defaultUrl, null, callback, true);
11751 * Set this element to auto refresh.
11752 * @param {Number} interval How often to update (in seconds).
11753 * @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)
11754 * @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}
11755 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11756 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11758 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11760 this.update(url || this.defaultUrl, params, callback, true);
11762 if(this.autoRefreshProcId){
11763 clearInterval(this.autoRefreshProcId);
11765 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11769 * Stop auto refresh on this element.
11771 stopAutoRefresh : function(){
11772 if(this.autoRefreshProcId){
11773 clearInterval(this.autoRefreshProcId);
11774 delete this.autoRefreshProcId;
11778 isAutoRefreshing : function(){
11779 return this.autoRefreshProcId ? true : false;
11782 * Called to update the element to "Loading" state. Override to perform custom action.
11784 showLoading : function(){
11785 if(this.showLoadIndicator){
11786 this.el.update(this.indicatorText);
11791 * Adds unique parameter to query string if disableCaching = true
11794 prepareUrl : function(url){
11795 if(this.disableCaching){
11796 var append = "_dc=" + (new Date().getTime());
11797 if(url.indexOf("?") !== -1){
11798 url += "&" + append;
11800 url += "?" + append;
11809 processSuccess : function(response){
11810 this.transaction = null;
11811 if(response.argument.form && response.argument.reset){
11812 try{ // put in try/catch since some older FF releases had problems with this
11813 response.argument.form.reset();
11816 if(this.loadScripts){
11817 this.renderer.render(this.el, response, this,
11818 this.updateComplete.createDelegate(this, [response]));
11820 this.renderer.render(this.el, response, this);
11821 this.updateComplete(response);
11825 updateComplete : function(response){
11826 this.fireEvent("update", this.el, response);
11827 if(typeof response.argument.callback == "function"){
11828 response.argument.callback(this.el, true, response);
11835 processFailure : function(response){
11836 this.transaction = null;
11837 this.fireEvent("failure", this.el, response);
11838 if(typeof response.argument.callback == "function"){
11839 response.argument.callback(this.el, false, response);
11844 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11845 * @param {Object} renderer The object implementing the render() method
11847 setRenderer : function(renderer){
11848 this.renderer = renderer;
11851 getRenderer : function(){
11852 return this.renderer;
11856 * Set the defaultUrl used for updates
11857 * @param {String/Function} defaultUrl The url or a function to call to get the url
11859 setDefaultUrl : function(defaultUrl){
11860 this.defaultUrl = defaultUrl;
11864 * Aborts the executing transaction
11866 abort : function(){
11867 if(this.transaction){
11868 Roo.Ajax.abort(this.transaction);
11873 * Returns true if an update is in progress
11874 * @return {Boolean}
11876 isUpdating : function(){
11877 if(this.transaction){
11878 return Roo.Ajax.isLoading(this.transaction);
11885 * @class Roo.UpdateManager.defaults
11886 * @static (not really - but it helps the doc tool)
11887 * The defaults collection enables customizing the default properties of UpdateManager
11889 Roo.UpdateManager.defaults = {
11891 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
11897 * True to process scripts by default (Defaults to false).
11900 loadScripts : false,
11903 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
11906 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
11908 * Whether to append unique parameter on get request to disable caching (Defaults to false).
11911 disableCaching : false,
11913 * Whether to show indicatorText when loading (Defaults to true).
11916 showLoadIndicator : true,
11918 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
11921 indicatorText : '<div class="loading-indicator">Loading...</div>'
11925 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
11927 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
11928 * @param {String/HTMLElement/Roo.Element} el The element to update
11929 * @param {String} url The url
11930 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
11931 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
11934 * @member Roo.UpdateManager
11936 Roo.UpdateManager.updateElement = function(el, url, params, options){
11937 var um = Roo.get(el, true).getUpdateManager();
11938 Roo.apply(um, options);
11939 um.update(url, params, options ? options.callback : null);
11941 // alias for backwards compat
11942 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
11944 * @class Roo.UpdateManager.BasicRenderer
11945 * Default Content renderer. Updates the elements innerHTML with the responseText.
11947 Roo.UpdateManager.BasicRenderer = function(){};
11949 Roo.UpdateManager.BasicRenderer.prototype = {
11951 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
11952 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
11953 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
11954 * @param {Roo.Element} el The element being rendered
11955 * @param {Object} response The YUI Connect response object
11956 * @param {UpdateManager} updateManager The calling update manager
11957 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
11959 render : function(el, response, updateManager, callback){
11960 el.update(response.responseText, updateManager.loadScripts, callback);
11965 * Ext JS Library 1.1.1
11966 * Copyright(c) 2006-2007, Ext JS, LLC.
11968 * Originally Released Under LGPL - original licence link has changed is not relivant.
11971 * <script type="text/javascript">
11975 * @class Roo.util.DelayedTask
11976 * Provides a convenient method of performing setTimeout where a new
11977 * timeout cancels the old timeout. An example would be performing validation on a keypress.
11978 * You can use this class to buffer
11979 * the keypress events for a certain number of milliseconds, and perform only if they stop
11980 * for that amount of time.
11981 * @constructor The parameters to this constructor serve as defaults and are not required.
11982 * @param {Function} fn (optional) The default function to timeout
11983 * @param {Object} scope (optional) The default scope of that timeout
11984 * @param {Array} args (optional) The default Array of arguments
11986 Roo.util.DelayedTask = function(fn, scope, args){
11987 var id = null, d, t;
11989 var call = function(){
11990 var now = new Date().getTime();
11994 fn.apply(scope, args || []);
11998 * Cancels any pending timeout and queues a new one
11999 * @param {Number} delay The milliseconds to delay
12000 * @param {Function} newFn (optional) Overrides function passed to constructor
12001 * @param {Object} newScope (optional) Overrides scope passed to constructor
12002 * @param {Array} newArgs (optional) Overrides args passed to constructor
12004 this.delay = function(delay, newFn, newScope, newArgs){
12005 if(id && delay != d){
12009 t = new Date().getTime();
12011 scope = newScope || scope;
12012 args = newArgs || args;
12014 id = setInterval(call, d);
12019 * Cancel the last queued timeout
12021 this.cancel = function(){
12029 * Ext JS Library 1.1.1
12030 * Copyright(c) 2006-2007, Ext JS, LLC.
12032 * Originally Released Under LGPL - original licence link has changed is not relivant.
12035 * <script type="text/javascript">
12039 Roo.util.TaskRunner = function(interval){
12040 interval = interval || 10;
12041 var tasks = [], removeQueue = [];
12043 var running = false;
12045 var stopThread = function(){
12051 var startThread = function(){
12054 id = setInterval(runTasks, interval);
12058 var removeTask = function(task){
12059 removeQueue.push(task);
12065 var runTasks = function(){
12066 if(removeQueue.length > 0){
12067 for(var i = 0, len = removeQueue.length; i < len; i++){
12068 tasks.remove(removeQueue[i]);
12071 if(tasks.length < 1){
12076 var now = new Date().getTime();
12077 for(var i = 0, len = tasks.length; i < len; ++i){
12079 var itime = now - t.taskRunTime;
12080 if(t.interval <= itime){
12081 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12082 t.taskRunTime = now;
12083 if(rt === false || t.taskRunCount === t.repeat){
12088 if(t.duration && t.duration <= (now - t.taskStartTime)){
12095 * Queues a new task.
12096 * @param {Object} task
12098 this.start = function(task){
12100 task.taskStartTime = new Date().getTime();
12101 task.taskRunTime = 0;
12102 task.taskRunCount = 0;
12107 this.stop = function(task){
12112 this.stopAll = function(){
12114 for(var i = 0, len = tasks.length; i < len; i++){
12115 if(tasks[i].onStop){
12124 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12126 * Ext JS Library 1.1.1
12127 * Copyright(c) 2006-2007, Ext JS, LLC.
12129 * Originally Released Under LGPL - original licence link has changed is not relivant.
12132 * <script type="text/javascript">
12137 * @class Roo.util.MixedCollection
12138 * @extends Roo.util.Observable
12139 * A Collection class that maintains both numeric indexes and keys and exposes events.
12141 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12142 * collection (defaults to false)
12143 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12144 * and return the key value for that item. This is used when available to look up the key on items that
12145 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12146 * equivalent to providing an implementation for the {@link #getKey} method.
12148 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12156 * Fires when the collection is cleared.
12161 * Fires when an item is added to the collection.
12162 * @param {Number} index The index at which the item was added.
12163 * @param {Object} o The item added.
12164 * @param {String} key The key associated with the added item.
12169 * Fires when an item is replaced in the collection.
12170 * @param {String} key he key associated with the new added.
12171 * @param {Object} old The item being replaced.
12172 * @param {Object} new The new item.
12177 * Fires when an item is removed from the collection.
12178 * @param {Object} o The item being removed.
12179 * @param {String} key (optional) The key associated with the removed item.
12184 this.allowFunctions = allowFunctions === true;
12186 this.getKey = keyFn;
12188 Roo.util.MixedCollection.superclass.constructor.call(this);
12191 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12192 allowFunctions : false,
12195 * Adds an item to the collection.
12196 * @param {String} key The key to associate with the item
12197 * @param {Object} o The item to add.
12198 * @return {Object} The item added.
12200 add : function(key, o){
12201 if(arguments.length == 1){
12203 key = this.getKey(o);
12205 if(typeof key == "undefined" || key === null){
12207 this.items.push(o);
12208 this.keys.push(null);
12210 var old = this.map[key];
12212 return this.replace(key, o);
12215 this.items.push(o);
12217 this.keys.push(key);
12219 this.fireEvent("add", this.length-1, o, key);
12224 * MixedCollection has a generic way to fetch keys if you implement getKey.
12227 var mc = new Roo.util.MixedCollection();
12228 mc.add(someEl.dom.id, someEl);
12229 mc.add(otherEl.dom.id, otherEl);
12233 var mc = new Roo.util.MixedCollection();
12234 mc.getKey = function(el){
12240 // or via the constructor
12241 var mc = new Roo.util.MixedCollection(false, function(el){
12247 * @param o {Object} The item for which to find the key.
12248 * @return {Object} The key for the passed item.
12250 getKey : function(o){
12255 * Replaces an item in the collection.
12256 * @param {String} key The key associated with the item to replace, or the item to replace.
12257 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12258 * @return {Object} The new item.
12260 replace : function(key, o){
12261 if(arguments.length == 1){
12263 key = this.getKey(o);
12265 var old = this.item(key);
12266 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12267 return this.add(key, o);
12269 var index = this.indexOfKey(key);
12270 this.items[index] = o;
12272 this.fireEvent("replace", key, old, o);
12277 * Adds all elements of an Array or an Object to the collection.
12278 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12279 * an Array of values, each of which are added to the collection.
12281 addAll : function(objs){
12282 if(arguments.length > 1 || objs instanceof Array){
12283 var args = arguments.length > 1 ? arguments : objs;
12284 for(var i = 0, len = args.length; i < len; i++){
12288 for(var key in objs){
12289 if(this.allowFunctions || typeof objs[key] != "function"){
12290 this.add(key, objs[key]);
12297 * Executes the specified function once for every item in the collection, passing each
12298 * item as the first and only parameter. returning false from the function will stop the iteration.
12299 * @param {Function} fn The function to execute for each item.
12300 * @param {Object} scope (optional) The scope in which to execute the function.
12302 each : function(fn, scope){
12303 var items = [].concat(this.items); // each safe for removal
12304 for(var i = 0, len = items.length; i < len; i++){
12305 if(fn.call(scope || items[i], items[i], i, len) === false){
12312 * Executes the specified function once for every key in the collection, passing each
12313 * key, and its associated item as the first two parameters.
12314 * @param {Function} fn The function to execute for each item.
12315 * @param {Object} scope (optional) The scope in which to execute the function.
12317 eachKey : function(fn, scope){
12318 for(var i = 0, len = this.keys.length; i < len; i++){
12319 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12324 * Returns the first item in the collection which elicits a true return value from the
12325 * passed selection function.
12326 * @param {Function} fn The selection function to execute for each item.
12327 * @param {Object} scope (optional) The scope in which to execute the function.
12328 * @return {Object} The first item in the collection which returned true from the selection function.
12330 find : function(fn, scope){
12331 for(var i = 0, len = this.items.length; i < len; i++){
12332 if(fn.call(scope || window, this.items[i], this.keys[i])){
12333 return this.items[i];
12340 * Inserts an item at the specified index in the collection.
12341 * @param {Number} index The index to insert the item at.
12342 * @param {String} key The key to associate with the new item, or the item itself.
12343 * @param {Object} o (optional) If the second parameter was a key, the new item.
12344 * @return {Object} The item inserted.
12346 insert : function(index, key, o){
12347 if(arguments.length == 2){
12349 key = this.getKey(o);
12351 if(index >= this.length){
12352 return this.add(key, o);
12355 this.items.splice(index, 0, o);
12356 if(typeof key != "undefined" && key != null){
12359 this.keys.splice(index, 0, key);
12360 this.fireEvent("add", index, o, key);
12365 * Removed an item from the collection.
12366 * @param {Object} o The item to remove.
12367 * @return {Object} The item removed.
12369 remove : function(o){
12370 return this.removeAt(this.indexOf(o));
12374 * Remove an item from a specified index in the collection.
12375 * @param {Number} index The index within the collection of the item to remove.
12377 removeAt : function(index){
12378 if(index < this.length && index >= 0){
12380 var o = this.items[index];
12381 this.items.splice(index, 1);
12382 var key = this.keys[index];
12383 if(typeof key != "undefined"){
12384 delete this.map[key];
12386 this.keys.splice(index, 1);
12387 this.fireEvent("remove", o, key);
12392 * Removed an item associated with the passed key fom the collection.
12393 * @param {String} key The key of the item to remove.
12395 removeKey : function(key){
12396 return this.removeAt(this.indexOfKey(key));
12400 * Returns the number of items in the collection.
12401 * @return {Number} the number of items in the collection.
12403 getCount : function(){
12404 return this.length;
12408 * Returns index within the collection of the passed Object.
12409 * @param {Object} o The item to find the index of.
12410 * @return {Number} index of the item.
12412 indexOf : function(o){
12413 if(!this.items.indexOf){
12414 for(var i = 0, len = this.items.length; i < len; i++){
12415 if(this.items[i] == o) return i;
12419 return this.items.indexOf(o);
12424 * Returns index within the collection of the passed key.
12425 * @param {String} key The key to find the index of.
12426 * @return {Number} index of the key.
12428 indexOfKey : function(key){
12429 if(!this.keys.indexOf){
12430 for(var i = 0, len = this.keys.length; i < len; i++){
12431 if(this.keys[i] == key) return i;
12435 return this.keys.indexOf(key);
12440 * Returns the item associated with the passed key OR index. Key has priority over index.
12441 * @param {String/Number} key The key or index of the item.
12442 * @return {Object} The item associated with the passed key.
12444 item : function(key){
12445 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12446 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12450 * Returns the item at the specified index.
12451 * @param {Number} index The index of the item.
12454 itemAt : function(index){
12455 return this.items[index];
12459 * Returns the item associated with the passed key.
12460 * @param {String/Number} key The key of the item.
12461 * @return {Object} The item associated with the passed key.
12463 key : function(key){
12464 return this.map[key];
12468 * Returns true if the collection contains the passed Object as an item.
12469 * @param {Object} o The Object to look for in the collection.
12470 * @return {Boolean} True if the collection contains the Object as an item.
12472 contains : function(o){
12473 return this.indexOf(o) != -1;
12477 * Returns true if the collection contains the passed Object as a key.
12478 * @param {String} key The key to look for in the collection.
12479 * @return {Boolean} True if the collection contains the Object as a key.
12481 containsKey : function(key){
12482 return typeof this.map[key] != "undefined";
12486 * Removes all items from the collection.
12488 clear : function(){
12493 this.fireEvent("clear");
12497 * Returns the first item in the collection.
12498 * @return {Object} the first item in the collection..
12500 first : function(){
12501 return this.items[0];
12505 * Returns the last item in the collection.
12506 * @return {Object} the last item in the collection..
12509 return this.items[this.length-1];
12512 _sort : function(property, dir, fn){
12513 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12514 fn = fn || function(a, b){
12517 var c = [], k = this.keys, items = this.items;
12518 for(var i = 0, len = items.length; i < len; i++){
12519 c[c.length] = {key: k[i], value: items[i], index: i};
12521 c.sort(function(a, b){
12522 var v = fn(a[property], b[property]) * dsc;
12524 v = (a.index < b.index ? -1 : 1);
12528 for(var i = 0, len = c.length; i < len; i++){
12529 items[i] = c[i].value;
12532 this.fireEvent("sort", this);
12536 * Sorts this collection with the passed comparison function
12537 * @param {String} direction (optional) "ASC" or "DESC"
12538 * @param {Function} fn (optional) comparison function
12540 sort : function(dir, fn){
12541 this._sort("value", dir, fn);
12545 * Sorts this collection by keys
12546 * @param {String} direction (optional) "ASC" or "DESC"
12547 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12549 keySort : function(dir, fn){
12550 this._sort("key", dir, fn || function(a, b){
12551 return String(a).toUpperCase()-String(b).toUpperCase();
12556 * Returns a range of items in this collection
12557 * @param {Number} startIndex (optional) defaults to 0
12558 * @param {Number} endIndex (optional) default to the last item
12559 * @return {Array} An array of items
12561 getRange : function(start, end){
12562 var items = this.items;
12563 if(items.length < 1){
12566 start = start || 0;
12567 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12570 for(var i = start; i <= end; i++) {
12571 r[r.length] = items[i];
12574 for(var i = start; i >= end; i--) {
12575 r[r.length] = items[i];
12582 * Filter the <i>objects</i> in this collection by a specific property.
12583 * Returns a new collection that has been filtered.
12584 * @param {String} property A property on your objects
12585 * @param {String/RegExp} value Either string that the property values
12586 * should start with or a RegExp to test against the property
12587 * @return {MixedCollection} The new filtered collection
12589 filter : function(property, value){
12590 if(!value.exec){ // not a regex
12591 value = String(value);
12592 if(value.length == 0){
12593 return this.clone();
12595 value = new RegExp("^" + Roo.escapeRe(value), "i");
12597 return this.filterBy(function(o){
12598 return o && value.test(o[property]);
12603 * Filter by a function. * Returns a new collection that has been filtered.
12604 * The passed function will be called with each
12605 * object in the collection. If the function returns true, the value is included
12606 * otherwise it is filtered.
12607 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12608 * @param {Object} scope (optional) The scope of the function (defaults to this)
12609 * @return {MixedCollection} The new filtered collection
12611 filterBy : function(fn, scope){
12612 var r = new Roo.util.MixedCollection();
12613 r.getKey = this.getKey;
12614 var k = this.keys, it = this.items;
12615 for(var i = 0, len = it.length; i < len; i++){
12616 if(fn.call(scope||this, it[i], k[i])){
12617 r.add(k[i], it[i]);
12624 * Creates a duplicate of this collection
12625 * @return {MixedCollection}
12627 clone : function(){
12628 var r = new Roo.util.MixedCollection();
12629 var k = this.keys, it = this.items;
12630 for(var i = 0, len = it.length; i < len; i++){
12631 r.add(k[i], it[i]);
12633 r.getKey = this.getKey;
12638 * Returns the item associated with the passed key or index.
12640 * @param {String/Number} key The key or index of the item.
12641 * @return {Object} The item associated with the passed key.
12643 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12645 * Ext JS Library 1.1.1
12646 * Copyright(c) 2006-2007, Ext JS, LLC.
12648 * Originally Released Under LGPL - original licence link has changed is not relivant.
12651 * <script type="text/javascript">
12654 * @class Roo.util.JSON
12655 * Modified version of Douglas Crockford"s json.js that doesn"t
12656 * mess with the Object prototype
12657 * http://www.json.org/js.html
12660 Roo.util.JSON = new (function(){
12661 var useHasOwn = {}.hasOwnProperty ? true : false;
12663 // crashes Safari in some instances
12664 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12666 var pad = function(n) {
12667 return n < 10 ? "0" + n : n;
12680 var encodeString = function(s){
12681 if (/["\\\x00-\x1f]/.test(s)) {
12682 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12687 c = b.charCodeAt();
12689 Math.floor(c / 16).toString(16) +
12690 (c % 16).toString(16);
12693 return '"' + s + '"';
12696 var encodeArray = function(o){
12697 var a = ["["], b, i, l = o.length, v;
12698 for (i = 0; i < l; i += 1) {
12700 switch (typeof v) {
12709 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12717 var encodeDate = function(o){
12718 return '"' + o.getFullYear() + "-" +
12719 pad(o.getMonth() + 1) + "-" +
12720 pad(o.getDate()) + "T" +
12721 pad(o.getHours()) + ":" +
12722 pad(o.getMinutes()) + ":" +
12723 pad(o.getSeconds()) + '"';
12727 * Encodes an Object, Array or other value
12728 * @param {Mixed} o The variable to encode
12729 * @return {String} The JSON string
12731 this.encode = function(o){
12732 if(typeof o == "undefined" || o === null){
12734 }else if(o instanceof Array){
12735 return encodeArray(o);
12736 }else if(o instanceof Date){
12737 return encodeDate(o);
12738 }else if(typeof o == "string"){
12739 return encodeString(o);
12740 }else if(typeof o == "number"){
12741 return isFinite(o) ? String(o) : "null";
12742 }else if(typeof o == "boolean"){
12745 var a = ["{"], b, i, v;
12747 if(!useHasOwn || o.hasOwnProperty(i)) {
12749 switch (typeof v) {
12758 a.push(this.encode(i), ":",
12759 v === null ? "null" : this.encode(v));
12770 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12771 * @param {String} json The JSON string
12772 * @return {Object} The resulting object
12774 this.decode = function(json){
12778 return eval("(" + json + ')');
12782 * Shorthand for {@link Roo.util.JSON#encode}
12783 * @member Roo encode
12785 Roo.encode = Roo.util.JSON.encode;
12787 * Shorthand for {@link Roo.util.JSON#decode}
12788 * @member Roo decode
12790 Roo.decode = Roo.util.JSON.decode;
12793 * Ext JS Library 1.1.1
12794 * Copyright(c) 2006-2007, Ext JS, LLC.
12796 * Originally Released Under LGPL - original licence link has changed is not relivant.
12799 * <script type="text/javascript">
12803 * @class Roo.util.Format
12804 * Reusable data formatting functions
12807 Roo.util.Format = function(){
12808 var trimRe = /^\s+|\s+$/g;
12811 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12812 * @param {String} value The string to truncate
12813 * @param {Number} length The maximum length to allow before truncating
12814 * @return {String} The converted text
12816 ellipsis : function(value, len){
12817 if(value && value.length > len){
12818 return value.substr(0, len-3)+"...";
12824 * Checks a reference and converts it to empty string if it is undefined
12825 * @param {Mixed} value Reference to check
12826 * @return {Mixed} Empty string if converted, otherwise the original value
12828 undef : function(value){
12829 return typeof value != "undefined" ? value : "";
12833 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12834 * @param {String} value The string to encode
12835 * @return {String} The encoded text
12837 htmlEncode : function(value){
12838 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12842 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12843 * @param {String} value The string to decode
12844 * @return {String} The decoded text
12846 htmlDecode : function(value){
12847 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12851 * Trims any whitespace from either side of a string
12852 * @param {String} value The text to trim
12853 * @return {String} The trimmed text
12855 trim : function(value){
12856 return String(value).replace(trimRe, "");
12860 * Returns a substring from within an original string
12861 * @param {String} value The original text
12862 * @param {Number} start The start index of the substring
12863 * @param {Number} length The length of the substring
12864 * @return {String} The substring
12866 substr : function(value, start, length){
12867 return String(value).substr(start, length);
12871 * Converts a string to all lower case letters
12872 * @param {String} value The text to convert
12873 * @return {String} The converted text
12875 lowercase : function(value){
12876 return String(value).toLowerCase();
12880 * Converts a string to all upper case letters
12881 * @param {String} value The text to convert
12882 * @return {String} The converted text
12884 uppercase : function(value){
12885 return String(value).toUpperCase();
12889 * Converts the first character only of a string to upper case
12890 * @param {String} value The text to convert
12891 * @return {String} The converted text
12893 capitalize : function(value){
12894 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
12898 call : function(value, fn){
12899 if(arguments.length > 2){
12900 var args = Array.prototype.slice.call(arguments, 2);
12901 args.unshift(value);
12903 return /** eval:var:value */ eval(fn).apply(window, args);
12905 /** eval:var:value */
12906 return /** eval:var:value */ eval(fn).call(window, value);
12911 * Format a number as US currency
12912 * @param {Number/String} value The numeric value to format
12913 * @return {String} The formatted currency string
12915 usMoney : function(v){
12916 v = (Math.round((v-0)*100))/100;
12917 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
12919 var ps = v.split('.');
12921 var sub = ps[1] ? '.'+ ps[1] : '.00';
12922 var r = /(\d+)(\d{3})/;
12923 while (r.test(whole)) {
12924 whole = whole.replace(r, '$1' + ',' + '$2');
12926 return "$" + whole + sub ;
12930 * Parse a value into a formatted date using the specified format pattern.
12931 * @param {Mixed} value The value to format
12932 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
12933 * @return {String} The formatted date string
12935 date : function(v, format){
12939 if(!(v instanceof Date)){
12940 v = new Date(Date.parse(v));
12942 return v.dateFormat(format || "m/d/Y");
12946 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
12947 * @param {String} format Any valid date format string
12948 * @return {Function} The date formatting function
12950 dateRenderer : function(format){
12951 return function(v){
12952 return Roo.util.Format.date(v, format);
12957 stripTagsRE : /<\/?[^>]+>/gi,
12960 * Strips all HTML tags
12961 * @param {Mixed} value The text from which to strip tags
12962 * @return {String} The stripped text
12964 stripTags : function(v){
12965 return !v ? v : String(v).replace(this.stripTagsRE, "");
12970 * Ext JS Library 1.1.1
12971 * Copyright(c) 2006-2007, Ext JS, LLC.
12973 * Originally Released Under LGPL - original licence link has changed is not relivant.
12976 * <script type="text/javascript">
12983 * @class Roo.MasterTemplate
12984 * @extends Roo.Template
12985 * Provides a template that can have child templates. The syntax is:
12987 var t = new Roo.MasterTemplate(
12988 '<select name="{name}">',
12989 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
12992 t.add('options', {value: 'foo', text: 'bar'});
12993 // or you can add multiple child elements in one shot
12994 t.addAll('options', [
12995 {value: 'foo', text: 'bar'},
12996 {value: 'foo2', text: 'bar2'},
12997 {value: 'foo3', text: 'bar3'}
12999 // then append, applying the master template values
13000 t.append('my-form', {name: 'my-select'});
13002 * A name attribute for the child template is not required if you have only one child
13003 * template or you want to refer to them by index.
13005 Roo.MasterTemplate = function(){
13006 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13007 this.originalHtml = this.html;
13009 var m, re = this.subTemplateRe;
13012 while(m = re.exec(this.html)){
13013 var name = m[1], content = m[2];
13018 tpl : new Roo.Template(content)
13021 st[name] = st[subIndex];
13023 st[subIndex].tpl.compile();
13024 st[subIndex].tpl.call = this.call.createDelegate(this);
13027 this.subCount = subIndex;
13030 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13032 * The regular expression used to match sub templates
13036 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13039 * Applies the passed values to a child template.
13040 * @param {String/Number} name (optional) The name or index of the child template
13041 * @param {Array/Object} values The values to be applied to the template
13042 * @return {MasterTemplate} this
13044 add : function(name, values){
13045 if(arguments.length == 1){
13046 values = arguments[0];
13049 var s = this.subs[name];
13050 s.buffer[s.buffer.length] = s.tpl.apply(values);
13055 * Applies all the passed values to a child template.
13056 * @param {String/Number} name (optional) The name or index of the child template
13057 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13058 * @param {Boolean} reset (optional) True to reset the template first
13059 * @return {MasterTemplate} this
13061 fill : function(name, values, reset){
13063 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13071 for(var i = 0, len = values.length; i < len; i++){
13072 this.add(name, values[i]);
13078 * Resets the template for reuse
13079 * @return {MasterTemplate} this
13081 reset : function(){
13083 for(var i = 0; i < this.subCount; i++){
13089 applyTemplate : function(values){
13091 var replaceIndex = -1;
13092 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13093 return s[++replaceIndex].buffer.join("");
13095 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13098 apply : function(){
13099 return this.applyTemplate.apply(this, arguments);
13102 compile : function(){return this;}
13106 * Alias for fill().
13109 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13111 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13112 * var tpl = Roo.MasterTemplate.from('element-id');
13113 * @param {String/HTMLElement} el
13114 * @param {Object} config
13117 Roo.MasterTemplate.from = function(el, config){
13118 el = Roo.getDom(el);
13119 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13122 * Ext JS Library 1.1.1
13123 * Copyright(c) 2006-2007, Ext JS, LLC.
13125 * Originally Released Under LGPL - original licence link has changed is not relivant.
13128 * <script type="text/javascript">
13133 * @class Roo.util.CSS
13134 * Utility class for manipulating CSS rules
13137 Roo.util.CSS = function(){
13139 var doc = document;
13141 var camelRe = /(-[a-z])/gi;
13142 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13146 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13147 * tag and appended to the HEAD of the document.
13148 * @param {String} cssText The text containing the css rules
13149 * @param {String} id An id to add to the stylesheet for later removal
13150 * @return {StyleSheet}
13152 createStyleSheet : function(cssText, id){
13154 var head = doc.getElementsByTagName("head")[0];
13155 var rules = doc.createElement("style");
13156 rules.setAttribute("type", "text/css");
13158 rules.setAttribute("id", id);
13161 head.appendChild(rules);
13162 ss = rules.styleSheet;
13163 ss.cssText = cssText;
13166 rules.appendChild(doc.createTextNode(cssText));
13168 rules.cssText = cssText;
13170 head.appendChild(rules);
13171 ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13173 this.cacheStyleSheet(ss);
13178 * Removes a style or link tag by id
13179 * @param {String} id The id of the tag
13181 removeStyleSheet : function(id){
13182 var existing = doc.getElementById(id);
13184 existing.parentNode.removeChild(existing);
13189 * Dynamically swaps an existing stylesheet reference for a new one
13190 * @param {String} id The id of an existing link tag to remove
13191 * @param {String} url The href of the new stylesheet to include
13193 swapStyleSheet : function(id, url){
13194 this.removeStyleSheet(id);
13195 var ss = doc.createElement("link");
13196 ss.setAttribute("rel", "stylesheet");
13197 ss.setAttribute("type", "text/css");
13198 ss.setAttribute("id", id);
13199 ss.setAttribute("href", url);
13200 doc.getElementsByTagName("head")[0].appendChild(ss);
13204 * Refresh the rule cache if you have dynamically added stylesheets
13205 * @return {Object} An object (hash) of rules indexed by selector
13207 refreshCache : function(){
13208 return this.getRules(true);
13212 cacheStyleSheet : function(ss){
13216 try{// try catch for cross domain access issue
13217 var ssRules = ss.cssRules || ss.rules;
13218 for(var j = ssRules.length-1; j >= 0; --j){
13219 rules[ssRules[j].selectorText] = ssRules[j];
13225 * Gets all css rules for the document
13226 * @param {Boolean} refreshCache true to refresh the internal cache
13227 * @return {Object} An object (hash) of rules indexed by selector
13229 getRules : function(refreshCache){
13230 if(rules == null || refreshCache){
13232 var ds = doc.styleSheets;
13233 for(var i =0, len = ds.length; i < len; i++){
13235 this.cacheStyleSheet(ds[i]);
13243 * Gets an an individual CSS rule by selector(s)
13244 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13245 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13246 * @return {CSSRule} The CSS rule or null if one is not found
13248 getRule : function(selector, refreshCache){
13249 var rs = this.getRules(refreshCache);
13250 if(!(selector instanceof Array)){
13251 return rs[selector];
13253 for(var i = 0; i < selector.length; i++){
13254 if(rs[selector[i]]){
13255 return rs[selector[i]];
13263 * Updates a rule property
13264 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13265 * @param {String} property The css property
13266 * @param {String} value The new value for the property
13267 * @return {Boolean} true If a rule was found and updated
13269 updateRule : function(selector, property, value){
13270 if(!(selector instanceof Array)){
13271 var rule = this.getRule(selector);
13273 rule.style[property.replace(camelRe, camelFn)] = value;
13277 for(var i = 0; i < selector.length; i++){
13278 if(this.updateRule(selector[i], property, value)){
13288 * Ext JS Library 1.1.1
13289 * Copyright(c) 2006-2007, Ext JS, LLC.
13291 * Originally Released Under LGPL - original licence link has changed is not relivant.
13294 * <script type="text/javascript">
13300 * @class Roo.util.ClickRepeater
13301 * @extends Roo.util.Observable
13303 * A wrapper class which can be applied to any element. Fires a "click" event while the
13304 * mouse is pressed. The interval between firings may be specified in the config but
13305 * defaults to 10 milliseconds.
13307 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13309 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13310 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13311 * Similar to an autorepeat key delay.
13312 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13313 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13314 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13315 * "interval" and "delay" are ignored. "immediate" is honored.
13316 * @cfg {Boolean} preventDefault True to prevent the default click event
13317 * @cfg {Boolean} stopDefault True to stop the default click event
13320 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13321 * 2007-02-02 jvs Renamed to ClickRepeater
13322 * 2007-02-03 jvs Modifications for FF Mac and Safari
13325 * @param {String/HTMLElement/Element} el The element to listen on
13326 * @param {Object} config
13328 Roo.util.ClickRepeater = function(el, config)
13330 this.el = Roo.get(el);
13331 this.el.unselectable();
13333 Roo.apply(this, config);
13338 * Fires when the mouse button is depressed.
13339 * @param {Roo.util.ClickRepeater} this
13341 "mousedown" : true,
13344 * Fires on a specified interval during the time the element is pressed.
13345 * @param {Roo.util.ClickRepeater} this
13350 * Fires when the mouse key is released.
13351 * @param {Roo.util.ClickRepeater} this
13356 this.el.on("mousedown", this.handleMouseDown, this);
13357 if(this.preventDefault || this.stopDefault){
13358 this.el.on("click", function(e){
13359 if(this.preventDefault){
13360 e.preventDefault();
13362 if(this.stopDefault){
13368 // allow inline handler
13370 this.on("click", this.handler, this.scope || this);
13373 Roo.util.ClickRepeater.superclass.constructor.call(this);
13376 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13379 preventDefault : true,
13380 stopDefault : false,
13384 handleMouseDown : function(){
13385 clearTimeout(this.timer);
13387 if(this.pressClass){
13388 this.el.addClass(this.pressClass);
13390 this.mousedownTime = new Date();
13392 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13393 this.el.on("mouseout", this.handleMouseOut, this);
13395 this.fireEvent("mousedown", this);
13396 this.fireEvent("click", this);
13398 this.timer = this.click.defer(this.delay || this.interval, this);
13402 click : function(){
13403 this.fireEvent("click", this);
13404 this.timer = this.click.defer(this.getInterval(), this);
13408 getInterval: function(){
13409 if(!this.accelerate){
13410 return this.interval;
13412 var pressTime = this.mousedownTime.getElapsed();
13413 if(pressTime < 500){
13415 }else if(pressTime < 1700){
13417 }else if(pressTime < 2600){
13419 }else if(pressTime < 3500){
13421 }else if(pressTime < 4400){
13423 }else if(pressTime < 5300){
13425 }else if(pressTime < 6200){
13433 handleMouseOut : function(){
13434 clearTimeout(this.timer);
13435 if(this.pressClass){
13436 this.el.removeClass(this.pressClass);
13438 this.el.on("mouseover", this.handleMouseReturn, this);
13442 handleMouseReturn : function(){
13443 this.el.un("mouseover", this.handleMouseReturn);
13444 if(this.pressClass){
13445 this.el.addClass(this.pressClass);
13451 handleMouseUp : function(){
13452 clearTimeout(this.timer);
13453 this.el.un("mouseover", this.handleMouseReturn);
13454 this.el.un("mouseout", this.handleMouseOut);
13455 Roo.get(document).un("mouseup", this.handleMouseUp);
13456 this.el.removeClass(this.pressClass);
13457 this.fireEvent("mouseup", this);
13461 * Ext JS Library 1.1.1
13462 * Copyright(c) 2006-2007, Ext JS, LLC.
13464 * Originally Released Under LGPL - original licence link has changed is not relivant.
13467 * <script type="text/javascript">
13472 * @class Roo.KeyNav
13473 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13474 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13475 * way to implement custom navigation schemes for any UI component.</p>
13476 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13477 * pageUp, pageDown, del, home, end. Usage:</p>
13479 var nav = new Roo.KeyNav("my-element", {
13480 "left" : function(e){
13481 this.moveLeft(e.ctrlKey);
13483 "right" : function(e){
13484 this.moveRight(e.ctrlKey);
13486 "enter" : function(e){
13493 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13494 * @param {Object} config The config
13496 Roo.KeyNav = function(el, config){
13497 this.el = Roo.get(el);
13498 Roo.apply(this, config);
13499 if(!this.disabled){
13500 this.disabled = true;
13505 Roo.KeyNav.prototype = {
13507 * @cfg {Boolean} disabled
13508 * True to disable this KeyNav instance (defaults to false)
13512 * @cfg {String} defaultEventAction
13513 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13514 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13515 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13517 defaultEventAction: "stopEvent",
13519 * @cfg {Boolean} forceKeyDown
13520 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13521 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13522 * handle keydown instead of keypress.
13524 forceKeyDown : false,
13527 prepareEvent : function(e){
13528 var k = e.getKey();
13529 var h = this.keyToHandler[k];
13530 //if(h && this[h]){
13531 // e.stopPropagation();
13533 if(Roo.isSafari && h && k >= 37 && k <= 40){
13539 relay : function(e){
13540 var k = e.getKey();
13541 var h = this.keyToHandler[k];
13543 if(this.doRelay(e, this[h], h) !== true){
13544 e[this.defaultEventAction]();
13550 doRelay : function(e, h, hname){
13551 return h.call(this.scope || this, e);
13554 // possible handlers
13568 // quick lookup hash
13585 * Enable this KeyNav
13587 enable: function(){
13589 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13590 // the EventObject will normalize Safari automatically
13591 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13592 this.el.on("keydown", this.relay, this);
13594 this.el.on("keydown", this.prepareEvent, this);
13595 this.el.on("keypress", this.relay, this);
13597 this.disabled = false;
13602 * Disable this KeyNav
13604 disable: function(){
13605 if(!this.disabled){
13606 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13607 this.el.un("keydown", this.relay);
13609 this.el.un("keydown", this.prepareEvent);
13610 this.el.un("keypress", this.relay);
13612 this.disabled = true;
13617 * Ext JS Library 1.1.1
13618 * Copyright(c) 2006-2007, Ext JS, LLC.
13620 * Originally Released Under LGPL - original licence link has changed is not relivant.
13623 * <script type="text/javascript">
13628 * @class Roo.KeyMap
13629 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13630 * The constructor accepts the same config object as defined by {@link #addBinding}.
13631 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13632 * combination it will call the function with this signature (if the match is a multi-key
13633 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13634 * A KeyMap can also handle a string representation of keys.<br />
13637 // map one key by key code
13638 var map = new Roo.KeyMap("my-element", {
13639 key: 13, // or Roo.EventObject.ENTER
13644 // map multiple keys to one action by string
13645 var map = new Roo.KeyMap("my-element", {
13651 // map multiple keys to multiple actions by strings and array of codes
13652 var map = new Roo.KeyMap("my-element", [
13655 fn: function(){ alert("Return was pressed"); }
13658 fn: function(){ alert('a, b or c was pressed'); }
13663 fn: function(){ alert('Control + shift + tab was pressed.'); }
13667 * <b>Note: A KeyMap starts enabled</b>
13669 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13670 * @param {Object} config The config (see {@link #addBinding})
13671 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13673 Roo.KeyMap = function(el, config, eventName){
13674 this.el = Roo.get(el);
13675 this.eventName = eventName || "keydown";
13676 this.bindings = [];
13678 this.addBinding(config);
13683 Roo.KeyMap.prototype = {
13685 * True to stop the event from bubbling and prevent the default browser action if the
13686 * key was handled by the KeyMap (defaults to false)
13692 * Add a new binding to this KeyMap. The following config object properties are supported:
13694 Property Type Description
13695 ---------- --------------- ----------------------------------------------------------------------
13696 key String/Array A single keycode or an array of keycodes to handle
13697 shift Boolean True to handle key only when shift is pressed (defaults to false)
13698 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13699 alt Boolean True to handle key only when alt is pressed (defaults to false)
13700 fn Function The function to call when KeyMap finds the expected key combination
13701 scope Object The scope of the callback function
13707 var map = new Roo.KeyMap(document, {
13708 key: Roo.EventObject.ENTER,
13713 //Add a new binding to the existing KeyMap later
13721 * @param {Object/Array} config A single KeyMap config or an array of configs
13723 addBinding : function(config){
13724 if(config instanceof Array){
13725 for(var i = 0, len = config.length; i < len; i++){
13726 this.addBinding(config[i]);
13730 var keyCode = config.key,
13731 shift = config.shift,
13732 ctrl = config.ctrl,
13735 scope = config.scope;
13736 if(typeof keyCode == "string"){
13738 var keyString = keyCode.toUpperCase();
13739 for(var j = 0, len = keyString.length; j < len; j++){
13740 ks.push(keyString.charCodeAt(j));
13744 var keyArray = keyCode instanceof Array;
13745 var handler = function(e){
13746 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13747 var k = e.getKey();
13749 for(var i = 0, len = keyCode.length; i < len; i++){
13750 if(keyCode[i] == k){
13751 if(this.stopEvent){
13754 fn.call(scope || window, k, e);
13760 if(this.stopEvent){
13763 fn.call(scope || window, k, e);
13768 this.bindings.push(handler);
13772 * Shorthand for adding a single key listener
13773 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13774 * following options:
13775 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13776 * @param {Function} fn The function to call
13777 * @param {Object} scope (optional) The scope of the function
13779 on : function(key, fn, scope){
13780 var keyCode, shift, ctrl, alt;
13781 if(typeof key == "object" && !(key instanceof Array)){
13800 handleKeyDown : function(e){
13801 if(this.enabled){ //just in case
13802 var b = this.bindings;
13803 for(var i = 0, len = b.length; i < len; i++){
13804 b[i].call(this, e);
13810 * Returns true if this KeyMap is enabled
13811 * @return {Boolean}
13813 isEnabled : function(){
13814 return this.enabled;
13818 * Enables this KeyMap
13820 enable: function(){
13822 this.el.on(this.eventName, this.handleKeyDown, this);
13823 this.enabled = true;
13828 * Disable this KeyMap
13830 disable: function(){
13832 this.el.removeListener(this.eventName, this.handleKeyDown, this);
13833 this.enabled = false;
13838 * Ext JS Library 1.1.1
13839 * Copyright(c) 2006-2007, Ext JS, LLC.
13841 * Originally Released Under LGPL - original licence link has changed is not relivant.
13844 * <script type="text/javascript">
13849 * @class Roo.util.TextMetrics
13850 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
13851 * wide, in pixels, a given block of text will be.
13854 Roo.util.TextMetrics = function(){
13858 * Measures the size of the specified text
13859 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
13860 * that can affect the size of the rendered text
13861 * @param {String} text The text to measure
13862 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13863 * in order to accurately measure the text height
13864 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13866 measure : function(el, text, fixedWidth){
13868 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
13871 shared.setFixedWidth(fixedWidth || 'auto');
13872 return shared.getSize(text);
13876 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
13877 * the overhead of multiple calls to initialize the style properties on each measurement.
13878 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
13879 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13880 * in order to accurately measure the text height
13881 * @return {Roo.util.TextMetrics.Instance} instance The new instance
13883 createInstance : function(el, fixedWidth){
13884 return Roo.util.TextMetrics.Instance(el, fixedWidth);
13891 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
13892 var ml = new Roo.Element(document.createElement('div'));
13893 document.body.appendChild(ml.dom);
13894 ml.position('absolute');
13895 ml.setLeftTop(-1000, -1000);
13899 ml.setWidth(fixedWidth);
13904 * Returns the size of the specified text based on the internal element's style and width properties
13905 * @memberOf Roo.util.TextMetrics.Instance#
13906 * @param {String} text The text to measure
13907 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13909 getSize : function(text){
13911 var s = ml.getSize();
13917 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
13918 * that can affect the size of the rendered text
13919 * @memberOf Roo.util.TextMetrics.Instance#
13920 * @param {String/HTMLElement} el The element, dom node or id
13922 bind : function(el){
13924 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
13929 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
13930 * to set a fixed width in order to accurately measure the text height.
13931 * @memberOf Roo.util.TextMetrics.Instance#
13932 * @param {Number} width The width to set on the element
13934 setFixedWidth : function(width){
13935 ml.setWidth(width);
13939 * Returns the measured width of the specified text
13940 * @memberOf Roo.util.TextMetrics.Instance#
13941 * @param {String} text The text to measure
13942 * @return {Number} width The width in pixels
13944 getWidth : function(text){
13945 ml.dom.style.width = 'auto';
13946 return this.getSize(text).width;
13950 * Returns the measured height of the specified text. For multiline text, be sure to call
13951 * {@link #setFixedWidth} if necessary.
13952 * @memberOf Roo.util.TextMetrics.Instance#
13953 * @param {String} text The text to measure
13954 * @return {Number} height The height in pixels
13956 getHeight : function(text){
13957 return this.getSize(text).height;
13961 instance.bind(bindTo);
13966 // backwards compat
13967 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
13969 * Ext JS Library 1.1.1
13970 * Copyright(c) 2006-2007, Ext JS, LLC.
13972 * Originally Released Under LGPL - original licence link has changed is not relivant.
13975 * <script type="text/javascript">
13979 * @class Roo.state.Provider
13980 * Abstract base class for state provider implementations. This class provides methods
13981 * for encoding and decoding <b>typed</b> variables including dates and defines the
13982 * Provider interface.
13984 Roo.state.Provider = function(){
13986 * @event statechange
13987 * Fires when a state change occurs.
13988 * @param {Provider} this This state provider
13989 * @param {String} key The state key which was changed
13990 * @param {String} value The encoded value for the state
13993 "statechange": true
13996 Roo.state.Provider.superclass.constructor.call(this);
13998 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14000 * Returns the current value for a key
14001 * @param {String} name The key name
14002 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14003 * @return {Mixed} The state data
14005 get : function(name, defaultValue){
14006 return typeof this.state[name] == "undefined" ?
14007 defaultValue : this.state[name];
14011 * Clears a value from the state
14012 * @param {String} name The key name
14014 clear : function(name){
14015 delete this.state[name];
14016 this.fireEvent("statechange", this, name, null);
14020 * Sets the value for a key
14021 * @param {String} name The key name
14022 * @param {Mixed} value The value to set
14024 set : function(name, value){
14025 this.state[name] = value;
14026 this.fireEvent("statechange", this, name, value);
14030 * Decodes a string previously encoded with {@link #encodeValue}.
14031 * @param {String} value The value to decode
14032 * @return {Mixed} The decoded value
14034 decodeValue : function(cookie){
14035 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14036 var matches = re.exec(unescape(cookie));
14037 if(!matches || !matches[1]) return; // non state cookie
14038 var type = matches[1];
14039 var v = matches[2];
14042 return parseFloat(v);
14044 return new Date(Date.parse(v));
14049 var values = v.split("^");
14050 for(var i = 0, len = values.length; i < len; i++){
14051 all.push(this.decodeValue(values[i]));
14056 var values = v.split("^");
14057 for(var i = 0, len = values.length; i < len; i++){
14058 var kv = values[i].split("=");
14059 all[kv[0]] = this.decodeValue(kv[1]);
14068 * Encodes a value including type information. Decode with {@link #decodeValue}.
14069 * @param {Mixed} value The value to encode
14070 * @return {String} The encoded value
14072 encodeValue : function(v){
14074 if(typeof v == "number"){
14076 }else if(typeof v == "boolean"){
14077 enc = "b:" + (v ? "1" : "0");
14078 }else if(v instanceof Date){
14079 enc = "d:" + v.toGMTString();
14080 }else if(v instanceof Array){
14082 for(var i = 0, len = v.length; i < len; i++){
14083 flat += this.encodeValue(v[i]);
14084 if(i != len-1) flat += "^";
14087 }else if(typeof v == "object"){
14090 if(typeof v[key] != "function"){
14091 flat += key + "=" + this.encodeValue(v[key]) + "^";
14094 enc = "o:" + flat.substring(0, flat.length-1);
14098 return escape(enc);
14104 * Ext JS Library 1.1.1
14105 * Copyright(c) 2006-2007, Ext JS, LLC.
14107 * Originally Released Under LGPL - original licence link has changed is not relivant.
14110 * <script type="text/javascript">
14113 * @class Roo.state.Manager
14114 * This is the global state manager. By default all components that are "state aware" check this class
14115 * for state information if you don't pass them a custom state provider. In order for this class
14116 * to be useful, it must be initialized with a provider when your application initializes.
14118 // in your initialization function
14120 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14122 // supposed you have a {@link Roo.BorderLayout}
14123 var layout = new Roo.BorderLayout(...);
14124 layout.restoreState();
14125 // or a {Roo.BasicDialog}
14126 var dialog = new Roo.BasicDialog(...);
14127 dialog.restoreState();
14131 Roo.state.Manager = function(){
14132 var provider = new Roo.state.Provider();
14136 * Configures the default state provider for your application
14137 * @param {Provider} stateProvider The state provider to set
14139 setProvider : function(stateProvider){
14140 provider = stateProvider;
14144 * Returns the current value for a key
14145 * @param {String} name The key name
14146 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14147 * @return {Mixed} The state data
14149 get : function(key, defaultValue){
14150 return provider.get(key, defaultValue);
14154 * Sets the value for a key
14155 * @param {String} name The key name
14156 * @param {Mixed} value The state data
14158 set : function(key, value){
14159 provider.set(key, value);
14163 * Clears a value from the state
14164 * @param {String} name The key name
14166 clear : function(key){
14167 provider.clear(key);
14171 * Gets the currently configured state provider
14172 * @return {Provider} The state provider
14174 getProvider : function(){
14181 * Ext JS Library 1.1.1
14182 * Copyright(c) 2006-2007, Ext JS, LLC.
14184 * Originally Released Under LGPL - original licence link has changed is not relivant.
14187 * <script type="text/javascript">
14190 * @class Roo.state.CookieProvider
14191 * @extends Roo.state.Provider
14192 * The default Provider implementation which saves state via cookies.
14195 var cp = new Roo.state.CookieProvider({
14197 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14198 domain: "roojs.com"
14200 Roo.state.Manager.setProvider(cp);
14202 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14203 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14204 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14205 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14206 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14207 * domain the page is running on including the 'www' like 'www.roojs.com')
14208 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14210 * Create a new CookieProvider
14211 * @param {Object} config The configuration object
14213 Roo.state.CookieProvider = function(config){
14214 Roo.state.CookieProvider.superclass.constructor.call(this);
14216 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14217 this.domain = null;
14218 this.secure = false;
14219 Roo.apply(this, config);
14220 this.state = this.readCookies();
14223 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14225 set : function(name, value){
14226 if(typeof value == "undefined" || value === null){
14230 this.setCookie(name, value);
14231 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14235 clear : function(name){
14236 this.clearCookie(name);
14237 Roo.state.CookieProvider.superclass.clear.call(this, name);
14241 readCookies : function(){
14243 var c = document.cookie + ";";
14244 var re = /\s?(.*?)=(.*?);/g;
14246 while((matches = re.exec(c)) != null){
14247 var name = matches[1];
14248 var value = matches[2];
14249 if(name && name.substring(0,3) == "ys-"){
14250 cookies[name.substr(3)] = this.decodeValue(value);
14257 setCookie : function(name, value){
14258 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14259 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14260 ((this.path == null) ? "" : ("; path=" + this.path)) +
14261 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14262 ((this.secure == true) ? "; secure" : "");
14266 clearCookie : function(name){
14267 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14268 ((this.path == null) ? "" : ("; path=" + this.path)) +
14269 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14270 ((this.secure == true) ? "; secure" : "");