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);
849 * Ext JS Library 1.1.1
850 * Copyright(c) 2006-2007, Ext JS, LLC.
852 * Originally Released Under LGPL - original licence link has changed is not relivant.
855 * <script type="text/javascript">
861 * The date parsing and format syntax is a subset of
862 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
863 * supported will provide results equivalent to their PHP versions.
865 * Following is the list of all currently supported formats:
868 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
870 Format Output Description
871 ------ ---------- --------------------------------------------------------------
872 d 10 Day of the month, 2 digits with leading zeros
873 D Wed A textual representation of a day, three letters
874 j 10 Day of the month without leading zeros
875 l Wednesday A full textual representation of the day of the week
876 S th English ordinal day of month suffix, 2 chars (use with j)
877 w 3 Numeric representation of the day of the week
878 z 9 The julian date, or day of the year (0-365)
879 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
880 F January A full textual representation of the month
881 m 01 Numeric representation of a month, with leading zeros
882 M Jan Month name abbreviation, three letters
883 n 1 Numeric representation of a month, without leading zeros
884 t 31 Number of days in the given month
885 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
886 Y 2007 A full numeric representation of a year, 4 digits
887 y 07 A two digit representation of a year
888 a pm Lowercase Ante meridiem and Post meridiem
889 A PM Uppercase Ante meridiem and Post meridiem
890 g 3 12-hour format of an hour without leading zeros
891 G 15 24-hour format of an hour without leading zeros
892 h 03 12-hour format of an hour with leading zeros
893 H 15 24-hour format of an hour with leading zeros
894 i 05 Minutes with leading zeros
895 s 01 Seconds, with leading zeros
896 O -0600 Difference to Greenwich time (GMT) in hours
897 T CST Timezone setting of the machine running the code
898 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
901 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
903 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
904 document.write(dt.format('Y-m-d')); //2007-01-10
905 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
906 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
909 * Here are some standard date/time patterns that you might find helpful. They
910 * are not part of the source of Date.js, but to use them you can simply copy this
911 * block of code into any script that is included after Date.js and they will also become
912 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
915 ISO8601Long:"Y-m-d H:i:s",
916 ISO8601Short:"Y-m-d",
918 LongDate: "l, F d, Y",
919 FullDateTime: "l, F d, Y g:i:s A",
923 SortableDateTime: "Y-m-d\\TH:i:s",
924 UniversalSortableDateTime: "Y-m-d H:i:sO",
932 document.write(dt.format(Date.patterns.ShortDate));
937 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
938 * They generate precompiled functions from date formats instead of parsing and
939 * processing the pattern every time you format a date. These functions are available
940 * on every Date object (any javascript function).
942 * The original article and download are here:
943 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
950 Returns the number of milliseconds between this date and date
951 @param {Date} date (optional) Defaults to now
952 @return {Number} The diff in milliseconds
953 @member Date getElapsed
955 Date.prototype.getElapsed = function(date) {
956 return Math.abs((date || new Date()).getTime()-this.getTime());
958 // was in date file..
962 Date.parseFunctions = {count:0};
964 Date.parseRegexes = [];
966 Date.formatFunctions = {count:0};
969 Date.prototype.dateFormat = function(format) {
970 if (Date.formatFunctions[format] == null) {
971 Date.createNewFormat(format);
973 var func = Date.formatFunctions[format];
979 * Formats a date given the supplied format string
980 * @param {String} format The format string
981 * @return {String} The formatted date
984 Date.prototype.format = Date.prototype.dateFormat;
987 Date.createNewFormat = function(format) {
988 var funcName = "format" + Date.formatFunctions.count++;
989 Date.formatFunctions[format] = funcName;
990 var code = "Date.prototype." + funcName + " = function(){return ";
993 for (var i = 0; i < format.length; ++i) {
994 ch = format.charAt(i);
995 if (!special && ch == "\\") {
1000 code += "'" + String.escape(ch) + "' + ";
1003 code += Date.getFormatCode(ch);
1006 /** eval:var:zzzzzzzzzzzzz */
1007 eval(code.substring(0, code.length - 3) + ";}");
1011 Date.getFormatCode = function(character) {
1012 switch (character) {
1014 return "String.leftPad(this.getDate(), 2, '0') + ";
1016 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1018 return "this.getDate() + ";
1020 return "Date.dayNames[this.getDay()] + ";
1022 return "this.getSuffix() + ";
1024 return "this.getDay() + ";
1026 return "this.getDayOfYear() + ";
1028 return "this.getWeekOfYear() + ";
1030 return "Date.monthNames[this.getMonth()] + ";
1032 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1034 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1036 return "(this.getMonth() + 1) + ";
1038 return "this.getDaysInMonth() + ";
1040 return "(this.isLeapYear() ? 1 : 0) + ";
1042 return "this.getFullYear() + ";
1044 return "('' + this.getFullYear()).substring(2, 4) + ";
1046 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1048 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1050 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1052 return "this.getHours() + ";
1054 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1056 return "String.leftPad(this.getHours(), 2, '0') + ";
1058 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1060 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1062 return "this.getGMTOffset() + ";
1064 return "this.getTimezone() + ";
1066 return "(this.getTimezoneOffset() * -60) + ";
1068 return "'" + String.escape(character) + "' + ";
1073 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1074 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1075 * the date format that is not specified will default to the current date value for that part. Time parts can also
1076 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1077 * string or the parse operation will fail.
1080 //dt = Fri May 25 2007 (current date)
1081 var dt = new Date();
1083 //dt = Thu May 25 2006 (today's month/day in 2006)
1084 dt = Date.parseDate("2006", "Y");
1086 //dt = Sun Jan 15 2006 (all date parts specified)
1087 dt = Date.parseDate("2006-1-15", "Y-m-d");
1089 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1090 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1092 * @param {String} input The unparsed date as a string
1093 * @param {String} format The format the date is in
1094 * @return {Date} The parsed date
1097 Date.parseDate = function(input, format) {
1098 if (Date.parseFunctions[format] == null) {
1099 Date.createParser(format);
1101 var func = Date.parseFunctions[format];
1102 return Date[func](input);
1107 Date.createParser = function(format) {
1108 var funcName = "parse" + Date.parseFunctions.count++;
1109 var regexNum = Date.parseRegexes.length;
1110 var currentGroup = 1;
1111 Date.parseFunctions[format] = funcName;
1113 var code = "Date." + funcName + " = function(input){\n"
1114 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1115 + "var d = new Date();\n"
1116 + "y = d.getFullYear();\n"
1117 + "m = d.getMonth();\n"
1118 + "d = d.getDate();\n"
1119 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1120 + "if (results && results.length > 0) {";
1123 var special = false;
1125 for (var i = 0; i < format.length; ++i) {
1126 ch = format.charAt(i);
1127 if (!special && ch == "\\") {
1132 regex += String.escape(ch);
1135 var obj = Date.formatCodeToRegex(ch, currentGroup);
1136 currentGroup += obj.g;
1138 if (obj.g && obj.c) {
1144 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1145 + "{v = new Date(y, m, d, h, i, s);}\n"
1146 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1147 + "{v = new Date(y, m, d, h, i);}\n"
1148 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1149 + "{v = new Date(y, m, d, h);}\n"
1150 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1151 + "{v = new Date(y, m, d);}\n"
1152 + "else if (y >= 0 && m >= 0)\n"
1153 + "{v = new Date(y, m);}\n"
1154 + "else if (y >= 0)\n"
1155 + "{v = new Date(y);}\n"
1156 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1157 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1158 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1161 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1162 /** eval:var:zzzzzzzzzzzzz */
1167 Date.formatCodeToRegex = function(character, currentGroup) {
1168 switch (character) {
1172 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1175 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1176 s:"(\\d{1,2})"}; // day of month without leading zeroes
1179 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1180 s:"(\\d{2})"}; // day of month with leading zeroes
1184 s:"(?:" + Date.dayNames.join("|") + ")"};
1188 s:"(?:st|nd|rd|th)"};
1203 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1204 s:"(" + Date.monthNames.join("|") + ")"};
1207 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1208 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1211 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1212 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1215 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1216 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1227 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1231 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1232 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1236 c:"if (results[" + currentGroup + "] == 'am') {\n"
1237 + "if (h == 12) { h = 0; }\n"
1238 + "} else { if (h < 12) { h += 12; }}",
1242 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1243 + "if (h == 12) { h = 0; }\n"
1244 + "} else { if (h < 12) { h += 12; }}",
1249 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1250 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1254 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1255 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1258 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1262 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1267 "o = results[", currentGroup, "];\n",
1268 "var sn = o.substring(0,1);\n", // get + / - sign
1269 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1270 "var mn = o.substring(3,5) % 60;\n", // get minutes
1271 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1272 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1278 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1281 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1282 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1283 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1287 s:String.escape(character)};
1292 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1293 * @return {String} The abbreviated timezone name (e.g. 'CST')
1295 Date.prototype.getTimezone = function() {
1296 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1300 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1301 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1303 Date.prototype.getGMTOffset = function() {
1304 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1305 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1306 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1310 * Get the numeric day number of the year, adjusted for leap year.
1311 * @return {Number} 0 through 364 (365 in leap years)
1313 Date.prototype.getDayOfYear = function() {
1315 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1316 for (var i = 0; i < this.getMonth(); ++i) {
1317 num += Date.daysInMonth[i];
1319 return num + this.getDate() - 1;
1323 * Get the string representation of the numeric week number of the year
1324 * (equivalent to the format specifier 'W').
1325 * @return {String} '00' through '52'
1327 Date.prototype.getWeekOfYear = function() {
1328 // Skip to Thursday of this week
1329 var now = this.getDayOfYear() + (4 - this.getDay());
1330 // Find the first Thursday of the year
1331 var jan1 = new Date(this.getFullYear(), 0, 1);
1332 var then = (7 - jan1.getDay() + 4);
1333 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1337 * Whether or not the current date is in a leap year.
1338 * @return {Boolean} True if the current date is in a leap year, else false
1340 Date.prototype.isLeapYear = function() {
1341 var year = this.getFullYear();
1342 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1346 * Get the first day of the current month, adjusted for leap year. The returned value
1347 * is the numeric day index within the week (0-6) which can be used in conjunction with
1348 * the {@link #monthNames} array to retrieve the textual day name.
1351 var dt = new Date('1/10/2007');
1352 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1354 * @return {Number} The day number (0-6)
1356 Date.prototype.getFirstDayOfMonth = function() {
1357 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1358 return (day < 0) ? (day + 7) : day;
1362 * Get the last day of the current month, adjusted for leap year. The returned value
1363 * is the numeric day index within the week (0-6) which can be used in conjunction with
1364 * the {@link #monthNames} array to retrieve the textual day name.
1367 var dt = new Date('1/10/2007');
1368 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1370 * @return {Number} The day number (0-6)
1372 Date.prototype.getLastDayOfMonth = function() {
1373 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1374 return (day < 0) ? (day + 7) : day;
1379 * Get the first date of this date's month
1382 Date.prototype.getFirstDateOfMonth = function() {
1383 return new Date(this.getFullYear(), this.getMonth(), 1);
1387 * Get the last date of this date's month
1390 Date.prototype.getLastDateOfMonth = function() {
1391 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1394 * Get the number of days in the current month, adjusted for leap year.
1395 * @return {Number} The number of days in the month
1397 Date.prototype.getDaysInMonth = function() {
1398 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1399 return Date.daysInMonth[this.getMonth()];
1403 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1404 * @return {String} 'st, 'nd', 'rd' or 'th'
1406 Date.prototype.getSuffix = function() {
1407 switch (this.getDate()) {
1424 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1427 * An array of textual month names.
1428 * Override these values for international dates, for example...
1429 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1448 * An array of textual day names.
1449 * Override these values for international dates, for example...
1450 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1466 Date.monthNumbers = {
1481 * Creates and returns a new Date instance with the exact same date value as the called instance.
1482 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1483 * variable will also be changed. When the intention is to create a new variable that will not
1484 * modify the original instance, you should create a clone.
1486 * Example of correctly cloning a date:
1489 var orig = new Date('10/1/2006');
1492 document.write(orig); //returns 'Thu Oct 05 2006'!
1495 var orig = new Date('10/1/2006');
1496 var copy = orig.clone();
1498 document.write(orig); //returns 'Thu Oct 01 2006'
1500 * @return {Date} The new Date instance
1502 Date.prototype.clone = function() {
1503 return new Date(this.getTime());
1507 * Clears any time information from this date
1508 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1509 @return {Date} this or the clone
1511 Date.prototype.clearTime = function(clone){
1513 return this.clone().clearTime();
1518 this.setMilliseconds(0);
1523 // safari setMonth is broken
1525 Date.brokenSetMonth = Date.prototype.setMonth;
1526 Date.prototype.setMonth = function(num){
1528 var n = Math.ceil(-num);
1529 var back_year = Math.ceil(n/12);
1530 var month = (n % 12) ? 12 - n % 12 : 0 ;
1531 this.setFullYear(this.getFullYear() - back_year);
1532 return Date.brokenSetMonth.call(this, month);
1534 return Date.brokenSetMonth.apply(this, arguments);
1539 /** Date interval constant
1543 /** Date interval constant
1547 /** Date interval constant
1551 /** Date interval constant
1555 /** Date interval constant
1559 /** Date interval constant
1563 /** Date interval constant
1569 * Provides a convenient method of performing basic date arithmetic. This method
1570 * does not modify the Date instance being called - it creates and returns
1571 * a new Date instance containing the resulting date value.
1576 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1577 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1579 //Negative values will subtract correctly:
1580 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1581 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1583 //You can even chain several calls together in one line!
1584 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1585 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1588 * @param {String} interval A valid date interval enum value
1589 * @param {Number} value The amount to add to the current date
1590 * @return {Date} The new Date instance
1592 Date.prototype.add = function(interval, value){
1593 var d = this.clone();
1594 if (!interval || value === 0) return d;
1595 switch(interval.toLowerCase()){
1597 d.setMilliseconds(this.getMilliseconds() + value);
1600 d.setSeconds(this.getSeconds() + value);
1603 d.setMinutes(this.getMinutes() + value);
1606 d.setHours(this.getHours() + value);
1609 d.setDate(this.getDate() + value);
1612 var day = this.getDate();
1614 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1617 d.setMonth(this.getMonth() + value);
1620 d.setFullYear(this.getFullYear() + value);
1626 * Ext JS Library 1.1.1
1627 * Copyright(c) 2006-2007, Ext JS, LLC.
1629 * Originally Released Under LGPL - original licence link has changed is not relivant.
1632 * <script type="text/javascript">
1636 getViewWidth : function(full) {
1637 return full ? this.getDocumentWidth() : this.getViewportWidth();
1640 getViewHeight : function(full) {
1641 return full ? this.getDocumentHeight() : this.getViewportHeight();
1644 getDocumentHeight: function() {
1645 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1646 return Math.max(scrollHeight, this.getViewportHeight());
1649 getDocumentWidth: function() {
1650 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1651 return Math.max(scrollWidth, this.getViewportWidth());
1654 getViewportHeight: function() {
1655 var height = self.innerHeight;
1656 var mode = document.compatMode;
1658 if ((mode || Roo.isIE) && !Roo.isOpera) {
1659 height = (mode == "CSS1Compat") ?
1660 document.documentElement.clientHeight :
1661 document.body.clientHeight;
1667 getViewportWidth: function() {
1668 var width = self.innerWidth;
1669 var mode = document.compatMode;
1671 if (mode || Roo.isIE) {
1672 width = (mode == "CSS1Compat") ?
1673 document.documentElement.clientWidth :
1674 document.body.clientWidth;
1679 isAncestor : function(p, c) {
1686 if (p.contains && !Roo.isSafari) {
1687 return p.contains(c);
1688 } else if (p.compareDocumentPosition) {
1689 return !!(p.compareDocumentPosition(c) & 16);
1691 var parent = c.parentNode;
1696 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1699 parent = parent.parentNode;
1705 getRegion : function(el) {
1706 return Roo.lib.Region.getRegion(el);
1709 getY : function(el) {
1710 return this.getXY(el)[1];
1713 getX : function(el) {
1714 return this.getXY(el)[0];
1717 getXY : function(el) {
1718 var p, pe, b, scroll, bd = document.body;
1719 el = Roo.getDom(el);
1720 var fly = Roo.lib.AnimBase.fly;
1721 if (el.getBoundingClientRect) {
1722 b = el.getBoundingClientRect();
1723 scroll = fly(document).getScroll();
1724 return [b.left + scroll.left, b.top + scroll.top];
1730 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1737 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1744 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1745 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1752 if (p != el && pe.getStyle('overflow') != 'visible') {
1760 if (Roo.isSafari && hasAbsolute) {
1765 if (Roo.isGecko && !hasAbsolute) {
1767 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1768 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1772 while (p && p != bd) {
1773 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1785 setXY : function(el, xy) {
1786 el = Roo.fly(el, '_setXY');
1788 var pts = el.translatePoints(xy);
1789 if (xy[0] !== false) {
1790 el.dom.style.left = pts.left + "px";
1792 if (xy[1] !== false) {
1793 el.dom.style.top = pts.top + "px";
1797 setX : function(el, x) {
1798 this.setXY(el, [x, false]);
1801 setY : function(el, y) {
1802 this.setXY(el, [false, y]);
1806 * Portions of this file are based on pieces of Yahoo User Interface Library
1807 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1808 * YUI licensed under the BSD License:
1809 * http://developer.yahoo.net/yui/license.txt
1810 * <script type="text/javascript">
1814 Roo.lib.Event = function() {
1815 var loadComplete = false;
1817 var unloadListeners = [];
1819 var onAvailStack = [];
1821 var lastError = null;
1834 startInterval: function() {
1835 if (!this._interval) {
1837 var callback = function() {
1838 self._tryPreloadAttach();
1840 this._interval = setInterval(callback, this.POLL_INTERVAL);
1845 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1846 onAvailStack.push({ id: p_id,
1849 override: p_override,
1850 checkReady: false });
1852 retryCount = this.POLL_RETRYS;
1853 this.startInterval();
1857 addListener: function(el, eventName, fn) {
1858 el = Roo.getDom(el);
1863 if ("unload" == eventName) {
1864 unloadListeners[unloadListeners.length] =
1865 [el, eventName, fn];
1869 var wrappedFn = function(e) {
1870 return fn(Roo.lib.Event.getEvent(e));
1873 var li = [el, eventName, fn, wrappedFn];
1875 var index = listeners.length;
1876 listeners[index] = li;
1878 this.doAdd(el, eventName, wrappedFn, false);
1884 removeListener: function(el, eventName, fn) {
1887 el = Roo.getDom(el);
1890 return this.purgeElement(el, false, eventName);
1894 if ("unload" == eventName) {
1896 for (i = 0,len = unloadListeners.length; i < len; i++) {
1897 var li = unloadListeners[i];
1900 li[1] == eventName &&
1902 unloadListeners.splice(i, 1);
1910 var cacheItem = null;
1913 var index = arguments[3];
1915 if ("undefined" == typeof index) {
1916 index = this._getCacheIndex(el, eventName, fn);
1920 cacheItem = listeners[index];
1923 if (!el || !cacheItem) {
1927 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1929 delete listeners[index][this.WFN];
1930 delete listeners[index][this.FN];
1931 listeners.splice(index, 1);
1938 getTarget: function(ev, resolveTextNode) {
1939 ev = ev.browserEvent || ev;
1940 var t = ev.target || ev.srcElement;
1941 return this.resolveTextNode(t);
1945 resolveTextNode: function(node) {
1946 if (Roo.isSafari && node && 3 == node.nodeType) {
1947 return node.parentNode;
1954 getPageX: function(ev) {
1955 ev = ev.browserEvent || ev;
1957 if (!x && 0 !== x) {
1958 x = ev.clientX || 0;
1961 x += this.getScroll()[1];
1969 getPageY: function(ev) {
1970 ev = ev.browserEvent || ev;
1972 if (!y && 0 !== y) {
1973 y = ev.clientY || 0;
1976 y += this.getScroll()[0];
1985 getXY: function(ev) {
1986 ev = ev.browserEvent || ev;
1987 return [this.getPageX(ev), this.getPageY(ev)];
1991 getRelatedTarget: function(ev) {
1992 ev = ev.browserEvent || ev;
1993 var t = ev.relatedTarget;
1995 if (ev.type == "mouseout") {
1997 } else if (ev.type == "mouseover") {
2002 return this.resolveTextNode(t);
2006 getTime: function(ev) {
2007 ev = ev.browserEvent || ev;
2009 var t = new Date().getTime();
2013 this.lastError = ex;
2022 stopEvent: function(ev) {
2023 this.stopPropagation(ev);
2024 this.preventDefault(ev);
2028 stopPropagation: function(ev) {
2029 ev = ev.browserEvent || ev;
2030 if (ev.stopPropagation) {
2031 ev.stopPropagation();
2033 ev.cancelBubble = true;
2038 preventDefault: function(ev) {
2039 ev = ev.browserEvent || ev;
2040 if(ev.preventDefault) {
2041 ev.preventDefault();
2043 ev.returnValue = false;
2048 getEvent: function(e) {
2049 var ev = e || window.event;
2051 var c = this.getEvent.caller;
2053 ev = c.arguments[0];
2054 if (ev && Event == ev.constructor) {
2064 getCharCode: function(ev) {
2065 ev = ev.browserEvent || ev;
2066 return ev.charCode || ev.keyCode || 0;
2070 _getCacheIndex: function(el, eventName, fn) {
2071 for (var i = 0,len = listeners.length; i < len; ++i) {
2072 var li = listeners[i];
2074 li[this.FN] == fn &&
2075 li[this.EL] == el &&
2076 li[this.TYPE] == eventName) {
2088 getEl: function(id) {
2089 return document.getElementById(id);
2093 clearCache: function() {
2097 _load: function(e) {
2098 loadComplete = true;
2099 var EU = Roo.lib.Event;
2103 EU.doRemove(window, "load", EU._load);
2108 _tryPreloadAttach: function() {
2117 var tryAgain = !loadComplete;
2119 tryAgain = (retryCount > 0);
2124 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2125 var item = onAvailStack[i];
2127 var el = this.getEl(item.id);
2130 if (!item.checkReady ||
2133 (document && document.body)) {
2136 if (item.override) {
2137 if (item.override === true) {
2140 scope = item.override;
2143 item.fn.call(scope, item.obj);
2144 onAvailStack[i] = null;
2147 notAvail.push(item);
2152 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2156 this.startInterval();
2158 clearInterval(this._interval);
2159 this._interval = null;
2162 this.locked = false;
2169 purgeElement: function(el, recurse, eventName) {
2170 var elListeners = this.getListeners(el, eventName);
2172 for (var i = 0,len = elListeners.length; i < len; ++i) {
2173 var l = elListeners[i];
2174 this.removeListener(el, l.type, l.fn);
2178 if (recurse && el && el.childNodes) {
2179 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2180 this.purgeElement(el.childNodes[i], recurse, eventName);
2186 getListeners: function(el, eventName) {
2187 var results = [], searchLists;
2189 searchLists = [listeners, unloadListeners];
2190 } else if (eventName == "unload") {
2191 searchLists = [unloadListeners];
2193 searchLists = [listeners];
2196 for (var j = 0; j < searchLists.length; ++j) {
2197 var searchList = searchLists[j];
2198 if (searchList && searchList.length > 0) {
2199 for (var i = 0,len = searchList.length; i < len; ++i) {
2200 var l = searchList[i];
2201 if (l && l[this.EL] === el &&
2202 (!eventName || eventName === l[this.TYPE])) {
2207 adjust: l[this.ADJ_SCOPE],
2215 return (results.length) ? results : null;
2219 _unload: function(e) {
2221 var EU = Roo.lib.Event, i, j, l, len, index;
2223 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2224 l = unloadListeners[i];
2227 if (l[EU.ADJ_SCOPE]) {
2228 if (l[EU.ADJ_SCOPE] === true) {
2231 scope = l[EU.ADJ_SCOPE];
2234 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2235 unloadListeners[i] = null;
2241 unloadListeners = null;
2243 if (listeners && listeners.length > 0) {
2244 j = listeners.length;
2247 l = listeners[index];
2249 EU.removeListener(l[EU.EL], l[EU.TYPE],
2259 EU.doRemove(window, "unload", EU._unload);
2264 getScroll: function() {
2265 var dd = document.documentElement, db = document.body;
2266 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2267 return [dd.scrollTop, dd.scrollLeft];
2269 return [db.scrollTop, db.scrollLeft];
2276 doAdd: function () {
2277 if (window.addEventListener) {
2278 return function(el, eventName, fn, capture) {
2279 el.addEventListener(eventName, fn, (capture));
2281 } else if (window.attachEvent) {
2282 return function(el, eventName, fn, capture) {
2283 el.attachEvent("on" + eventName, fn);
2292 doRemove: function() {
2293 if (window.removeEventListener) {
2294 return function (el, eventName, fn, capture) {
2295 el.removeEventListener(eventName, fn, (capture));
2297 } else if (window.detachEvent) {
2298 return function (el, eventName, fn) {
2299 el.detachEvent("on" + eventName, fn);
2311 var E = Roo.lib.Event;
2312 E.on = E.addListener;
2313 E.un = E.removeListener;
2315 if (document && document.body) {
2318 E.doAdd(window, "load", E._load);
2320 E.doAdd(window, "unload", E._unload);
2321 E._tryPreloadAttach();
2325 * Portions of this file are based on pieces of Yahoo User Interface Library
2326 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2327 * YUI licensed under the BSD License:
2328 * http://developer.yahoo.net/yui/license.txt
2329 * <script type="text/javascript">
2336 request : function(method, uri, cb, data, options) {
2338 var hs = options.headers;
2341 if(hs.hasOwnProperty(h)){
2342 this.initHeader(h, hs[h], false);
2346 if(options.xmlData){
2347 this.initHeader('Content-Type', 'text/xml', false);
2349 data = options.xmlData;
2353 return this.asyncRequest(method, uri, cb, data);
2356 serializeForm : function(form) {
2357 if(typeof form == 'string') {
2358 form = (document.getElementById(form) || document.forms[form]);
2361 var el, name, val, disabled, data = '', hasSubmit = false;
2362 for (var i = 0; i < form.elements.length; i++) {
2363 el = form.elements[i];
2364 disabled = form.elements[i].disabled;
2365 name = form.elements[i].name;
2366 val = form.elements[i].value;
2368 if (!disabled && name){
2372 case 'select-multiple':
2373 for (var j = 0; j < el.options.length; j++) {
2374 if (el.options[j].selected) {
2376 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2379 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2387 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2400 if(hasSubmit == false) {
2401 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2406 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2411 data = data.substr(0, data.length - 1);
2419 useDefaultHeader:true,
2421 defaultPostHeader:'application/x-www-form-urlencoded',
2423 useDefaultXhrHeader:true,
2425 defaultXhrHeader:'XMLHttpRequest',
2427 hasDefaultHeaders:true,
2439 setProgId:function(id)
2441 this.activeX.unshift(id);
2444 setDefaultPostHeader:function(b)
2446 this.useDefaultHeader = b;
2449 setDefaultXhrHeader:function(b)
2451 this.useDefaultXhrHeader = b;
2454 setPollingInterval:function(i)
2456 if (typeof i == 'number' && isFinite(i)) {
2457 this.pollInterval = i;
2461 createXhrObject:function(transactionId)
2467 http = new XMLHttpRequest();
2469 obj = { conn:http, tId:transactionId };
2473 for (var i = 0; i < this.activeX.length; ++i) {
2477 http = new ActiveXObject(this.activeX[i]);
2479 obj = { conn:http, tId:transactionId };
2492 getConnectionObject:function()
2495 var tId = this.transactionId;
2499 o = this.createXhrObject(tId);
2501 this.transactionId++;
2512 asyncRequest:function(method, uri, callback, postData)
2514 var o = this.getConnectionObject();
2520 o.conn.open(method, uri, true);
2522 if (this.useDefaultXhrHeader) {
2523 if (!this.defaultHeaders['X-Requested-With']) {
2524 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2528 if(postData && this.useDefaultHeader){
2529 this.initHeader('Content-Type', this.defaultPostHeader);
2532 if (this.hasDefaultHeaders || this.hasHeaders) {
2536 this.handleReadyState(o, callback);
2537 o.conn.send(postData || null);
2543 handleReadyState:function(o, callback)
2547 if (callback && callback.timeout) {
2548 this.timeout[o.tId] = window.setTimeout(function() {
2549 oConn.abort(o, callback, true);
2550 }, callback.timeout);
2553 this.poll[o.tId] = window.setInterval(
2555 if (o.conn && o.conn.readyState == 4) {
2556 window.clearInterval(oConn.poll[o.tId]);
2557 delete oConn.poll[o.tId];
2559 if(callback && callback.timeout) {
2560 window.clearTimeout(oConn.timeout[o.tId]);
2561 delete oConn.timeout[o.tId];
2564 oConn.handleTransactionResponse(o, callback);
2567 , this.pollInterval);
2570 handleTransactionResponse:function(o, callback, isAbort)
2574 this.releaseObject(o);
2578 var httpStatus, responseObject;
2582 if (o.conn.status !== undefined && o.conn.status != 0) {
2583 httpStatus = o.conn.status;
2595 if (httpStatus >= 200 && httpStatus < 300) {
2596 responseObject = this.createResponseObject(o, callback.argument);
2597 if (callback.success) {
2598 if (!callback.scope) {
2599 callback.success(responseObject);
2604 callback.success.apply(callback.scope, [responseObject]);
2609 switch (httpStatus) {
2617 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2618 if (callback.failure) {
2619 if (!callback.scope) {
2620 callback.failure(responseObject);
2623 callback.failure.apply(callback.scope, [responseObject]);
2628 responseObject = this.createResponseObject(o, callback.argument);
2629 if (callback.failure) {
2630 if (!callback.scope) {
2631 callback.failure(responseObject);
2634 callback.failure.apply(callback.scope, [responseObject]);
2640 this.releaseObject(o);
2641 responseObject = null;
2644 createResponseObject:function(o, callbackArg)
2651 var headerStr = o.conn.getAllResponseHeaders();
2652 var header = headerStr.split('\n');
2653 for (var i = 0; i < header.length; i++) {
2654 var delimitPos = header[i].indexOf(':');
2655 if (delimitPos != -1) {
2656 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2664 obj.status = o.conn.status;
2665 obj.statusText = o.conn.statusText;
2666 obj.getResponseHeader = headerObj;
2667 obj.getAllResponseHeaders = headerStr;
2668 obj.responseText = o.conn.responseText;
2669 obj.responseXML = o.conn.responseXML;
2671 if (typeof callbackArg !== undefined) {
2672 obj.argument = callbackArg;
2678 createExceptionObject:function(tId, callbackArg, isAbort)
2681 var COMM_ERROR = 'communication failure';
2682 var ABORT_CODE = -1;
2683 var ABORT_ERROR = 'transaction aborted';
2689 obj.status = ABORT_CODE;
2690 obj.statusText = ABORT_ERROR;
2693 obj.status = COMM_CODE;
2694 obj.statusText = COMM_ERROR;
2698 obj.argument = callbackArg;
2704 initHeader:function(label, value, isDefault)
2706 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2708 if (headerObj[label] === undefined) {
2709 headerObj[label] = value;
2714 headerObj[label] = value + "," + headerObj[label];
2718 this.hasDefaultHeaders = true;
2721 this.hasHeaders = true;
2726 setHeader:function(o)
2728 if (this.hasDefaultHeaders) {
2729 for (var prop in this.defaultHeaders) {
2730 if (this.defaultHeaders.hasOwnProperty(prop)) {
2731 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2736 if (this.hasHeaders) {
2737 for (var prop in this.headers) {
2738 if (this.headers.hasOwnProperty(prop)) {
2739 o.conn.setRequestHeader(prop, this.headers[prop]);
2743 this.hasHeaders = false;
2747 resetDefaultHeaders:function() {
2748 delete this.defaultHeaders;
2749 this.defaultHeaders = {};
2750 this.hasDefaultHeaders = false;
2753 abort:function(o, callback, isTimeout)
2755 if(this.isCallInProgress(o)) {
2757 window.clearInterval(this.poll[o.tId]);
2758 delete this.poll[o.tId];
2760 delete this.timeout[o.tId];
2763 this.handleTransactionResponse(o, callback, true);
2773 isCallInProgress:function(o)
2776 return o.conn.readyState != 4 && o.conn.readyState != 0;
2785 releaseObject:function(o)
2794 'MSXML2.XMLHTTP.3.0',
2802 * Portions of this file are based on pieces of Yahoo User Interface Library
2803 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2804 * YUI licensed under the BSD License:
2805 * http://developer.yahoo.net/yui/license.txt
2806 * <script type="text/javascript">
2810 Roo.lib.Region = function(t, r, b, l) {
2820 Roo.lib.Region.prototype = {
2821 contains : function(region) {
2822 return ( region.left >= this.left &&
2823 region.right <= this.right &&
2824 region.top >= this.top &&
2825 region.bottom <= this.bottom );
2829 getArea : function() {
2830 return ( (this.bottom - this.top) * (this.right - this.left) );
2833 intersect : function(region) {
2834 var t = Math.max(this.top, region.top);
2835 var r = Math.min(this.right, region.right);
2836 var b = Math.min(this.bottom, region.bottom);
2837 var l = Math.max(this.left, region.left);
2839 if (b >= t && r >= l) {
2840 return new Roo.lib.Region(t, r, b, l);
2845 union : function(region) {
2846 var t = Math.min(this.top, region.top);
2847 var r = Math.max(this.right, region.right);
2848 var b = Math.max(this.bottom, region.bottom);
2849 var l = Math.min(this.left, region.left);
2851 return new Roo.lib.Region(t, r, b, l);
2854 adjust : function(t, l, b, r) {
2863 Roo.lib.Region.getRegion = function(el) {
2864 var p = Roo.lib.Dom.getXY(el);
2867 var r = p[0] + el.offsetWidth;
2868 var b = p[1] + el.offsetHeight;
2871 return new Roo.lib.Region(t, r, b, l);
2874 * Portions of this file are based on pieces of Yahoo User Interface Library
2875 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2876 * YUI licensed under the BSD License:
2877 * http://developer.yahoo.net/yui/license.txt
2878 * <script type="text/javascript">
2881 //@@dep Roo.lib.Region
2884 Roo.lib.Point = function(x, y) {
2885 if (x instanceof Array) {
2889 this.x = this.right = this.left = this[0] = x;
2890 this.y = this.top = this.bottom = this[1] = y;
2893 Roo.lib.Point.prototype = new Roo.lib.Region();
2895 * Portions of this file are based on pieces of Yahoo User Interface Library
2896 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2897 * YUI licensed under the BSD License:
2898 * http://developer.yahoo.net/yui/license.txt
2899 * <script type="text/javascript">
2906 scroll : function(el, args, duration, easing, cb, scope) {
2907 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2910 motion : function(el, args, duration, easing, cb, scope) {
2911 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2914 color : function(el, args, duration, easing, cb, scope) {
2915 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2918 run : function(el, args, duration, easing, cb, scope, type) {
2919 type = type || Roo.lib.AnimBase;
2920 if (typeof easing == "string") {
2921 easing = Roo.lib.Easing[easing];
2923 var anim = new type(el, args, duration, easing);
2924 anim.animateX(function() {
2925 Roo.callback(cb, scope);
2931 * Portions of this file are based on pieces of Yahoo User Interface Library
2932 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2933 * YUI licensed under the BSD License:
2934 * http://developer.yahoo.net/yui/license.txt
2935 * <script type="text/javascript">
2943 if (!libFlyweight) {
2944 libFlyweight = new Roo.Element.Flyweight();
2946 libFlyweight.dom = el;
2947 return libFlyweight;
2950 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2954 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2956 this.init(el, attributes, duration, method);
2960 Roo.lib.AnimBase.fly = fly;
2964 Roo.lib.AnimBase.prototype = {
2966 toString: function() {
2967 var el = this.getEl();
2968 var id = el.id || el.tagName;
2969 return ("Anim " + id);
2973 noNegatives: /width|height|opacity|padding/i,
2974 offsetAttribute: /^((width|height)|(top|left))$/,
2975 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
2976 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
2980 doMethod: function(attr, start, end) {
2981 return this.method(this.currentFrame, start, end - start, this.totalFrames);
2985 setAttribute: function(attr, val, unit) {
2986 if (this.patterns.noNegatives.test(attr)) {
2987 val = (val > 0) ? val : 0;
2990 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
2994 getAttribute: function(attr) {
2995 var el = this.getEl();
2996 var val = fly(el).getStyle(attr);
2998 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
2999 return parseFloat(val);
3002 var a = this.patterns.offsetAttribute.exec(attr) || [];
3003 var pos = !!( a[3] );
3004 var box = !!( a[2] );
3007 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3008 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3017 getDefaultUnit: function(attr) {
3018 if (this.patterns.defaultUnit.test(attr)) {
3025 animateX : function(callback, scope) {
3026 var f = function() {
3027 this.onComplete.removeListener(f);
3028 if (typeof callback == "function") {
3029 callback.call(scope || this, this);
3032 this.onComplete.addListener(f, this);
3037 setRuntimeAttribute: function(attr) {
3040 var attributes = this.attributes;
3042 this.runtimeAttributes[attr] = {};
3044 var isset = function(prop) {
3045 return (typeof prop !== 'undefined');
3048 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3052 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3055 if (isset(attributes[attr]['to'])) {
3056 end = attributes[attr]['to'];
3057 } else if (isset(attributes[attr]['by'])) {
3058 if (start.constructor == Array) {
3060 for (var i = 0, len = start.length; i < len; ++i) {
3061 end[i] = start[i] + attributes[attr]['by'][i];
3064 end = start + attributes[attr]['by'];
3068 this.runtimeAttributes[attr].start = start;
3069 this.runtimeAttributes[attr].end = end;
3072 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3076 init: function(el, attributes, duration, method) {
3078 var isAnimated = false;
3081 var startTime = null;
3084 var actualFrames = 0;
3087 el = Roo.getDom(el);
3090 this.attributes = attributes || {};
3093 this.duration = duration || 1;
3096 this.method = method || Roo.lib.Easing.easeNone;
3099 this.useSeconds = true;
3102 this.currentFrame = 0;
3105 this.totalFrames = Roo.lib.AnimMgr.fps;
3108 this.getEl = function() {
3113 this.isAnimated = function() {
3118 this.getStartTime = function() {
3122 this.runtimeAttributes = {};
3125 this.animate = function() {
3126 if (this.isAnimated()) {
3130 this.currentFrame = 0;
3132 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3134 Roo.lib.AnimMgr.registerElement(this);
3138 this.stop = function(finish) {
3140 this.currentFrame = this.totalFrames;
3141 this._onTween.fire();
3143 Roo.lib.AnimMgr.stop(this);
3146 var onStart = function() {
3147 this.onStart.fire();
3149 this.runtimeAttributes = {};
3150 for (var attr in this.attributes) {
3151 this.setRuntimeAttribute(attr);
3156 startTime = new Date();
3160 var onTween = function() {
3162 duration: new Date() - this.getStartTime(),
3163 currentFrame: this.currentFrame
3166 data.toString = function() {
3168 'duration: ' + data.duration +
3169 ', currentFrame: ' + data.currentFrame
3173 this.onTween.fire(data);
3175 var runtimeAttributes = this.runtimeAttributes;
3177 for (var attr in runtimeAttributes) {
3178 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3184 var onComplete = function() {
3185 var actual_duration = (new Date() - startTime) / 1000 ;
3188 duration: actual_duration,
3189 frames: actualFrames,
3190 fps: actualFrames / actual_duration
3193 data.toString = function() {
3195 'duration: ' + data.duration +
3196 ', frames: ' + data.frames +
3197 ', fps: ' + data.fps
3203 this.onComplete.fire(data);
3207 this._onStart = new Roo.util.Event(this);
3208 this.onStart = new Roo.util.Event(this);
3209 this.onTween = new Roo.util.Event(this);
3210 this._onTween = new Roo.util.Event(this);
3211 this.onComplete = new Roo.util.Event(this);
3212 this._onComplete = new Roo.util.Event(this);
3213 this._onStart.addListener(onStart);
3214 this._onTween.addListener(onTween);
3215 this._onComplete.addListener(onComplete);
3220 * Portions of this file are based on pieces of Yahoo User Interface Library
3221 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3222 * YUI licensed under the BSD License:
3223 * http://developer.yahoo.net/yui/license.txt
3224 * <script type="text/javascript">
3228 Roo.lib.AnimMgr = new function() {
3245 this.registerElement = function(tween) {
3246 queue[queue.length] = tween;
3248 tween._onStart.fire();
3253 this.unRegister = function(tween, index) {
3254 tween._onComplete.fire();
3255 index = index || getIndex(tween);
3257 queue.splice(index, 1);
3261 if (tweenCount <= 0) {
3267 this.start = function() {
3268 if (thread === null) {
3269 thread = setInterval(this.run, this.delay);
3274 this.stop = function(tween) {
3276 clearInterval(thread);
3278 for (var i = 0, len = queue.length; i < len; ++i) {
3279 if (queue[0].isAnimated()) {
3280 this.unRegister(queue[0], 0);
3289 this.unRegister(tween);
3294 this.run = function() {
3295 for (var i = 0, len = queue.length; i < len; ++i) {
3296 var tween = queue[i];
3297 if (!tween || !tween.isAnimated()) {
3301 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3303 tween.currentFrame += 1;
3305 if (tween.useSeconds) {
3306 correctFrame(tween);
3308 tween._onTween.fire();
3311 Roo.lib.AnimMgr.stop(tween, i);
3316 var getIndex = function(anim) {
3317 for (var i = 0, len = queue.length; i < len; ++i) {
3318 if (queue[i] == anim) {
3326 var correctFrame = function(tween) {
3327 var frames = tween.totalFrames;
3328 var frame = tween.currentFrame;
3329 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3330 var elapsed = (new Date() - tween.getStartTime());
3333 if (elapsed < tween.duration * 1000) {
3334 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3336 tweak = frames - (frame + 1);
3338 if (tweak > 0 && isFinite(tweak)) {
3339 if (tween.currentFrame + tweak >= frames) {
3340 tweak = frames - (frame + 1);
3343 tween.currentFrame += tweak;
3347 * Portions of this file are based on pieces of Yahoo User Interface Library
3348 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3349 * YUI licensed under the BSD License:
3350 * http://developer.yahoo.net/yui/license.txt
3351 * <script type="text/javascript">
3354 Roo.lib.Bezier = new function() {
3356 this.getPosition = function(points, t) {
3357 var n = points.length;
3360 for (var i = 0; i < n; ++i) {
3361 tmp[i] = [points[i][0], points[i][1]];
3364 for (var j = 1; j < n; ++j) {
3365 for (i = 0; i < n - j; ++i) {
3366 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3367 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3371 return [ tmp[0][0], tmp[0][1] ];
3375 * Portions of this file are based on pieces of Yahoo User Interface Library
3376 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3377 * YUI licensed under the BSD License:
3378 * http://developer.yahoo.net/yui/license.txt
3379 * <script type="text/javascript">
3384 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3385 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3388 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3390 var fly = Roo.lib.AnimBase.fly;
3392 var superclass = Y.ColorAnim.superclass;
3393 var proto = Y.ColorAnim.prototype;
3395 proto.toString = function() {
3396 var el = this.getEl();
3397 var id = el.id || el.tagName;
3398 return ("ColorAnim " + id);
3401 proto.patterns.color = /color$/i;
3402 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3403 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3404 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3405 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3408 proto.parseColor = function(s) {
3409 if (s.length == 3) {
3413 var c = this.patterns.hex.exec(s);
3414 if (c && c.length == 4) {
3415 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3418 c = this.patterns.rgb.exec(s);
3419 if (c && c.length == 4) {
3420 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3423 c = this.patterns.hex3.exec(s);
3424 if (c && c.length == 4) {
3425 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3430 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3431 proto.getAttribute = function(attr) {
3432 var el = this.getEl();
3433 if (this.patterns.color.test(attr)) {
3434 var val = fly(el).getStyle(attr);
3436 if (this.patterns.transparent.test(val)) {
3437 var parent = el.parentNode;
3438 val = fly(parent).getStyle(attr);
3440 while (parent && this.patterns.transparent.test(val)) {
3441 parent = parent.parentNode;
3442 val = fly(parent).getStyle(attr);
3443 if (parent.tagName.toUpperCase() == 'HTML') {
3449 val = superclass.getAttribute.call(this, attr);
3454 proto.getAttribute = function(attr) {
3455 var el = this.getEl();
3456 if (this.patterns.color.test(attr)) {
3457 var val = fly(el).getStyle(attr);
3459 if (this.patterns.transparent.test(val)) {
3460 var parent = el.parentNode;
3461 val = fly(parent).getStyle(attr);
3463 while (parent && this.patterns.transparent.test(val)) {
3464 parent = parent.parentNode;
3465 val = fly(parent).getStyle(attr);
3466 if (parent.tagName.toUpperCase() == 'HTML') {
3472 val = superclass.getAttribute.call(this, attr);
3478 proto.doMethod = function(attr, start, end) {
3481 if (this.patterns.color.test(attr)) {
3483 for (var i = 0, len = start.length; i < len; ++i) {
3484 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3487 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3490 val = superclass.doMethod.call(this, attr, start, end);
3496 proto.setRuntimeAttribute = function(attr) {
3497 superclass.setRuntimeAttribute.call(this, attr);
3499 if (this.patterns.color.test(attr)) {
3500 var attributes = this.attributes;
3501 var start = this.parseColor(this.runtimeAttributes[attr].start);
3502 var end = this.parseColor(this.runtimeAttributes[attr].end);
3504 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3505 end = this.parseColor(attributes[attr].by);
3507 for (var i = 0, len = start.length; i < len; ++i) {
3508 end[i] = start[i] + end[i];
3512 this.runtimeAttributes[attr].start = start;
3513 this.runtimeAttributes[attr].end = end;
3519 * Portions of this file are based on pieces of Yahoo User Interface Library
3520 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3521 * YUI licensed under the BSD License:
3522 * http://developer.yahoo.net/yui/license.txt
3523 * <script type="text/javascript">
3529 easeNone: function (t, b, c, d) {
3530 return c * t / d + b;
3534 easeIn: function (t, b, c, d) {
3535 return c * (t /= d) * t + b;
3539 easeOut: function (t, b, c, d) {
3540 return -c * (t /= d) * (t - 2) + b;
3544 easeBoth: function (t, b, c, d) {
3545 if ((t /= d / 2) < 1) {
3546 return c / 2 * t * t + b;
3549 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3553 easeInStrong: function (t, b, c, d) {
3554 return c * (t /= d) * t * t * t + b;
3558 easeOutStrong: function (t, b, c, d) {
3559 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3563 easeBothStrong: function (t, b, c, d) {
3564 if ((t /= d / 2) < 1) {
3565 return c / 2 * t * t * t * t + b;
3568 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3573 elasticIn: function (t, b, c, d, a, p) {
3577 if ((t /= d) == 1) {
3584 if (!a || a < Math.abs(c)) {
3589 var s = p / (2 * Math.PI) * Math.asin(c / a);
3592 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3596 elasticOut: function (t, b, c, d, a, p) {
3600 if ((t /= d) == 1) {
3607 if (!a || a < Math.abs(c)) {
3612 var s = p / (2 * Math.PI) * Math.asin(c / a);
3615 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3619 elasticBoth: function (t, b, c, d, a, p) {
3624 if ((t /= d / 2) == 2) {
3632 if (!a || a < Math.abs(c)) {
3637 var s = p / (2 * Math.PI) * Math.asin(c / a);
3641 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3642 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3644 return a * Math.pow(2, -10 * (t -= 1)) *
3645 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3650 backIn: function (t, b, c, d, s) {
3651 if (typeof s == 'undefined') {
3654 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3658 backOut: function (t, b, c, d, s) {
3659 if (typeof s == 'undefined') {
3662 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3666 backBoth: function (t, b, c, d, s) {
3667 if (typeof s == 'undefined') {
3671 if ((t /= d / 2 ) < 1) {
3672 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3674 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3678 bounceIn: function (t, b, c, d) {
3679 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3683 bounceOut: function (t, b, c, d) {
3684 if ((t /= d) < (1 / 2.75)) {
3685 return c * (7.5625 * t * t) + b;
3686 } else if (t < (2 / 2.75)) {
3687 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3688 } else if (t < (2.5 / 2.75)) {
3689 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3691 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3695 bounceBoth: function (t, b, c, d) {
3697 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3699 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3702 * Portions of this file are based on pieces of Yahoo User Interface Library
3703 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3704 * YUI licensed under the BSD License:
3705 * http://developer.yahoo.net/yui/license.txt
3706 * <script type="text/javascript">
3710 Roo.lib.Motion = function(el, attributes, duration, method) {
3712 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3716 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3720 var superclass = Y.Motion.superclass;
3721 var proto = Y.Motion.prototype;
3723 proto.toString = function() {
3724 var el = this.getEl();
3725 var id = el.id || el.tagName;
3726 return ("Motion " + id);
3729 proto.patterns.points = /^points$/i;
3731 proto.setAttribute = function(attr, val, unit) {
3732 if (this.patterns.points.test(attr)) {
3733 unit = unit || 'px';
3734 superclass.setAttribute.call(this, 'left', val[0], unit);
3735 superclass.setAttribute.call(this, 'top', val[1], unit);
3737 superclass.setAttribute.call(this, attr, val, unit);
3741 proto.getAttribute = function(attr) {
3742 if (this.patterns.points.test(attr)) {
3744 superclass.getAttribute.call(this, 'left'),
3745 superclass.getAttribute.call(this, 'top')
3748 val = superclass.getAttribute.call(this, attr);
3754 proto.doMethod = function(attr, start, end) {
3757 if (this.patterns.points.test(attr)) {
3758 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3759 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3761 val = superclass.doMethod.call(this, attr, start, end);
3766 proto.setRuntimeAttribute = function(attr) {
3767 if (this.patterns.points.test(attr)) {
3768 var el = this.getEl();
3769 var attributes = this.attributes;
3771 var control = attributes['points']['control'] || [];
3775 if (control.length > 0 && !(control[0] instanceof Array)) {
3776 control = [control];
3779 for (i = 0,len = control.length; i < len; ++i) {
3780 tmp[i] = control[i];
3785 Roo.fly(el).position();
3787 if (isset(attributes['points']['from'])) {
3788 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3791 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3794 start = this.getAttribute('points');
3797 if (isset(attributes['points']['to'])) {
3798 end = translateValues.call(this, attributes['points']['to'], start);
3800 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3801 for (i = 0,len = control.length; i < len; ++i) {
3802 control[i] = translateValues.call(this, control[i], start);
3806 } else if (isset(attributes['points']['by'])) {
3807 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3809 for (i = 0,len = control.length; i < len; ++i) {
3810 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3814 this.runtimeAttributes[attr] = [start];
3816 if (control.length > 0) {
3817 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3820 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3823 superclass.setRuntimeAttribute.call(this, attr);
3827 var translateValues = function(val, start) {
3828 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3829 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3834 var isset = function(prop) {
3835 return (typeof prop !== 'undefined');
3839 * Portions of this file are based on pieces of Yahoo User Interface Library
3840 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3841 * YUI licensed under the BSD License:
3842 * http://developer.yahoo.net/yui/license.txt
3843 * <script type="text/javascript">
3847 Roo.lib.Scroll = function(el, attributes, duration, method) {
3849 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3853 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3857 var superclass = Y.Scroll.superclass;
3858 var proto = Y.Scroll.prototype;
3860 proto.toString = function() {
3861 var el = this.getEl();
3862 var id = el.id || el.tagName;
3863 return ("Scroll " + id);
3866 proto.doMethod = function(attr, start, end) {
3869 if (attr == 'scroll') {
3871 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3872 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3876 val = superclass.doMethod.call(this, attr, start, end);
3881 proto.getAttribute = function(attr) {
3883 var el = this.getEl();
3885 if (attr == 'scroll') {
3886 val = [ el.scrollLeft, el.scrollTop ];
3888 val = superclass.getAttribute.call(this, attr);
3894 proto.setAttribute = function(attr, val, unit) {
3895 var el = this.getEl();
3897 if (attr == 'scroll') {
3898 el.scrollLeft = val[0];
3899 el.scrollTop = val[1];
3901 superclass.setAttribute.call(this, attr, val, unit);
3907 * Ext JS Library 1.1.1
3908 * Copyright(c) 2006-2007, Ext JS, LLC.
3910 * Originally Released Under LGPL - original licence link has changed is not relivant.
3913 * <script type="text/javascript">
3918 * @class Roo.DomHelper
3919 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3920 * 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>.
3923 Roo.DomHelper = function(){
3924 var tempTableEl = null;
3925 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3926 var tableRe = /^table|tbody|tr|td$/i;
3928 // build as innerHTML where available
3930 var createHtml = function(o){
3931 if(typeof o == 'string'){
3940 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3941 if(attr == "style"){
3943 if(typeof s == "function"){
3946 if(typeof s == "string"){
3947 b += ' style="' + s + '"';
3948 }else if(typeof s == "object"){
3951 if(typeof s[key] != "function"){
3952 b += key + ":" + s[key] + ";";
3959 b += ' class="' + o["cls"] + '"';
3960 }else if(attr == "htmlFor"){
3961 b += ' for="' + o["htmlFor"] + '"';
3963 b += " " + attr + '="' + o[attr] + '"';
3967 if(emptyTags.test(o.tag)){
3971 var cn = o.children || o.cn;
3973 //http://bugs.kde.org/show_bug.cgi?id=71506
3974 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
3975 for(var i = 0, len = cn.length; i < len; i++) {
3976 b += createHtml(cn[i], b);
3979 b += createHtml(cn, b);
3985 b += "</" + o.tag + ">";
3992 var createDom = function(o, parentNode){
3994 // defininition craeted..
3996 if (o.ns && o.ns != 'html') {
3998 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
3999 xmlns[o.ns] = o.xmlns;
4002 if (typeof(xmlns[o.ns]) == 'undefined') {
4003 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4009 if (typeof(o) == 'string') {
4010 return parentNode.appendChild(document.createTextNode(o));
4012 o.tag = o.tag || div;
4013 if (o.ns && Roo.isIE) {
4015 o.tag = o.ns + ':' + o.tag;
4018 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4019 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4022 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4023 attr == "style" || typeof o[attr] == "function") continue;
4025 if(attr=="cls" && Roo.isIE){
4026 el.className = o["cls"];
4028 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4029 else el[attr] = o[attr];
4032 Roo.DomHelper.applyStyles(el, o.style);
4033 var cn = o.children || o.cn;
4035 //http://bugs.kde.org/show_bug.cgi?id=71506
4036 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4037 for(var i = 0, len = cn.length; i < len; i++) {
4038 createDom(cn[i], el);
4045 el.innerHTML = o.html;
4048 parentNode.appendChild(el);
4053 var ieTable = function(depth, s, h, e){
4054 tempTableEl.innerHTML = [s, h, e].join('');
4055 var i = -1, el = tempTableEl;
4062 // kill repeat to save bytes
4066 tbe = '</tbody>'+te,
4072 * Nasty code for IE's broken table implementation
4074 var insertIntoTable = function(tag, where, el, html){
4076 tempTableEl = document.createElement('div');
4081 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4084 if(where == 'beforebegin'){
4088 before = el.nextSibling;
4091 node = ieTable(4, trs, html, tre);
4093 else if(tag == 'tr'){
4094 if(where == 'beforebegin'){
4097 node = ieTable(3, tbs, html, tbe);
4098 } else if(where == 'afterend'){
4099 before = el.nextSibling;
4101 node = ieTable(3, tbs, html, tbe);
4102 } else{ // INTO a TR
4103 if(where == 'afterbegin'){
4104 before = el.firstChild;
4106 node = ieTable(4, trs, html, tre);
4108 } else if(tag == 'tbody'){
4109 if(where == 'beforebegin'){
4112 node = ieTable(2, ts, html, te);
4113 } else if(where == 'afterend'){
4114 before = el.nextSibling;
4116 node = ieTable(2, ts, html, te);
4118 if(where == 'afterbegin'){
4119 before = el.firstChild;
4121 node = ieTable(3, tbs, html, tbe);
4124 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4127 if(where == 'afterbegin'){
4128 before = el.firstChild;
4130 node = ieTable(2, ts, html, te);
4132 el.insertBefore(node, before);
4137 /** True to force the use of DOM instead of html fragments @type Boolean */
4141 * Returns the markup for the passed Element(s) config
4142 * @param {Object} o The Dom object spec (and children)
4145 markup : function(o){
4146 return createHtml(o);
4150 * Applies a style specification to an element
4151 * @param {String/HTMLElement} el The element to apply styles to
4152 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4153 * a function which returns such a specification.
4155 applyStyles : function(el, styles){
4158 if(typeof styles == "string"){
4159 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4161 while ((matches = re.exec(styles)) != null){
4162 el.setStyle(matches[1], matches[2]);
4164 }else if (typeof styles == "object"){
4165 for (var style in styles){
4166 el.setStyle(style, styles[style]);
4168 }else if (typeof styles == "function"){
4169 Roo.DomHelper.applyStyles(el, styles.call());
4175 * Inserts an HTML fragment into the Dom
4176 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4177 * @param {HTMLElement} el The context element
4178 * @param {String} html The HTML fragmenet
4179 * @return {HTMLElement} The new node
4181 insertHtml : function(where, el, html){
4182 where = where.toLowerCase();
4183 if(el.insertAdjacentHTML){
4184 if(tableRe.test(el.tagName)){
4186 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4192 el.insertAdjacentHTML('BeforeBegin', html);
4193 return el.previousSibling;
4195 el.insertAdjacentHTML('AfterBegin', html);
4196 return el.firstChild;
4198 el.insertAdjacentHTML('BeforeEnd', html);
4199 return el.lastChild;
4201 el.insertAdjacentHTML('AfterEnd', html);
4202 return el.nextSibling;
4204 throw 'Illegal insertion point -> "' + where + '"';
4206 var range = el.ownerDocument.createRange();
4210 range.setStartBefore(el);
4211 frag = range.createContextualFragment(html);
4212 el.parentNode.insertBefore(frag, el);
4213 return el.previousSibling;
4216 range.setStartBefore(el.firstChild);
4217 frag = range.createContextualFragment(html);
4218 el.insertBefore(frag, el.firstChild);
4219 return el.firstChild;
4221 el.innerHTML = html;
4222 return el.firstChild;
4226 range.setStartAfter(el.lastChild);
4227 frag = range.createContextualFragment(html);
4228 el.appendChild(frag);
4229 return el.lastChild;
4231 el.innerHTML = html;
4232 return el.lastChild;
4235 range.setStartAfter(el);
4236 frag = range.createContextualFragment(html);
4237 el.parentNode.insertBefore(frag, el.nextSibling);
4238 return el.nextSibling;
4240 throw 'Illegal insertion point -> "' + where + '"';
4244 * Creates new Dom element(s) and inserts them before el
4245 * @param {String/HTMLElement/Element} el The context element
4246 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4247 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4248 * @return {HTMLElement/Roo.Element} The new node
4250 insertBefore : function(el, o, returnElement){
4251 return this.doInsert(el, o, returnElement, "beforeBegin");
4255 * Creates new Dom element(s) and inserts them after el
4256 * @param {String/HTMLElement/Element} el The context element
4257 * @param {Object} o The Dom object spec (and children)
4258 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4259 * @return {HTMLElement/Roo.Element} The new node
4261 insertAfter : function(el, o, returnElement){
4262 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4266 * Creates new Dom element(s) and inserts them as the first child of el
4267 * @param {String/HTMLElement/Element} el The context element
4268 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4269 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4270 * @return {HTMLElement/Roo.Element} The new node
4272 insertFirst : function(el, o, returnElement){
4273 return this.doInsert(el, o, returnElement, "afterBegin");
4277 doInsert : function(el, o, returnElement, pos, sibling){
4278 el = Roo.getDom(el);
4280 if(this.useDom || o.ns){
4281 newNode = createDom(o, null);
4282 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4284 var html = createHtml(o);
4285 newNode = this.insertHtml(pos, el, html);
4287 return returnElement ? Roo.get(newNode, true) : newNode;
4291 * Creates new Dom element(s) and appends them to el
4292 * @param {String/HTMLElement/Element} el The context element
4293 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4294 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4295 * @return {HTMLElement/Roo.Element} The new node
4297 append : function(el, o, returnElement){
4298 el = Roo.getDom(el);
4300 if(this.useDom || o.ns){
4301 newNode = createDom(o, null);
4302 el.appendChild(newNode);
4304 var html = createHtml(o);
4305 newNode = this.insertHtml("beforeEnd", el, html);
4307 return returnElement ? Roo.get(newNode, true) : newNode;
4311 * Creates new Dom element(s) and overwrites the contents of el with them
4312 * @param {String/HTMLElement/Element} el The context element
4313 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4314 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4315 * @return {HTMLElement/Roo.Element} The new node
4317 overwrite : function(el, o, returnElement){
4318 el = Roo.getDom(el);
4321 while (el.childNodes.length) {
4322 el.removeChild(el.firstChild);
4326 el.innerHTML = createHtml(o);
4329 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4333 * Creates a new Roo.DomHelper.Template from the Dom object spec
4334 * @param {Object} o The Dom object spec (and children)
4335 * @return {Roo.DomHelper.Template} The new template
4337 createTemplate : function(o){
4338 var html = createHtml(o);
4339 return new Roo.Template(html);
4345 * Ext JS Library 1.1.1
4346 * Copyright(c) 2006-2007, Ext JS, LLC.
4348 * Originally Released Under LGPL - original licence link has changed is not relivant.
4351 * <script type="text/javascript">
4355 * @class Roo.Template
4356 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4357 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4360 var t = new Roo.Template(
4361 '<div name="{id}">',
4362 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4365 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4367 * 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>.
4369 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4371 Roo.Template = function(html){
4372 if(html instanceof Array){
4373 html = html.join("");
4374 }else if(arguments.length > 1){
4375 html = Array.prototype.join.call(arguments, "");
4381 Roo.Template.prototype = {
4383 * Returns an HTML fragment of this template with the specified values applied.
4384 * @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'})
4385 * @return {String} The HTML fragment
4387 applyTemplate : function(values){
4389 return this.compiled(values);
4391 var useF = this.disableFormats !== true;
4392 var fm = Roo.util.Format, tpl = this;
4393 var fn = function(m, name, format, args){
4395 if(format.substr(0, 5) == "this."){
4396 return tpl.call(format.substr(5), values[name], values);
4399 // quoted values are required for strings in compiled templates,
4400 // but for non compiled we need to strip them
4401 // quoted reversed for jsmin
4402 var re = /^\s*['"](.*)["']\s*$/;
4403 args = args.split(',');
4404 for(var i = 0, len = args.length; i < len; i++){
4405 args[i] = args[i].replace(re, "$1");
4407 args = [values[name]].concat(args);
4409 args = [values[name]];
4411 return fm[format].apply(fm, args);
4414 return values[name] !== undefined ? values[name] : "";
4417 return this.html.replace(this.re, fn);
4421 * Sets the HTML used as the template and optionally compiles it.
4422 * @param {String} html
4423 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4424 * @return {Roo.Template} this
4426 set : function(html, compile){
4428 this.compiled = null;
4436 * True to disable format functions (defaults to false)
4439 disableFormats : false,
4442 * The regular expression used to match template variables
4446 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4449 * Compiles the template into an internal function, eliminating the RegEx overhead.
4450 * @return {Roo.Template} this
4452 compile : function(){
4453 var fm = Roo.util.Format;
4454 var useF = this.disableFormats !== true;
4455 var sep = Roo.isGecko ? "+" : ",";
4456 var fn = function(m, name, format, args){
4458 args = args ? ',' + args : "";
4459 if(format.substr(0, 5) != "this."){
4460 format = "fm." + format + '(';
4462 format = 'this.call("'+ format.substr(5) + '", ';
4466 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4468 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4471 // branched to use + in gecko and [].join() in others
4473 body = "this.compiled = function(values){ return '" +
4474 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4477 body = ["this.compiled = function(values){ return ['"];
4478 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4479 body.push("'].join('');};");
4480 body = body.join('');
4490 // private function used to call members
4491 call : function(fnName, value, allValues){
4492 return this[fnName](value, allValues);
4496 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4497 * @param {String/HTMLElement/Roo.Element} el The context element
4498 * @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'})
4499 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4500 * @return {HTMLElement/Roo.Element} The new node or Element
4502 insertFirst: function(el, values, returnElement){
4503 return this.doInsert('afterBegin', el, values, returnElement);
4507 * Applies the supplied values to the template and inserts the new node(s) before el.
4508 * @param {String/HTMLElement/Roo.Element} el The context element
4509 * @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'})
4510 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4511 * @return {HTMLElement/Roo.Element} The new node or Element
4513 insertBefore: function(el, values, returnElement){
4514 return this.doInsert('beforeBegin', el, values, returnElement);
4518 * Applies the supplied values to the template and inserts the new node(s) after el.
4519 * @param {String/HTMLElement/Roo.Element} el The context element
4520 * @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'})
4521 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4522 * @return {HTMLElement/Roo.Element} The new node or Element
4524 insertAfter : function(el, values, returnElement){
4525 return this.doInsert('afterEnd', el, values, returnElement);
4529 * Applies the supplied values to the template and appends the new node(s) to el.
4530 * @param {String/HTMLElement/Roo.Element} el The context element
4531 * @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'})
4532 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4533 * @return {HTMLElement/Roo.Element} The new node or Element
4535 append : function(el, values, returnElement){
4536 return this.doInsert('beforeEnd', el, values, returnElement);
4539 doInsert : function(where, el, values, returnEl){
4540 el = Roo.getDom(el);
4541 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4542 return returnEl ? Roo.get(newNode, true) : newNode;
4546 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4547 * @param {String/HTMLElement/Roo.Element} el The context element
4548 * @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'})
4549 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4550 * @return {HTMLElement/Roo.Element} The new node or Element
4552 overwrite : function(el, values, returnElement){
4553 el = Roo.getDom(el);
4554 el.innerHTML = this.applyTemplate(values);
4555 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4559 * Alias for {@link #applyTemplate}
4562 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4565 Roo.DomHelper.Template = Roo.Template;
4568 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4569 * @param {String/HTMLElement} el A DOM element or its id
4570 * @returns {Roo.Template} The created template
4573 Roo.Template.from = function(el){
4574 el = Roo.getDom(el);
4575 return new Roo.Template(el.value || el.innerHTML);
4578 * Ext JS Library 1.1.1
4579 * Copyright(c) 2006-2007, Ext JS, LLC.
4581 * Originally Released Under LGPL - original licence link has changed is not relivant.
4584 * <script type="text/javascript">
4589 * This is code is also distributed under MIT license for use
4590 * with jQuery and prototype JavaScript libraries.
4593 * @class Roo.DomQuery
4594 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).
4596 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>
4599 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.
4601 <h4>Element Selectors:</h4>
4603 <li> <b>*</b> any element</li>
4604 <li> <b>E</b> an element with the tag E</li>
4605 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4606 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4607 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4608 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4610 <h4>Attribute Selectors:</h4>
4611 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4613 <li> <b>E[foo]</b> has an attribute "foo"</li>
4614 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4615 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4616 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4617 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4618 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4619 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4621 <h4>Pseudo Classes:</h4>
4623 <li> <b>E:first-child</b> E is the first child of its parent</li>
4624 <li> <b>E:last-child</b> E is the last child of its parent</li>
4625 <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>
4626 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4627 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4628 <li> <b>E:only-child</b> E is the only child of its parent</li>
4629 <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>
4630 <li> <b>E:first</b> the first E in the resultset</li>
4631 <li> <b>E:last</b> the last E in the resultset</li>
4632 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4633 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4634 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4635 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4636 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4637 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4638 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4639 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4640 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4642 <h4>CSS Value Selectors:</h4>
4644 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4645 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4646 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4647 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4648 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4649 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4653 Roo.DomQuery = function(){
4654 var cache = {}, simpleCache = {}, valueCache = {};
4655 var nonSpace = /\S/;
4656 var trimRe = /^\s+|\s+$/g;
4657 var tplRe = /\{(\d+)\}/g;
4658 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4659 var tagTokenRe = /^(#)?([\w-\*]+)/;
4660 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4662 function child(p, index){
4664 var n = p.firstChild;
4666 if(n.nodeType == 1){
4677 while((n = n.nextSibling) && n.nodeType != 1);
4682 while((n = n.previousSibling) && n.nodeType != 1);
4686 function children(d){
4687 var n = d.firstChild, ni = -1;
4689 var nx = n.nextSibling;
4690 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4700 function byClassName(c, a, v){
4704 var r = [], ri = -1, cn;
4705 for(var i = 0, ci; ci = c[i]; i++){
4706 if((' '+ci.className+' ').indexOf(v) != -1){
4713 function attrValue(n, attr){
4714 if(!n.tagName && typeof n.length != "undefined"){
4723 if(attr == "class" || attr == "className"){
4726 return n.getAttribute(attr) || n[attr];
4730 function getNodes(ns, mode, tagName){
4731 var result = [], ri = -1, cs;
4735 tagName = tagName || "*";
4736 if(typeof ns.getElementsByTagName != "undefined"){
4740 for(var i = 0, ni; ni = ns[i]; i++){
4741 cs = ni.getElementsByTagName(tagName);
4742 for(var j = 0, ci; ci = cs[j]; j++){
4746 }else if(mode == "/" || mode == ">"){
4747 var utag = tagName.toUpperCase();
4748 for(var i = 0, ni, cn; ni = ns[i]; i++){
4749 cn = ni.children || ni.childNodes;
4750 for(var j = 0, cj; cj = cn[j]; j++){
4751 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4756 }else if(mode == "+"){
4757 var utag = tagName.toUpperCase();
4758 for(var i = 0, n; n = ns[i]; i++){
4759 while((n = n.nextSibling) && n.nodeType != 1);
4760 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4764 }else if(mode == "~"){
4765 for(var i = 0, n; n = ns[i]; i++){
4766 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4775 function concat(a, b){
4779 for(var i = 0, l = b.length; i < l; i++){
4785 function byTag(cs, tagName){
4786 if(cs.tagName || cs == document){
4792 var r = [], ri = -1;
4793 tagName = tagName.toLowerCase();
4794 for(var i = 0, ci; ci = cs[i]; i++){
4795 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4802 function byId(cs, attr, id){
4803 if(cs.tagName || cs == document){
4809 var r = [], ri = -1;
4810 for(var i = 0,ci; ci = cs[i]; i++){
4811 if(ci && ci.id == id){
4819 function byAttribute(cs, attr, value, op, custom){
4820 var r = [], ri = -1, st = custom=="{";
4821 var f = Roo.DomQuery.operators[op];
4822 for(var i = 0, ci; ci = cs[i]; i++){
4825 a = Roo.DomQuery.getStyle(ci, attr);
4827 else if(attr == "class" || attr == "className"){
4829 }else if(attr == "for"){
4831 }else if(attr == "href"){
4832 a = ci.getAttribute("href", 2);
4834 a = ci.getAttribute(attr);
4836 if((f && f(a, value)) || (!f && a)){
4843 function byPseudo(cs, name, value){
4844 return Roo.DomQuery.pseudos[name](cs, value);
4847 // This is for IE MSXML which does not support expandos.
4848 // IE runs the same speed using setAttribute, however FF slows way down
4849 // and Safari completely fails so they need to continue to use expandos.
4850 var isIE = window.ActiveXObject ? true : false;
4852 // this eval is stop the compressor from
4853 // renaming the variable to something shorter
4855 /** eval:var:batch */
4860 function nodupIEXml(cs){
4862 cs[0].setAttribute("_nodup", d);
4864 for(var i = 1, len = cs.length; i < len; i++){
4866 if(!c.getAttribute("_nodup") != d){
4867 c.setAttribute("_nodup", d);
4871 for(var i = 0, len = cs.length; i < len; i++){
4872 cs[i].removeAttribute("_nodup");
4881 var len = cs.length, c, i, r = cs, cj, ri = -1;
4882 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4885 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4886 return nodupIEXml(cs);
4890 for(i = 1; c = cs[i]; i++){
4895 for(var j = 0; j < i; j++){
4898 for(j = i+1; cj = cs[j]; j++){
4910 function quickDiffIEXml(c1, c2){
4912 for(var i = 0, len = c1.length; i < len; i++){
4913 c1[i].setAttribute("_qdiff", d);
4916 for(var i = 0, len = c2.length; i < len; i++){
4917 if(c2[i].getAttribute("_qdiff") != d){
4918 r[r.length] = c2[i];
4921 for(var i = 0, len = c1.length; i < len; i++){
4922 c1[i].removeAttribute("_qdiff");
4927 function quickDiff(c1, c2){
4928 var len1 = c1.length;
4932 if(isIE && c1[0].selectSingleNode){
4933 return quickDiffIEXml(c1, c2);
4936 for(var i = 0; i < len1; i++){
4940 for(var i = 0, len = c2.length; i < len; i++){
4941 if(c2[i]._qdiff != d){
4942 r[r.length] = c2[i];
4948 function quickId(ns, mode, root, id){
4950 var d = root.ownerDocument || root;
4951 return d.getElementById(id);
4953 ns = getNodes(ns, mode, "*");
4954 return byId(ns, null, id);
4958 getStyle : function(el, name){
4959 return Roo.fly(el).getStyle(name);
4962 * Compiles a selector/xpath query into a reusable function. The returned function
4963 * takes one parameter "root" (optional), which is the context node from where the query should start.
4964 * @param {String} selector The selector/xpath query
4965 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4966 * @return {Function}
4968 compile : function(path, type){
4969 type = type || "select";
4971 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
4972 var q = path, mode, lq;
4973 var tk = Roo.DomQuery.matchers;
4974 var tklen = tk.length;
4977 // accept leading mode switch
4978 var lmode = q.match(modeRe);
4979 if(lmode && lmode[1]){
4980 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
4981 q = q.replace(lmode[1], "");
4983 // strip leading slashes
4984 while(path.substr(0, 1)=="/"){
4985 path = path.substr(1);
4988 while(q && lq != q){
4990 var tm = q.match(tagTokenRe);
4991 if(type == "select"){
4994 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
4996 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
4998 q = q.replace(tm[0], "");
4999 }else if(q.substr(0, 1) != '@'){
5000 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5005 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5007 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5009 q = q.replace(tm[0], "");
5012 while(!(mm = q.match(modeRe))){
5013 var matched = false;
5014 for(var j = 0; j < tklen; j++){
5016 var m = q.match(t.re);
5018 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5021 q = q.replace(m[0], "");
5026 // prevent infinite loop on bad selector
5028 throw 'Error parsing selector, parsing failed at "' + q + '"';
5032 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5033 q = q.replace(mm[1], "");
5036 fn[fn.length] = "return nodup(n);\n}";
5039 * list of variables that need from compression as they are used by eval.
5049 * eval:var:byClassName
5051 * eval:var:byAttribute
5052 * eval:var:attrValue
5060 * Selects a group of elements.
5061 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5062 * @param {Node} root (optional) The start of the query (defaults to document).
5065 select : function(path, root, type){
5066 if(!root || root == document){
5069 if(typeof root == "string"){
5070 root = document.getElementById(root);
5072 var paths = path.split(",");
5074 for(var i = 0, len = paths.length; i < len; i++){
5075 var p = paths[i].replace(trimRe, "");
5077 cache[p] = Roo.DomQuery.compile(p);
5079 throw p + " is not a valid selector";
5082 var result = cache[p](root);
5083 if(result && result != document){
5084 results = results.concat(result);
5087 if(paths.length > 1){
5088 return nodup(results);
5094 * Selects a single element.
5095 * @param {String} selector The selector/xpath query
5096 * @param {Node} root (optional) The start of the query (defaults to document).
5099 selectNode : function(path, root){
5100 return Roo.DomQuery.select(path, root)[0];
5104 * Selects the value of a node, optionally replacing null with the defaultValue.
5105 * @param {String} selector The selector/xpath query
5106 * @param {Node} root (optional) The start of the query (defaults to document).
5107 * @param {String} defaultValue
5109 selectValue : function(path, root, defaultValue){
5110 path = path.replace(trimRe, "");
5111 if(!valueCache[path]){
5112 valueCache[path] = Roo.DomQuery.compile(path, "select");
5114 var n = valueCache[path](root);
5115 n = n[0] ? n[0] : n;
5116 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5117 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5121 * Selects the value of a node, parsing integers and floats.
5122 * @param {String} selector The selector/xpath query
5123 * @param {Node} root (optional) The start of the query (defaults to document).
5124 * @param {Number} defaultValue
5127 selectNumber : function(path, root, defaultValue){
5128 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5129 return parseFloat(v);
5133 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5134 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5135 * @param {String} selector The simple selector to test
5138 is : function(el, ss){
5139 if(typeof el == "string"){
5140 el = document.getElementById(el);
5142 var isArray = (el instanceof Array);
5143 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5144 return isArray ? (result.length == el.length) : (result.length > 0);
5148 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5149 * @param {Array} el An array of elements to filter
5150 * @param {String} selector The simple selector to test
5151 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5152 * the selector instead of the ones that match
5155 filter : function(els, ss, nonMatches){
5156 ss = ss.replace(trimRe, "");
5157 if(!simpleCache[ss]){
5158 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5160 var result = simpleCache[ss](els);
5161 return nonMatches ? quickDiff(result, els) : result;
5165 * Collection of matching regular expressions and code snippets.
5169 select: 'n = byClassName(n, null, " {1} ");'
5171 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5172 select: 'n = byPseudo(n, "{1}", "{2}");'
5174 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5175 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5178 select: 'n = byId(n, null, "{1}");'
5181 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5186 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5187 * 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, > <.
5190 "=" : function(a, v){
5193 "!=" : function(a, v){
5196 "^=" : function(a, v){
5197 return a && a.substr(0, v.length) == v;
5199 "$=" : function(a, v){
5200 return a && a.substr(a.length-v.length) == v;
5202 "*=" : function(a, v){
5203 return a && a.indexOf(v) !== -1;
5205 "%=" : function(a, v){
5206 return (a % v) == 0;
5208 "|=" : function(a, v){
5209 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5211 "~=" : function(a, v){
5212 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5217 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5218 * and the argument (if any) supplied in the selector.
5221 "first-child" : function(c){
5222 var r = [], ri = -1, n;
5223 for(var i = 0, ci; ci = n = c[i]; i++){
5224 while((n = n.previousSibling) && n.nodeType != 1);
5232 "last-child" : function(c){
5233 var r = [], ri = -1, n;
5234 for(var i = 0, ci; ci = n = c[i]; i++){
5235 while((n = n.nextSibling) && n.nodeType != 1);
5243 "nth-child" : function(c, a) {
5244 var r = [], ri = -1;
5245 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5246 var f = (m[1] || 1) - 0, l = m[2] - 0;
5247 for(var i = 0, n; n = c[i]; i++){
5248 var pn = n.parentNode;
5249 if (batch != pn._batch) {
5251 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5252 if(cn.nodeType == 1){
5259 if (l == 0 || n.nodeIndex == l){
5262 } else if ((n.nodeIndex + l) % f == 0){
5270 "only-child" : function(c){
5271 var r = [], ri = -1;;
5272 for(var i = 0, ci; ci = c[i]; i++){
5273 if(!prev(ci) && !next(ci)){
5280 "empty" : function(c){
5281 var r = [], ri = -1;
5282 for(var i = 0, ci; ci = c[i]; i++){
5283 var cns = ci.childNodes, j = 0, cn, empty = true;
5286 if(cn.nodeType == 1 || cn.nodeType == 3){
5298 "contains" : function(c, v){
5299 var r = [], ri = -1;
5300 for(var i = 0, ci; ci = c[i]; i++){
5301 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5308 "nodeValue" : function(c, v){
5309 var r = [], ri = -1;
5310 for(var i = 0, ci; ci = c[i]; i++){
5311 if(ci.firstChild && ci.firstChild.nodeValue == v){
5318 "checked" : function(c){
5319 var r = [], ri = -1;
5320 for(var i = 0, ci; ci = c[i]; i++){
5321 if(ci.checked == true){
5328 "not" : function(c, ss){
5329 return Roo.DomQuery.filter(c, ss, true);
5332 "odd" : function(c){
5333 return this["nth-child"](c, "odd");
5336 "even" : function(c){
5337 return this["nth-child"](c, "even");
5340 "nth" : function(c, a){
5341 return c[a-1] || [];
5344 "first" : function(c){
5348 "last" : function(c){
5349 return c[c.length-1] || [];
5352 "has" : function(c, ss){
5353 var s = Roo.DomQuery.select;
5354 var r = [], ri = -1;
5355 for(var i = 0, ci; ci = c[i]; i++){
5356 if(s(ss, ci).length > 0){
5363 "next" : function(c, ss){
5364 var is = Roo.DomQuery.is;
5365 var r = [], ri = -1;
5366 for(var i = 0, ci; ci = c[i]; i++){
5375 "prev" : function(c, ss){
5376 var is = Roo.DomQuery.is;
5377 var r = [], ri = -1;
5378 for(var i = 0, ci; ci = c[i]; i++){
5391 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5392 * @param {String} path The selector/xpath query
5393 * @param {Node} root (optional) The start of the query (defaults to document).
5398 Roo.query = Roo.DomQuery.select;
5401 * Ext JS Library 1.1.1
5402 * Copyright(c) 2006-2007, Ext JS, LLC.
5404 * Originally Released Under LGPL - original licence link has changed is not relivant.
5407 * <script type="text/javascript">
5411 * @class Roo.util.Observable
5412 * Base class that provides a common interface for publishing events. Subclasses are expected to
5413 * to have a property "events" with all the events defined.<br>
5416 Employee = function(name){
5423 Roo.extend(Employee, Roo.util.Observable);
5425 * @param {Object} config properties to use (incuding events / listeners)
5428 Roo.util.Observable = function(cfg){
5431 this.addEvents(cfg.events || {});
5433 delete cfg.events; // make sure
5436 Roo.apply(this, cfg);
5439 this.on(this.listeners);
5440 delete this.listeners;
5443 Roo.util.Observable.prototype = {
5445 * @cfg {Object} listeners list of events and functions to call for this object,
5449 'click' : function(e) {
5459 * Fires the specified event with the passed parameters (minus the event name).
5460 * @param {String} eventName
5461 * @param {Object...} args Variable number of parameters are passed to handlers
5462 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5464 fireEvent : function(){
5465 var ce = this.events[arguments[0].toLowerCase()];
5466 if(typeof ce == "object"){
5467 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5474 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5477 * Appends an event handler to this component
5478 * @param {String} eventName The type of event to listen for
5479 * @param {Function} handler The method the event invokes
5480 * @param {Object} scope (optional) The scope in which to execute the handler
5481 * function. The handler function's "this" context.
5482 * @param {Object} options (optional) An object containing handler configuration
5483 * properties. This may contain any of the following properties:<ul>
5484 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5485 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5486 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5487 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5488 * by the specified number of milliseconds. If the event fires again within that time, the original
5489 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5492 * <b>Combining Options</b><br>
5493 * Using the options argument, it is possible to combine different types of listeners:<br>
5495 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5497 el.on('click', this.onClick, this, {
5504 * <b>Attaching multiple handlers in 1 call</b><br>
5505 * The method also allows for a single argument to be passed which is a config object containing properties
5506 * which specify multiple handlers.
5515 fn: this.onMouseOver,
5519 fn: this.onMouseOut,
5525 * Or a shorthand syntax which passes the same scope object to all handlers:
5528 'click': this.onClick,
5529 'mouseover': this.onMouseOver,
5530 'mouseout': this.onMouseOut,
5535 addListener : function(eventName, fn, scope, o){
5536 if(typeof eventName == "object"){
5539 if(this.filterOptRe.test(e)){
5542 if(typeof o[e] == "function"){
5544 this.addListener(e, o[e], o.scope, o);
5546 // individual options
5547 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5552 o = (!o || typeof o == "boolean") ? {} : o;
5553 eventName = eventName.toLowerCase();
5554 var ce = this.events[eventName] || true;
5555 if(typeof ce == "boolean"){
5556 ce = new Roo.util.Event(this, eventName);
5557 this.events[eventName] = ce;
5559 ce.addListener(fn, scope, o);
5563 * Removes a listener
5564 * @param {String} eventName The type of event to listen for
5565 * @param {Function} handler The handler to remove
5566 * @param {Object} scope (optional) The scope (this object) for the handler
5568 removeListener : function(eventName, fn, scope){
5569 var ce = this.events[eventName.toLowerCase()];
5570 if(typeof ce == "object"){
5571 ce.removeListener(fn, scope);
5576 * Removes all listeners for this object
5578 purgeListeners : function(){
5579 for(var evt in this.events){
5580 if(typeof this.events[evt] == "object"){
5581 this.events[evt].clearListeners();
5586 relayEvents : function(o, events){
5587 var createHandler = function(ename){
5589 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5592 for(var i = 0, len = events.length; i < len; i++){
5593 var ename = events[i];
5594 if(!this.events[ename]){ this.events[ename] = true; };
5595 o.on(ename, createHandler(ename), this);
5600 * Used to define events on this Observable
5601 * @param {Object} object The object with the events defined
5603 addEvents : function(o){
5607 Roo.applyIf(this.events, o);
5611 * Checks to see if this object has any listeners for a specified event
5612 * @param {String} eventName The name of the event to check for
5613 * @return {Boolean} True if the event is being listened for, else false
5615 hasListener : function(eventName){
5616 var e = this.events[eventName];
5617 return typeof e == "object" && e.listeners.length > 0;
5621 * Appends an event handler to this element (shorthand for addListener)
5622 * @param {String} eventName The type of event to listen for
5623 * @param {Function} handler The method the event invokes
5624 * @param {Object} scope (optional) The scope in which to execute the handler
5625 * function. The handler function's "this" context.
5626 * @param {Object} options (optional)
5629 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5631 * Removes a listener (shorthand for removeListener)
5632 * @param {String} eventName The type of event to listen for
5633 * @param {Function} handler The handler to remove
5634 * @param {Object} scope (optional) The scope (this object) for the handler
5637 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5640 * Starts capture on the specified Observable. All events will be passed
5641 * to the supplied function with the event name + standard signature of the event
5642 * <b>before</b> the event is fired. If the supplied function returns false,
5643 * the event will not fire.
5644 * @param {Observable} o The Observable to capture
5645 * @param {Function} fn The function to call
5646 * @param {Object} scope (optional) The scope (this object) for the fn
5649 Roo.util.Observable.capture = function(o, fn, scope){
5650 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5654 * Removes <b>all</b> added captures from the Observable.
5655 * @param {Observable} o The Observable to release
5658 Roo.util.Observable.releaseCapture = function(o){
5659 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5664 var createBuffered = function(h, o, scope){
5665 var task = new Roo.util.DelayedTask();
5667 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5671 var createSingle = function(h, e, fn, scope){
5673 e.removeListener(fn, scope);
5674 return h.apply(scope, arguments);
5678 var createDelayed = function(h, o, scope){
5680 var args = Array.prototype.slice.call(arguments, 0);
5681 setTimeout(function(){
5682 h.apply(scope, args);
5687 Roo.util.Event = function(obj, name){
5690 this.listeners = [];
5693 Roo.util.Event.prototype = {
5694 addListener : function(fn, scope, options){
5695 var o = options || {};
5696 scope = scope || this.obj;
5697 if(!this.isListening(fn, scope)){
5698 var l = {fn: fn, scope: scope, options: o};
5701 h = createDelayed(h, o, scope);
5704 h = createSingle(h, this, fn, scope);
5707 h = createBuffered(h, o, scope);
5710 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5711 this.listeners.push(l);
5713 this.listeners = this.listeners.slice(0);
5714 this.listeners.push(l);
5719 findListener : function(fn, scope){
5720 scope = scope || this.obj;
5721 var ls = this.listeners;
5722 for(var i = 0, len = ls.length; i < len; i++){
5724 if(l.fn == fn && l.scope == scope){
5731 isListening : function(fn, scope){
5732 return this.findListener(fn, scope) != -1;
5735 removeListener : function(fn, scope){
5737 if((index = this.findListener(fn, scope)) != -1){
5739 this.listeners.splice(index, 1);
5741 this.listeners = this.listeners.slice(0);
5742 this.listeners.splice(index, 1);
5749 clearListeners : function(){
5750 this.listeners = [];
5754 var ls = this.listeners, scope, len = ls.length;
5757 var args = Array.prototype.slice.call(arguments, 0);
5758 for(var i = 0; i < len; i++){
5760 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5761 this.firing = false;
5765 this.firing = false;
5772 * Ext JS Library 1.1.1
5773 * Copyright(c) 2006-2007, Ext JS, LLC.
5775 * Originally Released Under LGPL - original licence link has changed is not relivant.
5778 * <script type="text/javascript">
5782 * @class Roo.EventManager
5783 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5784 * several useful events directly.
5785 * See {@link Roo.EventObject} for more details on normalized event objects.
5788 Roo.EventManager = function(){
5789 var docReadyEvent, docReadyProcId, docReadyState = false;
5790 var resizeEvent, resizeTask, textEvent, textSize;
5791 var E = Roo.lib.Event;
5792 var D = Roo.lib.Dom;
5795 var fireDocReady = function(){
5797 docReadyState = true;
5800 clearInterval(docReadyProcId);
5802 if(Roo.isGecko || Roo.isOpera) {
5803 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5806 var defer = document.getElementById("ie-deferred-loader");
5808 defer.onreadystatechange = null;
5809 defer.parentNode.removeChild(defer);
5813 docReadyEvent.fire();
5814 docReadyEvent.clearListeners();
5819 var initDocReady = function(){
5820 docReadyEvent = new Roo.util.Event();
5821 if(Roo.isGecko || Roo.isOpera) {
5822 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5824 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5825 var defer = document.getElementById("ie-deferred-loader");
5826 defer.onreadystatechange = function(){
5827 if(this.readyState == "complete"){
5831 }else if(Roo.isSafari){
5832 docReadyProcId = setInterval(function(){
5833 var rs = document.readyState;
5834 if(rs == "complete") {
5839 // no matter what, make sure it fires on load
5840 E.on(window, "load", fireDocReady);
5843 var createBuffered = function(h, o){
5844 var task = new Roo.util.DelayedTask(h);
5846 // create new event object impl so new events don't wipe out properties
5847 e = new Roo.EventObjectImpl(e);
5848 task.delay(o.buffer, h, null, [e]);
5852 var createSingle = function(h, el, ename, fn){
5854 Roo.EventManager.removeListener(el, ename, fn);
5859 var createDelayed = function(h, o){
5861 // create new event object impl so new events don't wipe out properties
5862 e = new Roo.EventObjectImpl(e);
5863 setTimeout(function(){
5869 var listen = function(element, ename, opt, fn, scope){
5870 var o = (!opt || typeof opt == "boolean") ? {} : opt;
5871 fn = fn || o.fn; scope = scope || o.scope;
5872 var el = Roo.getDom(element);
5874 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
5876 var h = function(e){
5877 e = Roo.EventObject.setEvent(e);
5880 t = e.getTarget(o.delegate, el);
5887 if(o.stopEvent === true){
5890 if(o.preventDefault === true){
5893 if(o.stopPropagation === true){
5894 e.stopPropagation();
5897 if(o.normalized === false){
5901 fn.call(scope || el, e, t, o);
5904 h = createDelayed(h, o);
5907 h = createSingle(h, el, ename, fn);
5910 h = createBuffered(h, o);
5912 fn._handlers = fn._handlers || [];
5913 fn._handlers.push([Roo.id(el), ename, h]);
5916 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
5917 el.addEventListener("DOMMouseScroll", h, false);
5918 E.on(window, 'unload', function(){
5919 el.removeEventListener("DOMMouseScroll", h, false);
5922 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5923 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
5928 var stopListening = function(el, ename, fn){
5929 var id = Roo.id(el), hds = fn._handlers, hd = fn;
5931 for(var i = 0, len = hds.length; i < len; i++){
5933 if(h[0] == id && h[1] == ename){
5940 E.un(el, ename, hd);
5941 el = Roo.getDom(el);
5942 if(ename == "mousewheel" && el.addEventListener){
5943 el.removeEventListener("DOMMouseScroll", hd, false);
5945 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5946 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
5950 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
5957 * @scope Roo.EventManager
5962 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
5963 * object with a Roo.EventObject
5964 * @param {Function} fn The method the event invokes
5965 * @param {Object} scope An object that becomes the scope of the handler
5966 * @param {boolean} override If true, the obj passed in becomes
5967 * the execution scope of the listener
5968 * @return {Function} The wrapped function
5971 wrap : function(fn, scope, override){
5973 Roo.EventObject.setEvent(e);
5974 fn.call(override ? scope || window : window, Roo.EventObject, scope);
5979 * Appends an event handler to an element (shorthand for addListener)
5980 * @param {String/HTMLElement} element The html element or id to assign the
5981 * @param {String} eventName The type of event to listen for
5982 * @param {Function} handler The method the event invokes
5983 * @param {Object} scope (optional) The scope in which to execute the handler
5984 * function. The handler function's "this" context.
5985 * @param {Object} options (optional) An object containing handler configuration
5986 * properties. This may contain any of the following properties:<ul>
5987 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5988 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
5989 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
5990 * <li>preventDefault {Boolean} True to prevent the default action</li>
5991 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
5992 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
5993 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5994 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5995 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5996 * by the specified number of milliseconds. If the event fires again within that time, the original
5997 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6000 * <b>Combining Options</b><br>
6001 * Using the options argument, it is possible to combine different types of listeners:<br>
6003 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6005 el.on('click', this.onClick, this, {
6012 * <b>Attaching multiple handlers in 1 call</b><br>
6013 * The method also allows for a single argument to be passed which is a config object containing properties
6014 * which specify multiple handlers.
6024 fn: this.onMouseOver
6033 * Or a shorthand syntax:<br>
6036 'click' : this.onClick,
6037 'mouseover' : this.onMouseOver,
6038 'mouseout' : this.onMouseOut
6042 addListener : function(element, eventName, fn, scope, options){
6043 if(typeof eventName == "object"){
6049 if(typeof o[e] == "function"){
6051 listen(element, e, o, o[e], o.scope);
6053 // individual options
6054 listen(element, e, o[e]);
6059 return listen(element, eventName, options, fn, scope);
6063 * Removes an event handler
6065 * @param {String/HTMLElement} element The id or html element to remove the
6067 * @param {String} eventName The type of event
6068 * @param {Function} fn
6069 * @return {Boolean} True if a listener was actually removed
6071 removeListener : function(element, eventName, fn){
6072 return stopListening(element, eventName, fn);
6076 * Fires when the document is ready (before onload and before images are loaded). Can be
6077 * accessed shorthanded Roo.onReady().
6078 * @param {Function} fn The method the event invokes
6079 * @param {Object} scope An object that becomes the scope of the handler
6080 * @param {boolean} options
6082 onDocumentReady : function(fn, scope, options){
6083 if(docReadyState){ // if it already fired
6084 docReadyEvent.addListener(fn, scope, options);
6085 docReadyEvent.fire();
6086 docReadyEvent.clearListeners();
6092 docReadyEvent.addListener(fn, scope, options);
6096 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6097 * @param {Function} fn The method the event invokes
6098 * @param {Object} scope An object that becomes the scope of the handler
6099 * @param {boolean} options
6101 onWindowResize : function(fn, scope, options){
6103 resizeEvent = new Roo.util.Event();
6104 resizeTask = new Roo.util.DelayedTask(function(){
6105 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6107 E.on(window, "resize", function(){
6109 resizeTask.delay(50);
6111 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6115 resizeEvent.addListener(fn, scope, options);
6119 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6120 * @param {Function} fn The method the event invokes
6121 * @param {Object} scope An object that becomes the scope of the handler
6122 * @param {boolean} options
6124 onTextResize : function(fn, scope, options){
6126 textEvent = new Roo.util.Event();
6127 var textEl = new Roo.Element(document.createElement('div'));
6128 textEl.dom.className = 'x-text-resize';
6129 textEl.dom.innerHTML = 'X';
6130 textEl.appendTo(document.body);
6131 textSize = textEl.dom.offsetHeight;
6132 setInterval(function(){
6133 if(textEl.dom.offsetHeight != textSize){
6134 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6136 }, this.textResizeInterval);
6138 textEvent.addListener(fn, scope, options);
6142 * Removes the passed window resize listener.
6143 * @param {Function} fn The method the event invokes
6144 * @param {Object} scope The scope of handler
6146 removeResizeListener : function(fn, scope){
6148 resizeEvent.removeListener(fn, scope);
6153 fireResize : function(){
6155 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6159 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6163 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6165 textResizeInterval : 50
6170 * @scopeAlias pub=Roo.EventManager
6174 * Appends an event handler to an element (shorthand for addListener)
6175 * @param {String/HTMLElement} element The html element or id to assign the
6176 * @param {String} eventName The type of event to listen for
6177 * @param {Function} handler The method the event invokes
6178 * @param {Object} scope (optional) The scope in which to execute the handler
6179 * function. The handler function's "this" context.
6180 * @param {Object} options (optional) An object containing handler configuration
6181 * properties. This may contain any of the following properties:<ul>
6182 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6183 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6184 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6185 * <li>preventDefault {Boolean} True to prevent the default action</li>
6186 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6187 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6188 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6189 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6190 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6191 * by the specified number of milliseconds. If the event fires again within that time, the original
6192 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6195 * <b>Combining Options</b><br>
6196 * Using the options argument, it is possible to combine different types of listeners:<br>
6198 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6200 el.on('click', this.onClick, this, {
6207 * <b>Attaching multiple handlers in 1 call</b><br>
6208 * The method also allows for a single argument to be passed which is a config object containing properties
6209 * which specify multiple handlers.
6219 fn: this.onMouseOver
6228 * Or a shorthand syntax:<br>
6231 'click' : this.onClick,
6232 'mouseover' : this.onMouseOver,
6233 'mouseout' : this.onMouseOut
6237 pub.on = pub.addListener;
6238 pub.un = pub.removeListener;
6240 pub.stoppedMouseDownEvent = new Roo.util.Event();
6244 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6245 * @param {Function} fn The method the event invokes
6246 * @param {Object} scope An object that becomes the scope of the handler
6247 * @param {boolean} override If true, the obj passed in becomes
6248 * the execution scope of the listener
6252 Roo.onReady = Roo.EventManager.onDocumentReady;
6254 Roo.onReady(function(){
6255 var bd = Roo.get(document.body);
6260 : Roo.isGecko ? "roo-gecko"
6261 : Roo.isOpera ? "roo-opera"
6262 : Roo.isSafari ? "roo-safari" : ""];
6265 cls.push("roo-mac");
6268 cls.push("roo-linux");
6270 if(Roo.isBorderBox){
6271 cls.push('roo-border-box');
6273 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6274 var p = bd.dom.parentNode;
6276 p.className += ' roo-strict';
6279 bd.addClass(cls.join(' '));
6283 * @class Roo.EventObject
6284 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6285 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6288 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6290 var target = e.getTarget();
6293 var myDiv = Roo.get("myDiv");
6294 myDiv.on("click", handleClick);
6296 Roo.EventManager.on("myDiv", 'click', handleClick);
6297 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6301 Roo.EventObject = function(){
6303 var E = Roo.lib.Event;
6305 // safari keypress events for special keys return bad keycodes
6308 63235 : 39, // right
6311 63276 : 33, // page up
6312 63277 : 34, // page down
6313 63272 : 46, // delete
6318 // normalize button clicks
6319 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6320 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6322 Roo.EventObjectImpl = function(e){
6324 this.setEvent(e.browserEvent || e);
6327 Roo.EventObjectImpl.prototype = {
6329 * Used to fix doc tools.
6330 * @scope Roo.EventObject.prototype
6336 /** The normal browser event */
6337 browserEvent : null,
6338 /** The button pressed in a mouse event */
6340 /** True if the shift key was down during the event */
6342 /** True if the control key was down during the event */
6344 /** True if the alt key was down during the event */
6403 setEvent : function(e){
6404 if(e == this || (e && e.browserEvent)){ // already wrapped
6407 this.browserEvent = e;
6409 // normalize buttons
6410 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6411 if(e.type == 'click' && this.button == -1){
6415 this.shiftKey = e.shiftKey;
6416 // mac metaKey behaves like ctrlKey
6417 this.ctrlKey = e.ctrlKey || e.metaKey;
6418 this.altKey = e.altKey;
6419 // in getKey these will be normalized for the mac
6420 this.keyCode = e.keyCode;
6421 // keyup warnings on firefox.
6422 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6423 // cache the target for the delayed and or buffered events
6424 this.target = E.getTarget(e);
6426 this.xy = E.getXY(e);
6429 this.shiftKey = false;
6430 this.ctrlKey = false;
6431 this.altKey = false;
6441 * Stop the event (preventDefault and stopPropagation)
6443 stopEvent : function(){
6444 if(this.browserEvent){
6445 if(this.browserEvent.type == 'mousedown'){
6446 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6448 E.stopEvent(this.browserEvent);
6453 * Prevents the browsers default handling of the event.
6455 preventDefault : function(){
6456 if(this.browserEvent){
6457 E.preventDefault(this.browserEvent);
6462 isNavKeyPress : function(){
6463 var k = this.keyCode;
6464 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6465 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6468 isSpecialKey : function(){
6469 var k = this.keyCode;
6470 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6471 (k == 16) || (k == 17) ||
6472 (k >= 18 && k <= 20) ||
6473 (k >= 33 && k <= 35) ||
6474 (k >= 36 && k <= 39) ||
6475 (k >= 44 && k <= 45);
6478 * Cancels bubbling of the event.
6480 stopPropagation : function(){
6481 if(this.browserEvent){
6482 if(this.type == 'mousedown'){
6483 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6485 E.stopPropagation(this.browserEvent);
6490 * Gets the key code for the event.
6493 getCharCode : function(){
6494 return this.charCode || this.keyCode;
6498 * Returns a normalized keyCode for the event.
6499 * @return {Number} The key code
6501 getKey : function(){
6502 var k = this.keyCode || this.charCode;
6503 return Roo.isSafari ? (safariKeys[k] || k) : k;
6507 * Gets the x coordinate of the event.
6510 getPageX : function(){
6515 * Gets the y coordinate of the event.
6518 getPageY : function(){
6523 * Gets the time of the event.
6526 getTime : function(){
6527 if(this.browserEvent){
6528 return E.getTime(this.browserEvent);
6534 * Gets the page coordinates of the event.
6535 * @return {Array} The xy values like [x, y]
6542 * Gets the target for the event.
6543 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6544 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6545 search as a number or element (defaults to 10 || document.body)
6546 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6547 * @return {HTMLelement}
6549 getTarget : function(selector, maxDepth, returnEl){
6550 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6553 * Gets the related target.
6554 * @return {HTMLElement}
6556 getRelatedTarget : function(){
6557 if(this.browserEvent){
6558 return E.getRelatedTarget(this.browserEvent);
6564 * Normalizes mouse wheel delta across browsers
6565 * @return {Number} The delta
6567 getWheelDelta : function(){
6568 var e = this.browserEvent;
6570 if(e.wheelDelta){ /* IE/Opera. */
6571 delta = e.wheelDelta/120;
6572 }else if(e.detail){ /* Mozilla case. */
6573 delta = -e.detail/3;
6579 * Returns true if the control, meta, shift or alt key was pressed during this event.
6582 hasModifier : function(){
6583 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6587 * Returns true if the target of this event equals el or is a child of el
6588 * @param {String/HTMLElement/Element} el
6589 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6592 within : function(el, related){
6593 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6594 return t && Roo.fly(el).contains(t);
6597 getPoint : function(){
6598 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6602 return new Roo.EventObjectImpl();
6607 * Ext JS Library 1.1.1
6608 * Copyright(c) 2006-2007, Ext JS, LLC.
6610 * Originally Released Under LGPL - original licence link has changed is not relivant.
6613 * <script type="text/javascript">
6617 // was in Composite Element!??!?!
6620 var D = Roo.lib.Dom;
6621 var E = Roo.lib.Event;
6622 var A = Roo.lib.Anim;
6624 // local style camelizing for speed
6626 var camelRe = /(-[a-z])/gi;
6627 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6628 var view = document.defaultView;
6631 * @class Roo.Element
6632 * Represents an Element in the DOM.<br><br>
6635 var el = Roo.get("my-div");
6638 var el = getEl("my-div");
6640 // or with a DOM element
6641 var el = Roo.get(myDivElement);
6643 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6644 * each call instead of constructing a new one.<br><br>
6645 * <b>Animations</b><br />
6646 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6647 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6649 Option Default Description
6650 --------- -------- ---------------------------------------------
6651 duration .35 The duration of the animation in seconds
6652 easing easeOut The YUI easing method
6653 callback none A function to execute when the anim completes
6654 scope this The scope (this) of the callback function
6656 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6657 * manipulate the animation. Here's an example:
6659 var el = Roo.get("my-div");
6664 // default animation
6665 el.setWidth(100, true);
6667 // animation with some options set
6674 // using the "anim" property to get the Anim object
6680 el.setWidth(100, opt);
6682 if(opt.anim.isAnimated()){
6686 * <b> Composite (Collections of) Elements</b><br />
6687 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6688 * @constructor Create a new Element directly.
6689 * @param {String/HTMLElement} element
6690 * @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).
6692 Roo.Element = function(element, forceNew){
6693 var dom = typeof element == "string" ?
6694 document.getElementById(element) : element;
6695 if(!dom){ // invalid id/element
6699 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6700 return Roo.Element.cache[id];
6710 * The DOM element ID
6713 this.id = id || Roo.id(dom);
6716 var El = Roo.Element;
6720 * The element's default display mode (defaults to "")
6723 originalDisplay : "",
6727 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6732 * Sets the element's visibility mode. When setVisible() is called it
6733 * will use this to determine whether to set the visibility or the display property.
6734 * @param visMode Element.VISIBILITY or Element.DISPLAY
6735 * @return {Roo.Element} this
6737 setVisibilityMode : function(visMode){
6738 this.visibilityMode = visMode;
6742 * Convenience method for setVisibilityMode(Element.DISPLAY)
6743 * @param {String} display (optional) What to set display to when visible
6744 * @return {Roo.Element} this
6746 enableDisplayMode : function(display){
6747 this.setVisibilityMode(El.DISPLAY);
6748 if(typeof display != "undefined") this.originalDisplay = display;
6753 * 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)
6754 * @param {String} selector The simple selector to test
6755 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6756 search as a number or element (defaults to 10 || document.body)
6757 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6758 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6760 findParent : function(simpleSelector, maxDepth, returnEl){
6761 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6762 maxDepth = maxDepth || 50;
6763 if(typeof maxDepth != "number"){
6764 stopEl = Roo.getDom(maxDepth);
6767 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6768 if(dq.is(p, simpleSelector)){
6769 return returnEl ? Roo.get(p) : p;
6779 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6780 * @param {String} selector The simple selector to test
6781 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6782 search as a number or element (defaults to 10 || document.body)
6783 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6784 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6786 findParentNode : function(simpleSelector, maxDepth, returnEl){
6787 var p = Roo.fly(this.dom.parentNode, '_internal');
6788 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6792 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6793 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6794 * @param {String} selector The simple selector to test
6795 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6796 search as a number or element (defaults to 10 || document.body)
6797 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6799 up : function(simpleSelector, maxDepth){
6800 return this.findParentNode(simpleSelector, maxDepth, true);
6806 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6807 * @param {String} selector The simple selector to test
6808 * @return {Boolean} True if this element matches the selector, else false
6810 is : function(simpleSelector){
6811 return Roo.DomQuery.is(this.dom, simpleSelector);
6815 * Perform animation on this element.
6816 * @param {Object} args The YUI animation control args
6817 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6818 * @param {Function} onComplete (optional) Function to call when animation completes
6819 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6820 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6821 * @return {Roo.Element} this
6823 animate : function(args, duration, onComplete, easing, animType){
6824 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6829 * @private Internal animation call
6831 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6832 animType = animType || 'run';
6834 var anim = Roo.lib.Anim[animType](
6836 (opt.duration || defaultDur) || .35,
6837 (opt.easing || defaultEase) || 'easeOut',
6839 Roo.callback(cb, this);
6840 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6848 // private legacy anim prep
6849 preanim : function(a, i){
6850 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6854 * Removes worthless text nodes
6855 * @param {Boolean} forceReclean (optional) By default the element
6856 * keeps track if it has been cleaned already so
6857 * you can call this over and over. However, if you update the element and
6858 * need to force a reclean, you can pass true.
6860 clean : function(forceReclean){
6861 if(this.isCleaned && forceReclean !== true){
6865 var d = this.dom, n = d.firstChild, ni = -1;
6867 var nx = n.nextSibling;
6868 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
6875 this.isCleaned = true;
6880 calcOffsetsTo : function(el){
6883 var restorePos = false;
6884 if(el.getStyle('position') == 'static'){
6885 el.position('relative');
6890 while(op && op != d && op.tagName != 'HTML'){
6893 op = op.offsetParent;
6896 el.position('static');
6902 * Scrolls this element into view within the passed container.
6903 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
6904 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
6905 * @return {Roo.Element} this
6907 scrollIntoView : function(container, hscroll){
6908 var c = Roo.getDom(container) || document.body;
6911 var o = this.calcOffsetsTo(c),
6914 b = t+el.offsetHeight,
6915 r = l+el.offsetWidth;
6917 var ch = c.clientHeight;
6918 var ct = parseInt(c.scrollTop, 10);
6919 var cl = parseInt(c.scrollLeft, 10);
6921 var cr = cl + c.clientWidth;
6929 if(hscroll !== false){
6933 c.scrollLeft = r-c.clientWidth;
6940 scrollChildIntoView : function(child, hscroll){
6941 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
6945 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
6946 * the new height may not be available immediately.
6947 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
6948 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
6949 * @param {Function} onComplete (optional) Function to call when animation completes
6950 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
6951 * @return {Roo.Element} this
6953 autoHeight : function(animate, duration, onComplete, easing){
6954 var oldHeight = this.getHeight();
6956 this.setHeight(1); // force clipping
6957 setTimeout(function(){
6958 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
6960 this.setHeight(height);
6962 if(typeof onComplete == "function"){
6966 this.setHeight(oldHeight); // restore original height
6967 this.setHeight(height, animate, duration, function(){
6969 if(typeof onComplete == "function") onComplete();
6970 }.createDelegate(this), easing);
6972 }.createDelegate(this), 0);
6977 * Returns true if this element is an ancestor of the passed element
6978 * @param {HTMLElement/String} el The element to check
6979 * @return {Boolean} True if this element is an ancestor of el, else false
6981 contains : function(el){
6982 if(!el){return false;}
6983 return D.isAncestor(this.dom, el.dom ? el.dom : el);
6987 * Checks whether the element is currently visible using both visibility and display properties.
6988 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
6989 * @return {Boolean} True if the element is currently visible, else false
6991 isVisible : function(deep) {
6992 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
6993 if(deep !== true || !vis){
6996 var p = this.dom.parentNode;
6997 while(p && p.tagName.toLowerCase() != "body"){
6998 if(!Roo.fly(p, '_isVisible').isVisible()){
7007 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7008 * @param {String} selector The CSS selector
7009 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7010 * @return {CompositeElement/CompositeElementLite} The composite element
7012 select : function(selector, unique){
7013 return El.select(selector, unique, this.dom);
7017 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7018 * @param {String} selector The CSS selector
7019 * @return {Array} An array of the matched nodes
7021 query : function(selector, unique){
7022 return Roo.DomQuery.select(selector, this.dom);
7026 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7027 * @param {String} selector The CSS selector
7028 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7029 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7031 child : function(selector, returnDom){
7032 var n = Roo.DomQuery.selectNode(selector, this.dom);
7033 return returnDom ? n : Roo.get(n);
7037 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7038 * @param {String} selector The CSS selector
7039 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7040 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7042 down : function(selector, returnDom){
7043 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7044 return returnDom ? n : Roo.get(n);
7048 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7049 * @param {String} group The group the DD object is member of
7050 * @param {Object} config The DD config object
7051 * @param {Object} overrides An object containing methods to override/implement on the DD object
7052 * @return {Roo.dd.DD} The DD object
7054 initDD : function(group, config, overrides){
7055 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7056 return Roo.apply(dd, overrides);
7060 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7061 * @param {String} group The group the DDProxy object is member of
7062 * @param {Object} config The DDProxy config object
7063 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7064 * @return {Roo.dd.DDProxy} The DDProxy object
7066 initDDProxy : function(group, config, overrides){
7067 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7068 return Roo.apply(dd, overrides);
7072 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7073 * @param {String} group The group the DDTarget object is member of
7074 * @param {Object} config The DDTarget config object
7075 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7076 * @return {Roo.dd.DDTarget} The DDTarget object
7078 initDDTarget : function(group, config, overrides){
7079 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7080 return Roo.apply(dd, overrides);
7084 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7085 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7086 * @param {Boolean} visible Whether the element is visible
7087 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7088 * @return {Roo.Element} this
7090 setVisible : function(visible, animate){
7092 if(this.visibilityMode == El.DISPLAY){
7093 this.setDisplayed(visible);
7096 this.dom.style.visibility = visible ? "visible" : "hidden";
7099 // closure for composites
7101 var visMode = this.visibilityMode;
7103 this.setOpacity(.01);
7104 this.setVisible(true);
7106 this.anim({opacity: { to: (visible?1:0) }},
7107 this.preanim(arguments, 1),
7108 null, .35, 'easeIn', function(){
7110 if(visMode == El.DISPLAY){
7111 dom.style.display = "none";
7113 dom.style.visibility = "hidden";
7115 Roo.get(dom).setOpacity(1);
7123 * Returns true if display is not "none"
7126 isDisplayed : function() {
7127 return this.getStyle("display") != "none";
7131 * Toggles the element's visibility or display, depending on visibility mode.
7132 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7133 * @return {Roo.Element} this
7135 toggle : function(animate){
7136 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7141 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7142 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7143 * @return {Roo.Element} this
7145 setDisplayed : function(value) {
7146 if(typeof value == "boolean"){
7147 value = value ? this.originalDisplay : "none";
7149 this.setStyle("display", value);
7154 * Tries to focus the element. Any exceptions are caught and ignored.
7155 * @return {Roo.Element} this
7157 focus : function() {
7165 * Tries to blur the element. Any exceptions are caught and ignored.
7166 * @return {Roo.Element} this
7176 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7177 * @param {String/Array} className The CSS class to add, or an array of classes
7178 * @return {Roo.Element} this
7180 addClass : function(className){
7181 if(className instanceof Array){
7182 for(var i = 0, len = className.length; i < len; i++) {
7183 this.addClass(className[i]);
7186 if(className && !this.hasClass(className)){
7187 this.dom.className = this.dom.className + " " + className;
7194 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7195 * @param {String/Array} className The CSS class to add, or an array of classes
7196 * @return {Roo.Element} this
7198 radioClass : function(className){
7199 var siblings = this.dom.parentNode.childNodes;
7200 for(var i = 0; i < siblings.length; i++) {
7201 var s = siblings[i];
7202 if(s.nodeType == 1){
7203 Roo.get(s).removeClass(className);
7206 this.addClass(className);
7211 * Removes one or more CSS classes from the element.
7212 * @param {String/Array} className The CSS class to remove, or an array of classes
7213 * @return {Roo.Element} this
7215 removeClass : function(className){
7216 if(!className || !this.dom.className){
7219 if(className instanceof Array){
7220 for(var i = 0, len = className.length; i < len; i++) {
7221 this.removeClass(className[i]);
7224 if(this.hasClass(className)){
7225 var re = this.classReCache[className];
7227 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7228 this.classReCache[className] = re;
7230 this.dom.className =
7231 this.dom.className.replace(re, " ");
7241 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7242 * @param {String} className The CSS class to toggle
7243 * @return {Roo.Element} this
7245 toggleClass : function(className){
7246 if(this.hasClass(className)){
7247 this.removeClass(className);
7249 this.addClass(className);
7255 * Checks if the specified CSS class exists on this element's DOM node.
7256 * @param {String} className The CSS class to check for
7257 * @return {Boolean} True if the class exists, else false
7259 hasClass : function(className){
7260 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7264 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7265 * @param {String} oldClassName The CSS class to replace
7266 * @param {String} newClassName The replacement CSS class
7267 * @return {Roo.Element} this
7269 replaceClass : function(oldClassName, newClassName){
7270 this.removeClass(oldClassName);
7271 this.addClass(newClassName);
7276 * Returns an object with properties matching the styles requested.
7277 * For example, el.getStyles('color', 'font-size', 'width') might return
7278 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7279 * @param {String} style1 A style name
7280 * @param {String} style2 A style name
7281 * @param {String} etc.
7282 * @return {Object} The style object
7284 getStyles : function(){
7285 var a = arguments, len = a.length, r = {};
7286 for(var i = 0; i < len; i++){
7287 r[a[i]] = this.getStyle(a[i]);
7293 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7294 * @param {String} property The style property whose value is returned.
7295 * @return {String} The current value of the style property for this element.
7297 getStyle : function(){
7298 return view && view.getComputedStyle ?
7300 var el = this.dom, v, cs, camel;
7301 if(prop == 'float'){
7304 if(el.style && (v = el.style[prop])){
7307 if(cs = view.getComputedStyle(el, "")){
7308 if(!(camel = propCache[prop])){
7309 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7316 var el = this.dom, v, cs, camel;
7317 if(prop == 'opacity'){
7318 if(typeof el.style.filter == 'string'){
7319 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7321 var fv = parseFloat(m[1]);
7323 return fv ? fv / 100 : 0;
7328 }else if(prop == 'float'){
7329 prop = "styleFloat";
7331 if(!(camel = propCache[prop])){
7332 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7334 if(v = el.style[camel]){
7337 if(cs = el.currentStyle){
7345 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7346 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7347 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7348 * @return {Roo.Element} this
7350 setStyle : function(prop, value){
7351 if(typeof prop == "string"){
7353 if(!(camel = propCache[prop])){
7354 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7356 if(camel == 'opacity') {
7357 this.setOpacity(value);
7359 this.dom.style[camel] = value;
7362 for(var style in prop){
7363 if(typeof prop[style] != "function"){
7364 this.setStyle(style, prop[style]);
7372 * More flexible version of {@link #setStyle} for setting style properties.
7373 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7374 * a function which returns such a specification.
7375 * @return {Roo.Element} this
7377 applyStyles : function(style){
7378 Roo.DomHelper.applyStyles(this.dom, style);
7383 * 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).
7384 * @return {Number} The X position of the element
7387 return D.getX(this.dom);
7391 * 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).
7392 * @return {Number} The Y position of the element
7395 return D.getY(this.dom);
7399 * 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).
7400 * @return {Array} The XY position of the element
7403 return D.getXY(this.dom);
7407 * 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).
7408 * @param {Number} The X position of the element
7409 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7410 * @return {Roo.Element} this
7412 setX : function(x, animate){
7414 D.setX(this.dom, x);
7416 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7422 * 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).
7423 * @param {Number} The Y position of the element
7424 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7425 * @return {Roo.Element} this
7427 setY : function(y, animate){
7429 D.setY(this.dom, y);
7431 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7437 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7438 * @param {String} left The left CSS property value
7439 * @return {Roo.Element} this
7441 setLeft : function(left){
7442 this.setStyle("left", this.addUnits(left));
7447 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7448 * @param {String} top The top CSS property value
7449 * @return {Roo.Element} this
7451 setTop : function(top){
7452 this.setStyle("top", this.addUnits(top));
7457 * Sets the element's CSS right style.
7458 * @param {String} right The right CSS property value
7459 * @return {Roo.Element} this
7461 setRight : function(right){
7462 this.setStyle("right", this.addUnits(right));
7467 * Sets the element's CSS bottom style.
7468 * @param {String} bottom The bottom CSS property value
7469 * @return {Roo.Element} this
7471 setBottom : function(bottom){
7472 this.setStyle("bottom", this.addUnits(bottom));
7477 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7478 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7479 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7480 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7481 * @return {Roo.Element} this
7483 setXY : function(pos, animate){
7485 D.setXY(this.dom, pos);
7487 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7493 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7494 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7495 * @param {Number} x X value for new position (coordinates are page-based)
7496 * @param {Number} y Y value for new position (coordinates are page-based)
7497 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7498 * @return {Roo.Element} this
7500 setLocation : function(x, y, animate){
7501 this.setXY([x, y], this.preanim(arguments, 2));
7506 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7507 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7508 * @param {Number} x X value for new position (coordinates are page-based)
7509 * @param {Number} y Y value for new position (coordinates are page-based)
7510 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7511 * @return {Roo.Element} this
7513 moveTo : function(x, y, animate){
7514 this.setXY([x, y], this.preanim(arguments, 2));
7519 * Returns the region of the given element.
7520 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7521 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7523 getRegion : function(){
7524 return D.getRegion(this.dom);
7528 * Returns the offset height of the element
7529 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7530 * @return {Number} The element's height
7532 getHeight : function(contentHeight){
7533 var h = this.dom.offsetHeight || 0;
7534 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7538 * Returns the offset width of the element
7539 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7540 * @return {Number} The element's width
7542 getWidth : function(contentWidth){
7543 var w = this.dom.offsetWidth || 0;
7544 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7548 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7549 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7550 * if a height has not been set using CSS.
7553 getComputedHeight : function(){
7554 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7556 h = parseInt(this.getStyle('height'), 10) || 0;
7557 if(!this.isBorderBox()){
7558 h += this.getFrameWidth('tb');
7565 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7566 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7567 * if a width has not been set using CSS.
7570 getComputedWidth : function(){
7571 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7573 w = parseInt(this.getStyle('width'), 10) || 0;
7574 if(!this.isBorderBox()){
7575 w += this.getFrameWidth('lr');
7582 * Returns the size of the element.
7583 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7584 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7586 getSize : function(contentSize){
7587 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7591 * Returns the width and height of the viewport.
7592 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7594 getViewSize : function(){
7595 var d = this.dom, doc = document, aw = 0, ah = 0;
7596 if(d == doc || d == doc.body){
7597 return {width : D.getViewWidth(), height: D.getViewHeight()};
7600 width : d.clientWidth,
7601 height: d.clientHeight
7607 * Returns the value of the "value" attribute
7608 * @param {Boolean} asNumber true to parse the value as a number
7609 * @return {String/Number}
7611 getValue : function(asNumber){
7612 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7616 adjustWidth : function(width){
7617 if(typeof width == "number"){
7618 if(this.autoBoxAdjust && !this.isBorderBox()){
7619 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7629 adjustHeight : function(height){
7630 if(typeof height == "number"){
7631 if(this.autoBoxAdjust && !this.isBorderBox()){
7632 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7642 * Set the width of the element
7643 * @param {Number} width The new width
7644 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7645 * @return {Roo.Element} this
7647 setWidth : function(width, animate){
7648 width = this.adjustWidth(width);
7650 this.dom.style.width = this.addUnits(width);
7652 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7658 * Set the height of the element
7659 * @param {Number} height The new height
7660 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7661 * @return {Roo.Element} this
7663 setHeight : function(height, animate){
7664 height = this.adjustHeight(height);
7666 this.dom.style.height = this.addUnits(height);
7668 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7674 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7675 * @param {Number} width The new width
7676 * @param {Number} height The new height
7677 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7678 * @return {Roo.Element} this
7680 setSize : function(width, height, animate){
7681 if(typeof width == "object"){ // in case of object from getSize()
7682 height = width.height; width = width.width;
7684 width = this.adjustWidth(width); height = this.adjustHeight(height);
7686 this.dom.style.width = this.addUnits(width);
7687 this.dom.style.height = this.addUnits(height);
7689 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7695 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7696 * @param {Number} x X value for new position (coordinates are page-based)
7697 * @param {Number} y Y value for new position (coordinates are page-based)
7698 * @param {Number} width The new width
7699 * @param {Number} height The new height
7700 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7701 * @return {Roo.Element} this
7703 setBounds : function(x, y, width, height, animate){
7705 this.setSize(width, height);
7706 this.setLocation(x, y);
7708 width = this.adjustWidth(width); height = this.adjustHeight(height);
7709 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7710 this.preanim(arguments, 4), 'motion');
7716 * 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.
7717 * @param {Roo.lib.Region} region The region to fill
7718 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7719 * @return {Roo.Element} this
7721 setRegion : function(region, animate){
7722 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7727 * Appends an event handler
7729 * @param {String} eventName The type of event to append
7730 * @param {Function} fn The method the event invokes
7731 * @param {Object} scope (optional) The scope (this object) of the fn
7732 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7734 addListener : function(eventName, fn, scope, options){
7735 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7739 * Removes an event handler from this element
7740 * @param {String} eventName the type of event to remove
7741 * @param {Function} fn the method the event invokes
7742 * @return {Roo.Element} this
7744 removeListener : function(eventName, fn){
7745 Roo.EventManager.removeListener(this.dom, eventName, fn);
7750 * Removes all previous added listeners from this element
7751 * @return {Roo.Element} this
7753 removeAllListeners : function(){
7754 E.purgeElement(this.dom);
7758 relayEvent : function(eventName, observable){
7759 this.on(eventName, function(e){
7760 observable.fireEvent(eventName, e);
7765 * Set the opacity of the element
7766 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7767 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7768 * @return {Roo.Element} this
7770 setOpacity : function(opacity, animate){
7772 var s = this.dom.style;
7775 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7776 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7778 s.opacity = opacity;
7781 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7787 * Gets the left X coordinate
7788 * @param {Boolean} local True to get the local css position instead of page coordinate
7791 getLeft : function(local){
7795 return parseInt(this.getStyle("left"), 10) || 0;
7800 * Gets the right X coordinate of the element (element X position + element width)
7801 * @param {Boolean} local True to get the local css position instead of page coordinate
7804 getRight : function(local){
7806 return this.getX() + this.getWidth();
7808 return (this.getLeft(true) + this.getWidth()) || 0;
7813 * Gets the top Y coordinate
7814 * @param {Boolean} local True to get the local css position instead of page coordinate
7817 getTop : function(local) {
7821 return parseInt(this.getStyle("top"), 10) || 0;
7826 * Gets the bottom Y coordinate of the element (element Y position + element height)
7827 * @param {Boolean} local True to get the local css position instead of page coordinate
7830 getBottom : function(local){
7832 return this.getY() + this.getHeight();
7834 return (this.getTop(true) + this.getHeight()) || 0;
7839 * Initializes positioning on this element. If a desired position is not passed, it will make the
7840 * the element positioned relative IF it is not already positioned.
7841 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7842 * @param {Number} zIndex (optional) The zIndex to apply
7843 * @param {Number} x (optional) Set the page X position
7844 * @param {Number} y (optional) Set the page Y position
7846 position : function(pos, zIndex, x, y){
7848 if(this.getStyle('position') == 'static'){
7849 this.setStyle('position', 'relative');
7852 this.setStyle("position", pos);
7855 this.setStyle("z-index", zIndex);
7857 if(x !== undefined && y !== undefined){
7859 }else if(x !== undefined){
7861 }else if(y !== undefined){
7867 * Clear positioning back to the default when the document was loaded
7868 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7869 * @return {Roo.Element} this
7871 clearPositioning : function(value){
7879 "position" : "static"
7885 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7886 * snapshot before performing an update and then restoring the element.
7889 getPositioning : function(){
7890 var l = this.getStyle("left");
7891 var t = this.getStyle("top");
7893 "position" : this.getStyle("position"),
7895 "right" : l ? "" : this.getStyle("right"),
7897 "bottom" : t ? "" : this.getStyle("bottom"),
7898 "z-index" : this.getStyle("z-index")
7903 * Gets the width of the border(s) for the specified side(s)
7904 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7905 * passing lr would get the border (l)eft width + the border (r)ight width.
7906 * @return {Number} The width of the sides passed added together
7908 getBorderWidth : function(side){
7909 return this.addStyles(side, El.borders);
7913 * Gets the width of the padding(s) for the specified side(s)
7914 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7915 * passing lr would get the padding (l)eft + the padding (r)ight.
7916 * @return {Number} The padding of the sides passed added together
7918 getPadding : function(side){
7919 return this.addStyles(side, El.paddings);
7923 * Set positioning with an object returned by getPositioning().
7924 * @param {Object} posCfg
7925 * @return {Roo.Element} this
7927 setPositioning : function(pc){
7928 this.applyStyles(pc);
7929 if(pc.right == "auto"){
7930 this.dom.style.right = "";
7932 if(pc.bottom == "auto"){
7933 this.dom.style.bottom = "";
7939 fixDisplay : function(){
7940 if(this.getStyle("display") == "none"){
7941 this.setStyle("visibility", "hidden");
7942 this.setStyle("display", this.originalDisplay); // first try reverting to default
7943 if(this.getStyle("display") == "none"){ // if that fails, default to block
7944 this.setStyle("display", "block");
7950 * Quick set left and top adding default units
7951 * @param {String} left The left CSS property value
7952 * @param {String} top The top CSS property value
7953 * @return {Roo.Element} this
7955 setLeftTop : function(left, top){
7956 this.dom.style.left = this.addUnits(left);
7957 this.dom.style.top = this.addUnits(top);
7962 * Move this element relative to its current position.
7963 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
7964 * @param {Number} distance How far to move the element in pixels
7965 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7966 * @return {Roo.Element} this
7968 move : function(direction, distance, animate){
7969 var xy = this.getXY();
7970 direction = direction.toLowerCase();
7974 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
7978 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
7983 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
7988 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
7995 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
7996 * @return {Roo.Element} this
7999 if(!this.isClipped){
8000 this.isClipped = true;
8001 this.originalClip = {
8002 "o": this.getStyle("overflow"),
8003 "x": this.getStyle("overflow-x"),
8004 "y": this.getStyle("overflow-y")
8006 this.setStyle("overflow", "hidden");
8007 this.setStyle("overflow-x", "hidden");
8008 this.setStyle("overflow-y", "hidden");
8014 * Return clipping (overflow) to original clipping before clip() was called
8015 * @return {Roo.Element} this
8017 unclip : function(){
8019 this.isClipped = false;
8020 var o = this.originalClip;
8021 if(o.o){this.setStyle("overflow", o.o);}
8022 if(o.x){this.setStyle("overflow-x", o.x);}
8023 if(o.y){this.setStyle("overflow-y", o.y);}
8030 * Gets the x,y coordinates specified by the anchor position on the element.
8031 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8032 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8033 * {width: (target width), height: (target height)} (defaults to the element's current size)
8034 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8035 * @return {Array} [x, y] An array containing the element's x and y coordinates
8037 getAnchorXY : function(anchor, local, s){
8038 //Passing a different size is useful for pre-calculating anchors,
8039 //especially for anchored animations that change the el size.
8041 var w, h, vp = false;
8044 if(d == document.body || d == document){
8046 w = D.getViewWidth(); h = D.getViewHeight();
8048 w = this.getWidth(); h = this.getHeight();
8051 w = s.width; h = s.height;
8053 var x = 0, y = 0, r = Math.round;
8054 switch((anchor || "tl").toLowerCase()){
8096 var sc = this.getScroll();
8097 return [x + sc.left, y + sc.top];
8099 //Add the element's offset xy
8100 var o = this.getXY();
8101 return [x+o[0], y+o[1]];
8105 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8106 * supported position values.
8107 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8108 * @param {String} position The position to align to.
8109 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8110 * @return {Array} [x, y]
8112 getAlignToXY : function(el, p, o){
8116 throw "Element.alignTo with an element that doesn't exist";
8118 var c = false; //constrain to viewport
8119 var p1 = "", p2 = "";
8126 }else if(p.indexOf("-") == -1){
8129 p = p.toLowerCase();
8130 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8132 throw "Element.alignTo with an invalid alignment " + p;
8134 p1 = m[1]; p2 = m[2]; c = !!m[3];
8136 //Subtract the aligned el's internal xy from the target's offset xy
8137 //plus custom offset to get the aligned el's new offset xy
8138 var a1 = this.getAnchorXY(p1, true);
8139 var a2 = el.getAnchorXY(p2, false);
8140 var x = a2[0] - a1[0] + o[0];
8141 var y = a2[1] - a1[1] + o[1];
8143 //constrain the aligned el to viewport if necessary
8144 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8145 // 5px of margin for ie
8146 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8148 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8149 //perpendicular to the vp border, allow the aligned el to slide on that border,
8150 //otherwise swap the aligned el to the opposite border of the target.
8151 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8152 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8153 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8154 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8157 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8158 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8160 if((x+w) > dw + scrollX){
8161 x = swapX ? r.left-w : dw+scrollX-w;
8164 x = swapX ? r.right : scrollX;
8166 if((y+h) > dh + scrollY){
8167 y = swapY ? r.top-h : dh+scrollY-h;
8170 y = swapY ? r.bottom : scrollY;
8177 getConstrainToXY : function(){
8178 var os = {top:0, left:0, bottom:0, right: 0};
8180 return function(el, local, offsets, proposedXY){
8182 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8184 var vw, vh, vx = 0, vy = 0;
8185 if(el.dom == document.body || el.dom == document){
8186 vw = Roo.lib.Dom.getViewWidth();
8187 vh = Roo.lib.Dom.getViewHeight();
8189 vw = el.dom.clientWidth;
8190 vh = el.dom.clientHeight;
8192 var vxy = el.getXY();
8198 var s = el.getScroll();
8200 vx += offsets.left + s.left;
8201 vy += offsets.top + s.top;
8203 vw -= offsets.right;
8204 vh -= offsets.bottom;
8209 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8210 var x = xy[0], y = xy[1];
8211 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8213 // only move it if it needs it
8216 // first validate right/bottom
8225 // then make sure top/left isn't negative
8234 return moved ? [x, y] : false;
8239 adjustForConstraints : function(xy, parent, offsets){
8240 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8244 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8245 * document it aligns it to the viewport.
8246 * The position parameter is optional, and can be specified in any one of the following formats:
8248 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8249 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8250 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8251 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8252 * <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
8253 * element's anchor point, and the second value is used as the target's anchor point.</li>
8255 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8256 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8257 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8258 * that specified in order to enforce the viewport constraints.
8259 * Following are all of the supported anchor positions:
8262 ----- -----------------------------
8263 tl The top left corner (default)
8264 t The center of the top edge
8265 tr The top right corner
8266 l The center of the left edge
8267 c In the center of the element
8268 r The center of the right edge
8269 bl The bottom left corner
8270 b The center of the bottom edge
8271 br The bottom right corner
8275 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8276 el.alignTo("other-el");
8278 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8279 el.alignTo("other-el", "tr?");
8281 // align the bottom right corner of el with the center left edge of other-el
8282 el.alignTo("other-el", "br-l?");
8284 // align the center of el with the bottom left corner of other-el and
8285 // adjust the x position by -6 pixels (and the y position by 0)
8286 el.alignTo("other-el", "c-bl", [-6, 0]);
8288 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8289 * @param {String} position The position to align to.
8290 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8291 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8292 * @return {Roo.Element} this
8294 alignTo : function(element, position, offsets, animate){
8295 var xy = this.getAlignToXY(element, position, offsets);
8296 this.setXY(xy, this.preanim(arguments, 3));
8301 * Anchors an element to another element and realigns it when the window is resized.
8302 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8303 * @param {String} position The position to align to.
8304 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8305 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8306 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8307 * is a number, it is used as the buffer delay (defaults to 50ms).
8308 * @param {Function} callback The function to call after the animation finishes
8309 * @return {Roo.Element} this
8311 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8312 var action = function(){
8313 this.alignTo(el, alignment, offsets, animate);
8314 Roo.callback(callback, this);
8316 Roo.EventManager.onWindowResize(action, this);
8317 var tm = typeof monitorScroll;
8318 if(tm != 'undefined'){
8319 Roo.EventManager.on(window, 'scroll', action, this,
8320 {buffer: tm == 'number' ? monitorScroll : 50});
8322 action.call(this); // align immediately
8326 * Clears any opacity settings from this element. Required in some cases for IE.
8327 * @return {Roo.Element} this
8329 clearOpacity : function(){
8330 if (window.ActiveXObject) {
8331 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8332 this.dom.style.filter = "";
8335 this.dom.style.opacity = "";
8336 this.dom.style["-moz-opacity"] = "";
8337 this.dom.style["-khtml-opacity"] = "";
8343 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8344 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8345 * @return {Roo.Element} this
8347 hide : function(animate){
8348 this.setVisible(false, this.preanim(arguments, 0));
8353 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8354 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8355 * @return {Roo.Element} this
8357 show : function(animate){
8358 this.setVisible(true, this.preanim(arguments, 0));
8363 * @private Test if size has a unit, otherwise appends the default
8365 addUnits : function(size){
8366 return Roo.Element.addUnits(size, this.defaultUnit);
8370 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8371 * @return {Roo.Element} this
8373 beginMeasure : function(){
8375 if(el.offsetWidth || el.offsetHeight){
8376 return this; // offsets work already
8379 var p = this.dom, b = document.body; // start with this element
8380 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8381 var pe = Roo.get(p);
8382 if(pe.getStyle('display') == 'none'){
8383 changed.push({el: p, visibility: pe.getStyle("visibility")});
8384 p.style.visibility = "hidden";
8385 p.style.display = "block";
8389 this._measureChanged = changed;
8395 * Restores displays to before beginMeasure was called
8396 * @return {Roo.Element} this
8398 endMeasure : function(){
8399 var changed = this._measureChanged;
8401 for(var i = 0, len = changed.length; i < len; i++) {
8403 r.el.style.visibility = r.visibility;
8404 r.el.style.display = "none";
8406 this._measureChanged = null;
8412 * Update the innerHTML of this element, optionally searching for and processing scripts
8413 * @param {String} html The new HTML
8414 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8415 * @param {Function} callback For async script loading you can be noticed when the update completes
8416 * @return {Roo.Element} this
8418 update : function(html, loadScripts, callback){
8419 if(typeof html == "undefined"){
8422 if(loadScripts !== true){
8423 this.dom.innerHTML = html;
8424 if(typeof callback == "function"){
8432 html += '<span id="' + id + '"></span>';
8434 E.onAvailable(id, function(){
8435 var hd = document.getElementsByTagName("head")[0];
8436 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8437 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8438 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8441 while(match = re.exec(html)){
8442 var attrs = match[1];
8443 var srcMatch = attrs ? attrs.match(srcRe) : false;
8444 if(srcMatch && srcMatch[2]){
8445 var s = document.createElement("script");
8446 s.src = srcMatch[2];
8447 var typeMatch = attrs.match(typeRe);
8448 if(typeMatch && typeMatch[2]){
8449 s.type = typeMatch[2];
8452 }else if(match[2] && match[2].length > 0){
8453 if(window.execScript) {
8454 window.execScript(match[2]);
8462 window.eval(match[2]);
8466 var el = document.getElementById(id);
8467 if(el){el.parentNode.removeChild(el);}
8468 if(typeof callback == "function"){
8472 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8477 * Direct access to the UpdateManager update() method (takes the same parameters).
8478 * @param {String/Function} url The url for this request or a function to call to get the url
8479 * @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}
8480 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8481 * @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.
8482 * @return {Roo.Element} this
8485 var um = this.getUpdateManager();
8486 um.update.apply(um, arguments);
8491 * Gets this element's UpdateManager
8492 * @return {Roo.UpdateManager} The UpdateManager
8494 getUpdateManager : function(){
8495 if(!this.updateManager){
8496 this.updateManager = new Roo.UpdateManager(this);
8498 return this.updateManager;
8502 * Disables text selection for this element (normalized across browsers)
8503 * @return {Roo.Element} this
8505 unselectable : function(){
8506 this.dom.unselectable = "on";
8507 this.swallowEvent("selectstart", true);
8508 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8509 this.addClass("x-unselectable");
8514 * Calculates the x, y to center this element on the screen
8515 * @return {Array} The x, y values [x, y]
8517 getCenterXY : function(){
8518 return this.getAlignToXY(document, 'c-c');
8522 * Centers the Element in either the viewport, or another Element.
8523 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8525 center : function(centerIn){
8526 this.alignTo(centerIn || document, 'c-c');
8531 * Tests various css rules/browsers to determine if this element uses a border box
8534 isBorderBox : function(){
8535 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8539 * Return a box {x, y, width, height} that can be used to set another elements
8540 * size/location to match this element.
8541 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8542 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8543 * @return {Object} box An object in the format {x, y, width, height}
8545 getBox : function(contentBox, local){
8550 var left = parseInt(this.getStyle("left"), 10) || 0;
8551 var top = parseInt(this.getStyle("top"), 10) || 0;
8554 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8556 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8558 var l = this.getBorderWidth("l")+this.getPadding("l");
8559 var r = this.getBorderWidth("r")+this.getPadding("r");
8560 var t = this.getBorderWidth("t")+this.getPadding("t");
8561 var b = this.getBorderWidth("b")+this.getPadding("b");
8562 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)};
8564 bx.right = bx.x + bx.width;
8565 bx.bottom = bx.y + bx.height;
8570 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8571 for more information about the sides.
8572 * @param {String} sides
8575 getFrameWidth : function(sides, onlyContentBox){
8576 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8580 * 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.
8581 * @param {Object} box The box to fill {x, y, width, height}
8582 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8583 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8584 * @return {Roo.Element} this
8586 setBox : function(box, adjust, animate){
8587 var w = box.width, h = box.height;
8588 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8589 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8590 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8592 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8597 * Forces the browser to repaint this element
8598 * @return {Roo.Element} this
8600 repaint : function(){
8602 this.addClass("x-repaint");
8603 setTimeout(function(){
8604 Roo.get(dom).removeClass("x-repaint");
8610 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8611 * then it returns the calculated width of the sides (see getPadding)
8612 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8613 * @return {Object/Number}
8615 getMargins : function(side){
8618 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8619 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8620 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8621 right: parseInt(this.getStyle("margin-right"), 10) || 0
8624 return this.addStyles(side, El.margins);
8629 addStyles : function(sides, styles){
8631 for(var i = 0, len = sides.length; i < len; i++){
8632 v = this.getStyle(styles[sides.charAt(i)]);
8634 w = parseInt(v, 10);
8642 * Creates a proxy element of this element
8643 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8644 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8645 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8646 * @return {Roo.Element} The new proxy element
8648 createProxy : function(config, renderTo, matchBox){
8650 renderTo = Roo.getDom(renderTo);
8652 renderTo = document.body;
8654 config = typeof config == "object" ?
8655 config : {tag : "div", cls: config};
8656 var proxy = Roo.DomHelper.append(renderTo, config, true);
8658 proxy.setBox(this.getBox());
8664 * Puts a mask over this element to disable user interaction. Requires core.css.
8665 * This method can only be applied to elements which accept child nodes.
8666 * @param {String} msg (optional) A message to display in the mask
8667 * @param {String} msgCls (optional) A css class to apply to the msg element
8668 * @return {Element} The mask element
8670 mask : function(msg, msgCls){
8671 if(this.getStyle("position") == "static"){
8672 this.setStyle("position", "relative");
8675 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8677 this.addClass("x-masked");
8678 this._mask.setDisplayed(true);
8679 if(typeof msg == 'string'){
8681 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8683 var mm = this._maskMsg;
8684 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8685 mm.dom.firstChild.innerHTML = msg;
8686 mm.setDisplayed(true);
8689 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8690 this._mask.setHeight(this.getHeight());
8696 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8697 * it is cached for reuse.
8699 unmask : function(removeEl){
8701 if(removeEl === true){
8702 this._mask.remove();
8705 this._maskMsg.remove();
8706 delete this._maskMsg;
8709 this._mask.setDisplayed(false);
8711 this._maskMsg.setDisplayed(false);
8715 this.removeClass("x-masked");
8719 * Returns true if this element is masked
8722 isMasked : function(){
8723 return this._mask && this._mask.isVisible();
8727 * Creates an iframe shim for this element to keep selects and other windowed objects from
8729 * @return {Roo.Element} The new shim element
8731 createShim : function(){
8732 var el = document.createElement('iframe');
8733 el.frameBorder = 'no';
8734 el.className = 'roo-shim';
8735 if(Roo.isIE && Roo.isSecure){
8736 el.src = Roo.SSL_SECURE_URL;
8738 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8739 shim.autoBoxAdjust = false;
8744 * Removes this element from the DOM and deletes it from the cache
8746 remove : function(){
8747 if(this.dom.parentNode){
8748 this.dom.parentNode.removeChild(this.dom);
8750 delete El.cache[this.dom.id];
8754 * Sets up event handlers to add and remove a css class when the mouse is over this element
8755 * @param {String} className
8756 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8757 * mouseout events for children elements
8758 * @return {Roo.Element} this
8760 addClassOnOver : function(className, preventFlicker){
8761 this.on("mouseover", function(){
8762 Roo.fly(this, '_internal').addClass(className);
8764 var removeFn = function(e){
8765 if(preventFlicker !== true || !e.within(this, true)){
8766 Roo.fly(this, '_internal').removeClass(className);
8769 this.on("mouseout", removeFn, this.dom);
8774 * Sets up event handlers to add and remove a css class when this element has the focus
8775 * @param {String} className
8776 * @return {Roo.Element} this
8778 addClassOnFocus : function(className){
8779 this.on("focus", function(){
8780 Roo.fly(this, '_internal').addClass(className);
8782 this.on("blur", function(){
8783 Roo.fly(this, '_internal').removeClass(className);
8788 * 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)
8789 * @param {String} className
8790 * @return {Roo.Element} this
8792 addClassOnClick : function(className){
8794 this.on("mousedown", function(){
8795 Roo.fly(dom, '_internal').addClass(className);
8796 var d = Roo.get(document);
8797 var fn = function(){
8798 Roo.fly(dom, '_internal').removeClass(className);
8799 d.removeListener("mouseup", fn);
8801 d.on("mouseup", fn);
8807 * Stops the specified event from bubbling and optionally prevents the default action
8808 * @param {String} eventName
8809 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8810 * @return {Roo.Element} this
8812 swallowEvent : function(eventName, preventDefault){
8813 var fn = function(e){
8814 e.stopPropagation();
8819 if(eventName instanceof Array){
8820 for(var i = 0, len = eventName.length; i < len; i++){
8821 this.on(eventName[i], fn);
8825 this.on(eventName, fn);
8832 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8835 * Sizes this element to its parent element's dimensions performing
8836 * neccessary box adjustments.
8837 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8838 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8839 * @return {Roo.Element} this
8841 fitToParent : function(monitorResize, targetParent) {
8842 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8843 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8844 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8847 var p = Roo.get(targetParent || this.dom.parentNode);
8848 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8849 if (monitorResize === true) {
8850 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8851 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8857 * Gets the next sibling, skipping text nodes
8858 * @return {HTMLElement} The next sibling or null
8860 getNextSibling : function(){
8861 var n = this.dom.nextSibling;
8862 while(n && n.nodeType != 1){
8869 * Gets the previous sibling, skipping text nodes
8870 * @return {HTMLElement} The previous sibling or null
8872 getPrevSibling : function(){
8873 var n = this.dom.previousSibling;
8874 while(n && n.nodeType != 1){
8875 n = n.previousSibling;
8882 * Appends the passed element(s) to this element
8883 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8884 * @return {Roo.Element} this
8886 appendChild: function(el){
8893 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8894 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8895 * automatically generated with the specified attributes.
8896 * @param {HTMLElement} insertBefore (optional) a child element of this element
8897 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8898 * @return {Roo.Element} The new child element
8900 createChild: function(config, insertBefore, returnDom){
8901 config = config || {tag:'div'};
8903 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8905 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8909 * Appends this element to the passed element
8910 * @param {String/HTMLElement/Element} el The new parent element
8911 * @return {Roo.Element} this
8913 appendTo: function(el){
8914 el = Roo.getDom(el);
8915 el.appendChild(this.dom);
8920 * Inserts this element before the passed element in the DOM
8921 * @param {String/HTMLElement/Element} el The element to insert before
8922 * @return {Roo.Element} this
8924 insertBefore: function(el){
8925 el = Roo.getDom(el);
8926 el.parentNode.insertBefore(this.dom, el);
8931 * Inserts this element after the passed element in the DOM
8932 * @param {String/HTMLElement/Element} el The element to insert after
8933 * @return {Roo.Element} this
8935 insertAfter: function(el){
8936 el = Roo.getDom(el);
8937 el.parentNode.insertBefore(this.dom, el.nextSibling);
8942 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
8943 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8944 * @return {Roo.Element} The new child
8946 insertFirst: function(el, returnDom){
8948 if(typeof el == 'object' && !el.nodeType){ // dh config
8949 return this.createChild(el, this.dom.firstChild, returnDom);
8951 el = Roo.getDom(el);
8952 this.dom.insertBefore(el, this.dom.firstChild);
8953 return !returnDom ? Roo.get(el) : el;
8958 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
8959 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8960 * @param {String} where (optional) 'before' or 'after' defaults to before
8961 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8962 * @return {Roo.Element} the inserted Element
8964 insertSibling: function(el, where, returnDom){
8965 where = where ? where.toLowerCase() : 'before';
8967 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
8969 if(typeof el == 'object' && !el.nodeType){ // dh config
8970 if(where == 'after' && !this.dom.nextSibling){
8971 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
8973 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
8977 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
8978 where == 'before' ? this.dom : this.dom.nextSibling);
8987 * Creates and wraps this element with another element
8988 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
8989 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8990 * @return {HTMLElement/Element} The newly created wrapper element
8992 wrap: function(config, returnDom){
8994 config = {tag: "div"};
8996 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
8997 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9002 * Replaces the passed element with this element
9003 * @param {String/HTMLElement/Element} el The element to replace
9004 * @return {Roo.Element} this
9006 replace: function(el){
9008 this.insertBefore(el);
9014 * Inserts an html fragment into this element
9015 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9016 * @param {String} html The HTML fragment
9017 * @param {Boolean} returnEl True to return an Roo.Element
9018 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9020 insertHtml : function(where, html, returnEl){
9021 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9022 return returnEl ? Roo.get(el) : el;
9026 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9027 * @param {Object} o The object with the attributes
9028 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9029 * @return {Roo.Element} this
9031 set : function(o, useSet){
9033 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9035 if(attr == "style" || typeof o[attr] == "function") continue;
9037 el.className = o["cls"];
9039 if(useSet) el.setAttribute(attr, o[attr]);
9040 else el[attr] = o[attr];
9044 Roo.DomHelper.applyStyles(el, o.style);
9050 * Convenience method for constructing a KeyMap
9051 * @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:
9052 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9053 * @param {Function} fn The function to call
9054 * @param {Object} scope (optional) The scope of the function
9055 * @return {Roo.KeyMap} The KeyMap created
9057 addKeyListener : function(key, fn, scope){
9059 if(typeof key != "object" || key instanceof Array){
9075 return new Roo.KeyMap(this, config);
9079 * Creates a KeyMap for this element
9080 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9081 * @return {Roo.KeyMap} The KeyMap created
9083 addKeyMap : function(config){
9084 return new Roo.KeyMap(this, config);
9088 * Returns true if this element is scrollable.
9091 isScrollable : function(){
9093 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9097 * 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().
9098 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9099 * @param {Number} value The new scroll value
9100 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9101 * @return {Element} this
9104 scrollTo : function(side, value, animate){
9105 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9107 this.dom[prop] = value;
9109 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9110 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9116 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9117 * within this element's scrollable range.
9118 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9119 * @param {Number} distance How far to scroll the element in pixels
9120 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9121 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9122 * was scrolled as far as it could go.
9124 scroll : function(direction, distance, animate){
9125 if(!this.isScrollable()){
9129 var l = el.scrollLeft, t = el.scrollTop;
9130 var w = el.scrollWidth, h = el.scrollHeight;
9131 var cw = el.clientWidth, ch = el.clientHeight;
9132 direction = direction.toLowerCase();
9133 var scrolled = false;
9134 var a = this.preanim(arguments, 2);
9139 var v = Math.min(l + distance, w-cw);
9140 this.scrollTo("left", v, a);
9147 var v = Math.max(l - distance, 0);
9148 this.scrollTo("left", v, a);
9156 var v = Math.max(t - distance, 0);
9157 this.scrollTo("top", v, a);
9165 var v = Math.min(t + distance, h-ch);
9166 this.scrollTo("top", v, a);
9175 * Translates the passed page coordinates into left/top css values for this element
9176 * @param {Number/Array} x The page x or an array containing [x, y]
9177 * @param {Number} y The page y
9178 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9180 translatePoints : function(x, y){
9181 if(typeof x == 'object' || x instanceof Array){
9184 var p = this.getStyle('position');
9185 var o = this.getXY();
9187 var l = parseInt(this.getStyle('left'), 10);
9188 var t = parseInt(this.getStyle('top'), 10);
9191 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9194 t = (p == "relative") ? 0 : this.dom.offsetTop;
9197 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9201 * Returns the current scroll position of the element.
9202 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9204 getScroll : function(){
9205 var d = this.dom, doc = document;
9206 if(d == doc || d == doc.body){
9207 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9208 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9209 return {left: l, top: t};
9211 return {left: d.scrollLeft, top: d.scrollTop};
9216 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9217 * are convert to standard 6 digit hex color.
9218 * @param {String} attr The css attribute
9219 * @param {String} defaultValue The default value to use when a valid color isn't found
9220 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9223 getColor : function(attr, defaultValue, prefix){
9224 var v = this.getStyle(attr);
9225 if(!v || v == "transparent" || v == "inherit") {
9226 return defaultValue;
9228 var color = typeof prefix == "undefined" ? "#" : prefix;
9229 if(v.substr(0, 4) == "rgb("){
9230 var rvs = v.slice(4, v.length -1).split(",");
9231 for(var i = 0; i < 3; i++){
9232 var h = parseInt(rvs[i]).toString(16);
9239 if(v.substr(0, 1) == "#"){
9241 for(var i = 1; i < 4; i++){
9242 var c = v.charAt(i);
9245 }else if(v.length == 7){
9246 color += v.substr(1);
9250 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9254 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9255 * gradient background, rounded corners and a 4-way shadow.
9256 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9257 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9258 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9259 * @return {Roo.Element} this
9261 boxWrap : function(cls){
9262 cls = cls || 'x-box';
9263 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9264 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9269 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9270 * @param {String} namespace The namespace in which to look for the attribute
9271 * @param {String} name The attribute name
9272 * @return {String} The attribute value
9274 getAttributeNS : Roo.isIE ? function(ns, name){
9276 var type = typeof d[ns+":"+name];
9277 if(type != 'undefined' && type != 'unknown'){
9278 return d[ns+":"+name];
9281 } : function(ns, name){
9283 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9287 var ep = El.prototype;
9290 * Appends an event handler (Shorthand for addListener)
9291 * @param {String} eventName The type of event to append
9292 * @param {Function} fn The method the event invokes
9293 * @param {Object} scope (optional) The scope (this object) of the fn
9294 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9297 ep.on = ep.addListener;
9299 ep.mon = ep.addListener;
9302 * Removes an event handler from this element (shorthand for removeListener)
9303 * @param {String} eventName the type of event to remove
9304 * @param {Function} fn the method the event invokes
9305 * @return {Roo.Element} this
9308 ep.un = ep.removeListener;
9311 * true to automatically adjust width and height settings for box-model issues (default to true)
9313 ep.autoBoxAdjust = true;
9316 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9319 El.addUnits = function(v, defaultUnit){
9320 if(v === "" || v == "auto"){
9323 if(v === undefined){
9326 if(typeof v == "number" || !El.unitPattern.test(v)){
9327 return v + (defaultUnit || 'px');
9332 // special markup used throughout Roo when box wrapping elements
9333 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>';
9335 * Visibility mode constant - Use visibility to hide element
9341 * Visibility mode constant - Use display to hide element
9347 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9348 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9349 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9361 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9362 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9363 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9364 * @return {Element} The Element object
9367 El.get = function(el){
9369 if(!el){ return null; }
9370 if(typeof el == "string"){ // element id
9371 if(!(elm = document.getElementById(el))){
9374 if(ex = El.cache[el]){
9377 ex = El.cache[el] = new El(elm);
9380 }else if(el.tagName){ // dom element
9384 if(ex = El.cache[id]){
9387 ex = El.cache[id] = new El(el);
9390 }else if(el instanceof El){
9392 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9393 // catch case where it hasn't been appended
9394 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9397 }else if(el.isComposite){
9399 }else if(el instanceof Array){
9400 return El.select(el);
9401 }else if(el == document){
9402 // create a bogus element object representing the document object
9404 var f = function(){};
9405 f.prototype = El.prototype;
9407 docEl.dom = document;
9415 El.uncache = function(el){
9416 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9418 delete El.cache[a[i].id || a[i]];
9424 // Garbage collection - uncache elements/purge listeners on orphaned elements
9425 // so we don't hold a reference and cause the browser to retain them
9426 El.garbageCollect = function(){
9427 if(!Roo.enableGarbageCollector){
9428 clearInterval(El.collectorThread);
9431 for(var eid in El.cache){
9432 var el = El.cache[eid], d = el.dom;
9433 // -------------------------------------------------------
9434 // Determining what is garbage:
9435 // -------------------------------------------------------
9437 // dom node is null, definitely garbage
9438 // -------------------------------------------------------
9440 // no parentNode == direct orphan, definitely garbage
9441 // -------------------------------------------------------
9442 // !d.offsetParent && !document.getElementById(eid)
9443 // display none elements have no offsetParent so we will
9444 // also try to look it up by it's id. However, check
9445 // offsetParent first so we don't do unneeded lookups.
9446 // This enables collection of elements that are not orphans
9447 // directly, but somewhere up the line they have an orphan
9449 // -------------------------------------------------------
9450 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9451 delete El.cache[eid];
9452 if(d && Roo.enableListenerCollection){
9458 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9462 El.Flyweight = function(dom){
9465 El.Flyweight.prototype = El.prototype;
9467 El._flyweights = {};
9469 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9470 * the dom node can be overwritten by other code.
9471 * @param {String/HTMLElement} el The dom node or id
9472 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9473 * prevent conflicts (e.g. internally Roo uses "_internal")
9475 * @return {Element} The shared Element object
9477 El.fly = function(el, named){
9478 named = named || '_global';
9479 el = Roo.getDom(el);
9483 if(!El._flyweights[named]){
9484 El._flyweights[named] = new El.Flyweight();
9486 El._flyweights[named].dom = el;
9487 return El._flyweights[named];
9491 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9492 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9493 * Shorthand of {@link Roo.Element#get}
9494 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9495 * @return {Element} The Element object
9501 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9502 * the dom node can be overwritten by other code.
9503 * Shorthand of {@link Roo.Element#fly}
9504 * @param {String/HTMLElement} el The dom node or id
9505 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9506 * prevent conflicts (e.g. internally Roo uses "_internal")
9508 * @return {Element} The shared Element object
9514 // speedy lookup for elements never to box adjust
9515 var noBoxAdjust = Roo.isStrict ? {
9518 input:1, select:1, textarea:1
9520 if(Roo.isIE || Roo.isGecko){
9521 noBoxAdjust['button'] = 1;
9525 Roo.EventManager.on(window, 'unload', function(){
9527 delete El._flyweights;
9535 Roo.Element.selectorFunction = Roo.DomQuery.select;
9538 Roo.Element.select = function(selector, unique, root){
9540 if(typeof selector == "string"){
9541 els = Roo.Element.selectorFunction(selector, root);
9542 }else if(selector.length !== undefined){
9545 throw "Invalid selector";
9547 if(unique === true){
9548 return new Roo.CompositeElement(els);
9550 return new Roo.CompositeElementLite(els);
9554 * Selects elements based on the passed CSS selector to enable working on them as 1.
9555 * @param {String/Array} selector The CSS selector or an array of elements
9556 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9557 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9558 * @return {CompositeElementLite/CompositeElement}
9562 Roo.select = Roo.Element.select;