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 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);
1106 Date.createParser = function(format) {
1107 var funcName = "parse" + Date.parseFunctions.count++;
1108 var regexNum = Date.parseRegexes.length;
1109 var currentGroup = 1;
1110 Date.parseFunctions[format] = funcName;
1112 var code = "Date." + funcName + " = function(input){\n"
1113 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1114 + "var d = new Date();\n"
1115 + "y = d.getFullYear();\n"
1116 + "m = d.getMonth();\n"
1117 + "d = d.getDate();\n"
1118 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1119 + "if (results && results.length > 0) {";
1122 var special = false;
1124 for (var i = 0; i < format.length; ++i) {
1125 ch = format.charAt(i);
1126 if (!special && ch == "\\") {
1131 regex += String.escape(ch);
1134 var obj = Date.formatCodeToRegex(ch, currentGroup);
1135 currentGroup += obj.g;
1137 if (obj.g && obj.c) {
1143 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1144 + "{v = new Date(y, m, d, h, i, s);}\n"
1145 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1146 + "{v = new Date(y, m, d, h, i);}\n"
1147 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1148 + "{v = new Date(y, m, d, h);}\n"
1149 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1150 + "{v = new Date(y, m, d);}\n"
1151 + "else if (y >= 0 && m >= 0)\n"
1152 + "{v = new Date(y, m);}\n"
1153 + "else if (y >= 0)\n"
1154 + "{v = new Date(y);}\n"
1155 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1156 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1157 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1160 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1161 /** eval:var:zzzzzzzzzzzzz */
1166 Date.formatCodeToRegex = function(character, currentGroup) {
1167 switch (character) {
1171 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1174 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1175 s:"(\\d{1,2})"}; // day of month without leading zeroes
1178 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1179 s:"(\\d{2})"}; // day of month with leading zeroes
1183 s:"(?:" + Date.dayNames.join("|") + ")"};
1187 s:"(?:st|nd|rd|th)"};
1202 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1203 s:"(" + Date.monthNames.join("|") + ")"};
1206 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1207 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1210 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1211 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1214 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1215 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1226 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1230 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1231 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1235 c:"if (results[" + currentGroup + "] == 'am') {\n"
1236 + "if (h == 12) { h = 0; }\n"
1237 + "} else { if (h < 12) { h += 12; }}",
1241 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1242 + "if (h == 12) { h = 0; }\n"
1243 + "} else { if (h < 12) { h += 12; }}",
1248 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1249 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1253 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1254 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1257 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1261 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1266 "o = results[", currentGroup, "];\n",
1267 "var sn = o.substring(0,1);\n", // get + / - sign
1268 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1269 "var mn = o.substring(3,5) % 60;\n", // get minutes
1270 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1271 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1277 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1280 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1281 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1282 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1286 s:String.escape(character)};
1291 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1292 * @return {String} The abbreviated timezone name (e.g. 'CST')
1294 Date.prototype.getTimezone = function() {
1295 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1299 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1300 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1302 Date.prototype.getGMTOffset = function() {
1303 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1304 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1305 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1309 * Get the numeric day number of the year, adjusted for leap year.
1310 * @return {Number} 0 through 364 (365 in leap years)
1312 Date.prototype.getDayOfYear = function() {
1314 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1315 for (var i = 0; i < this.getMonth(); ++i) {
1316 num += Date.daysInMonth[i];
1318 return num + this.getDate() - 1;
1322 * Get the string representation of the numeric week number of the year
1323 * (equivalent to the format specifier 'W').
1324 * @return {String} '00' through '52'
1326 Date.prototype.getWeekOfYear = function() {
1327 // Skip to Thursday of this week
1328 var now = this.getDayOfYear() + (4 - this.getDay());
1329 // Find the first Thursday of the year
1330 var jan1 = new Date(this.getFullYear(), 0, 1);
1331 var then = (7 - jan1.getDay() + 4);
1332 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1336 * Whether or not the current date is in a leap year.
1337 * @return {Boolean} True if the current date is in a leap year, else false
1339 Date.prototype.isLeapYear = function() {
1340 var year = this.getFullYear();
1341 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1345 * Get the first day of the current month, adjusted for leap year. The returned value
1346 * is the numeric day index within the week (0-6) which can be used in conjunction with
1347 * the {@link #monthNames} array to retrieve the textual day name.
1350 var dt = new Date('1/10/2007');
1351 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1353 * @return {Number} The day number (0-6)
1355 Date.prototype.getFirstDayOfMonth = function() {
1356 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1357 return (day < 0) ? (day + 7) : day;
1361 * Get the last day of the current month, adjusted for leap year. The returned value
1362 * is the numeric day index within the week (0-6) which can be used in conjunction with
1363 * the {@link #monthNames} array to retrieve the textual day name.
1366 var dt = new Date('1/10/2007');
1367 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1369 * @return {Number} The day number (0-6)
1371 Date.prototype.getLastDayOfMonth = function() {
1372 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1373 return (day < 0) ? (day + 7) : day;
1378 * Get the first date of this date's month
1381 Date.prototype.getFirstDateOfMonth = function() {
1382 return new Date(this.getFullYear(), this.getMonth(), 1);
1386 * Get the last date of this date's month
1389 Date.prototype.getLastDateOfMonth = function() {
1390 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1393 * Get the number of days in the current month, adjusted for leap year.
1394 * @return {Number} The number of days in the month
1396 Date.prototype.getDaysInMonth = function() {
1397 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1398 return Date.daysInMonth[this.getMonth()];
1402 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1403 * @return {String} 'st, 'nd', 'rd' or 'th'
1405 Date.prototype.getSuffix = function() {
1406 switch (this.getDate()) {
1423 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1426 * An array of textual month names.
1427 * Override these values for international dates, for example...
1428 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1447 * An array of textual day names.
1448 * Override these values for international dates, for example...
1449 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1465 Date.monthNumbers = {
1480 * Creates and returns a new Date instance with the exact same date value as the called instance.
1481 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1482 * variable will also be changed. When the intention is to create a new variable that will not
1483 * modify the original instance, you should create a clone.
1485 * Example of correctly cloning a date:
1488 var orig = new Date('10/1/2006');
1491 document.write(orig); //returns 'Thu Oct 05 2006'!
1494 var orig = new Date('10/1/2006');
1495 var copy = orig.clone();
1497 document.write(orig); //returns 'Thu Oct 01 2006'
1499 * @return {Date} The new Date instance
1501 Date.prototype.clone = function() {
1502 return new Date(this.getTime());
1506 * Clears any time information from this date
1507 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1508 @return {Date} this or the clone
1510 Date.prototype.clearTime = function(clone){
1512 return this.clone().clearTime();
1517 this.setMilliseconds(0);
1522 // safari setMonth is broken
1524 Date.brokenSetMonth = Date.prototype.setMonth;
1525 Date.prototype.setMonth = function(num){
1527 var n = Math.ceil(-num);
1528 var back_year = Math.ceil(n/12);
1529 var month = (n % 12) ? 12 - n % 12 : 0 ;
1530 this.setFullYear(this.getFullYear() - back_year);
1531 return Date.brokenSetMonth.call(this, month);
1533 return Date.brokenSetMonth.apply(this, arguments);
1538 /** Date interval constant
1542 /** Date interval constant
1546 /** Date interval constant
1550 /** Date interval constant
1554 /** Date interval constant
1558 /** Date interval constant
1562 /** Date interval constant
1568 * Provides a convenient method of performing basic date arithmetic. This method
1569 * does not modify the Date instance being called - it creates and returns
1570 * a new Date instance containing the resulting date value.
1575 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1576 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1578 //Negative values will subtract correctly:
1579 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1580 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1582 //You can even chain several calls together in one line!
1583 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1584 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1587 * @param {String} interval A valid date interval enum value
1588 * @param {Number} value The amount to add to the current date
1589 * @return {Date} The new Date instance
1591 Date.prototype.add = function(interval, value){
1592 var d = this.clone();
1593 if (!interval || value === 0) return d;
1594 switch(interval.toLowerCase()){
1596 d.setMilliseconds(this.getMilliseconds() + value);
1599 d.setSeconds(this.getSeconds() + value);
1602 d.setMinutes(this.getMinutes() + value);
1605 d.setHours(this.getHours() + value);
1608 d.setDate(this.getDate() + value);
1611 var day = this.getDate();
1613 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1616 d.setMonth(this.getMonth() + value);
1619 d.setFullYear(this.getFullYear() + value);
1625 * Ext JS Library 1.1.1
1626 * Copyright(c) 2006-2007, Ext JS, LLC.
1628 * Originally Released Under LGPL - original licence link has changed is not relivant.
1631 * <script type="text/javascript">
1635 getViewWidth : function(full) {
1636 return full ? this.getDocumentWidth() : this.getViewportWidth();
1639 getViewHeight : function(full) {
1640 return full ? this.getDocumentHeight() : this.getViewportHeight();
1643 getDocumentHeight: function() {
1644 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1645 return Math.max(scrollHeight, this.getViewportHeight());
1648 getDocumentWidth: function() {
1649 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1650 return Math.max(scrollWidth, this.getViewportWidth());
1653 getViewportHeight: function() {
1654 var height = self.innerHeight;
1655 var mode = document.compatMode;
1657 if ((mode || Roo.isIE) && !Roo.isOpera) {
1658 height = (mode == "CSS1Compat") ?
1659 document.documentElement.clientHeight :
1660 document.body.clientHeight;
1666 getViewportWidth: function() {
1667 var width = self.innerWidth;
1668 var mode = document.compatMode;
1670 if (mode || Roo.isIE) {
1671 width = (mode == "CSS1Compat") ?
1672 document.documentElement.clientWidth :
1673 document.body.clientWidth;
1678 isAncestor : function(p, c) {
1685 if (p.contains && !Roo.isSafari) {
1686 return p.contains(c);
1687 } else if (p.compareDocumentPosition) {
1688 return !!(p.compareDocumentPosition(c) & 16);
1690 var parent = c.parentNode;
1695 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1698 parent = parent.parentNode;
1704 getRegion : function(el) {
1705 return Roo.lib.Region.getRegion(el);
1708 getY : function(el) {
1709 return this.getXY(el)[1];
1712 getX : function(el) {
1713 return this.getXY(el)[0];
1716 getXY : function(el) {
1717 var p, pe, b, scroll, bd = document.body;
1718 el = Roo.getDom(el);
1719 var fly = Roo.lib.AnimBase.fly;
1720 if (el.getBoundingClientRect) {
1721 b = el.getBoundingClientRect();
1722 scroll = fly(document).getScroll();
1723 return [b.left + scroll.left, b.top + scroll.top];
1729 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1736 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1743 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1744 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1751 if (p != el && pe.getStyle('overflow') != 'visible') {
1759 if (Roo.isSafari && hasAbsolute) {
1764 if (Roo.isGecko && !hasAbsolute) {
1766 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1767 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1771 while (p && p != bd) {
1772 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1784 setXY : function(el, xy) {
1785 el = Roo.fly(el, '_setXY');
1787 var pts = el.translatePoints(xy);
1788 if (xy[0] !== false) {
1789 el.dom.style.left = pts.left + "px";
1791 if (xy[1] !== false) {
1792 el.dom.style.top = pts.top + "px";
1796 setX : function(el, x) {
1797 this.setXY(el, [x, false]);
1800 setY : function(el, y) {
1801 this.setXY(el, [false, y]);
1805 * Portions of this file are based on pieces of Yahoo User Interface Library
1806 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1807 * YUI licensed under the BSD License:
1808 * http://developer.yahoo.net/yui/license.txt
1809 * <script type="text/javascript">
1813 Roo.lib.Event = function() {
1814 var loadComplete = false;
1816 var unloadListeners = [];
1818 var onAvailStack = [];
1820 var lastError = null;
1833 startInterval: function() {
1834 if (!this._interval) {
1836 var callback = function() {
1837 self._tryPreloadAttach();
1839 this._interval = setInterval(callback, this.POLL_INTERVAL);
1844 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1845 onAvailStack.push({ id: p_id,
1848 override: p_override,
1849 checkReady: false });
1851 retryCount = this.POLL_RETRYS;
1852 this.startInterval();
1856 addListener: function(el, eventName, fn) {
1857 el = Roo.getDom(el);
1862 if ("unload" == eventName) {
1863 unloadListeners[unloadListeners.length] =
1864 [el, eventName, fn];
1868 var wrappedFn = function(e) {
1869 return fn(Roo.lib.Event.getEvent(e));
1872 var li = [el, eventName, fn, wrappedFn];
1874 var index = listeners.length;
1875 listeners[index] = li;
1877 this.doAdd(el, eventName, wrappedFn, false);
1883 removeListener: function(el, eventName, fn) {
1886 el = Roo.getDom(el);
1889 return this.purgeElement(el, false, eventName);
1893 if ("unload" == eventName) {
1895 for (i = 0,len = unloadListeners.length; i < len; i++) {
1896 var li = unloadListeners[i];
1899 li[1] == eventName &&
1901 unloadListeners.splice(i, 1);
1909 var cacheItem = null;
1912 var index = arguments[3];
1914 if ("undefined" == typeof index) {
1915 index = this._getCacheIndex(el, eventName, fn);
1919 cacheItem = listeners[index];
1922 if (!el || !cacheItem) {
1926 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1928 delete listeners[index][this.WFN];
1929 delete listeners[index][this.FN];
1930 listeners.splice(index, 1);
1937 getTarget: function(ev, resolveTextNode) {
1938 ev = ev.browserEvent || ev;
1939 var t = ev.target || ev.srcElement;
1940 return this.resolveTextNode(t);
1944 resolveTextNode: function(node) {
1945 if (Roo.isSafari && node && 3 == node.nodeType) {
1946 return node.parentNode;
1953 getPageX: function(ev) {
1954 ev = ev.browserEvent || ev;
1956 if (!x && 0 !== x) {
1957 x = ev.clientX || 0;
1960 x += this.getScroll()[1];
1968 getPageY: function(ev) {
1969 ev = ev.browserEvent || ev;
1971 if (!y && 0 !== y) {
1972 y = ev.clientY || 0;
1975 y += this.getScroll()[0];
1984 getXY: function(ev) {
1985 ev = ev.browserEvent || ev;
1986 return [this.getPageX(ev), this.getPageY(ev)];
1990 getRelatedTarget: function(ev) {
1991 ev = ev.browserEvent || ev;
1992 var t = ev.relatedTarget;
1994 if (ev.type == "mouseout") {
1996 } else if (ev.type == "mouseover") {
2001 return this.resolveTextNode(t);
2005 getTime: function(ev) {
2006 ev = ev.browserEvent || ev;
2008 var t = new Date().getTime();
2012 this.lastError = ex;
2021 stopEvent: function(ev) {
2022 this.stopPropagation(ev);
2023 this.preventDefault(ev);
2027 stopPropagation: function(ev) {
2028 ev = ev.browserEvent || ev;
2029 if (ev.stopPropagation) {
2030 ev.stopPropagation();
2032 ev.cancelBubble = true;
2037 preventDefault: function(ev) {
2038 ev = ev.browserEvent || ev;
2039 if(ev.preventDefault) {
2040 ev.preventDefault();
2042 ev.returnValue = false;
2047 getEvent: function(e) {
2048 var ev = e || window.event;
2050 var c = this.getEvent.caller;
2052 ev = c.arguments[0];
2053 if (ev && Event == ev.constructor) {
2063 getCharCode: function(ev) {
2064 ev = ev.browserEvent || ev;
2065 return ev.charCode || ev.keyCode || 0;
2069 _getCacheIndex: function(el, eventName, fn) {
2070 for (var i = 0,len = listeners.length; i < len; ++i) {
2071 var li = listeners[i];
2073 li[this.FN] == fn &&
2074 li[this.EL] == el &&
2075 li[this.TYPE] == eventName) {
2087 getEl: function(id) {
2088 return document.getElementById(id);
2092 clearCache: function() {
2096 _load: function(e) {
2097 loadComplete = true;
2098 var EU = Roo.lib.Event;
2102 EU.doRemove(window, "load", EU._load);
2107 _tryPreloadAttach: function() {
2116 var tryAgain = !loadComplete;
2118 tryAgain = (retryCount > 0);
2123 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2124 var item = onAvailStack[i];
2126 var el = this.getEl(item.id);
2129 if (!item.checkReady ||
2132 (document && document.body)) {
2135 if (item.override) {
2136 if (item.override === true) {
2139 scope = item.override;
2142 item.fn.call(scope, item.obj);
2143 onAvailStack[i] = null;
2146 notAvail.push(item);
2151 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2155 this.startInterval();
2157 clearInterval(this._interval);
2158 this._interval = null;
2161 this.locked = false;
2168 purgeElement: function(el, recurse, eventName) {
2169 var elListeners = this.getListeners(el, eventName);
2171 for (var i = 0,len = elListeners.length; i < len; ++i) {
2172 var l = elListeners[i];
2173 this.removeListener(el, l.type, l.fn);
2177 if (recurse && el && el.childNodes) {
2178 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2179 this.purgeElement(el.childNodes[i], recurse, eventName);
2185 getListeners: function(el, eventName) {
2186 var results = [], searchLists;
2188 searchLists = [listeners, unloadListeners];
2189 } else if (eventName == "unload") {
2190 searchLists = [unloadListeners];
2192 searchLists = [listeners];
2195 for (var j = 0; j < searchLists.length; ++j) {
2196 var searchList = searchLists[j];
2197 if (searchList && searchList.length > 0) {
2198 for (var i = 0,len = searchList.length; i < len; ++i) {
2199 var l = searchList[i];
2200 if (l && l[this.EL] === el &&
2201 (!eventName || eventName === l[this.TYPE])) {
2206 adjust: l[this.ADJ_SCOPE],
2214 return (results.length) ? results : null;
2218 _unload: function(e) {
2220 var EU = Roo.lib.Event, i, j, l, len, index;
2222 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2223 l = unloadListeners[i];
2226 if (l[EU.ADJ_SCOPE]) {
2227 if (l[EU.ADJ_SCOPE] === true) {
2230 scope = l[EU.ADJ_SCOPE];
2233 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2234 unloadListeners[i] = null;
2240 unloadListeners = null;
2242 if (listeners && listeners.length > 0) {
2243 j = listeners.length;
2246 l = listeners[index];
2248 EU.removeListener(l[EU.EL], l[EU.TYPE],
2258 EU.doRemove(window, "unload", EU._unload);
2263 getScroll: function() {
2264 var dd = document.documentElement, db = document.body;
2265 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2266 return [dd.scrollTop, dd.scrollLeft];
2268 return [db.scrollTop, db.scrollLeft];
2275 doAdd: function () {
2276 if (window.addEventListener) {
2277 return function(el, eventName, fn, capture) {
2278 el.addEventListener(eventName, fn, (capture));
2280 } else if (window.attachEvent) {
2281 return function(el, eventName, fn, capture) {
2282 el.attachEvent("on" + eventName, fn);
2291 doRemove: function() {
2292 if (window.removeEventListener) {
2293 return function (el, eventName, fn, capture) {
2294 el.removeEventListener(eventName, fn, (capture));
2296 } else if (window.detachEvent) {
2297 return function (el, eventName, fn) {
2298 el.detachEvent("on" + eventName, fn);
2310 var E = Roo.lib.Event;
2311 E.on = E.addListener;
2312 E.un = E.removeListener;
2314 if (document && document.body) {
2317 E.doAdd(window, "load", E._load);
2319 E.doAdd(window, "unload", E._unload);
2320 E._tryPreloadAttach();
2324 * Portions of this file are based on pieces of Yahoo User Interface Library
2325 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2326 * YUI licensed under the BSD License:
2327 * http://developer.yahoo.net/yui/license.txt
2328 * <script type="text/javascript">
2335 request : function(method, uri, cb, data, options) {
2337 var hs = options.headers;
2340 if(hs.hasOwnProperty(h)){
2341 this.initHeader(h, hs[h], false);
2345 if(options.xmlData){
2346 this.initHeader('Content-Type', 'text/xml', false);
2348 data = options.xmlData;
2352 return this.asyncRequest(method, uri, cb, data);
2355 serializeForm : function(form) {
2356 if(typeof form == 'string') {
2357 form = (document.getElementById(form) || document.forms[form]);
2360 var el, name, val, disabled, data = '', hasSubmit = false;
2361 for (var i = 0; i < form.elements.length; i++) {
2362 el = form.elements[i];
2363 disabled = form.elements[i].disabled;
2364 name = form.elements[i].name;
2365 val = form.elements[i].value;
2367 if (!disabled && name){
2371 case 'select-multiple':
2372 for (var j = 0; j < el.options.length; j++) {
2373 if (el.options[j].selected) {
2375 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2378 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2386 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2399 if(hasSubmit == false) {
2400 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2405 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2410 data = data.substr(0, data.length - 1);
2418 useDefaultHeader:true,
2420 defaultPostHeader:'application/x-www-form-urlencoded',
2422 useDefaultXhrHeader:true,
2424 defaultXhrHeader:'XMLHttpRequest',
2426 hasDefaultHeaders:true,
2438 setProgId:function(id)
2440 this.activeX.unshift(id);
2443 setDefaultPostHeader:function(b)
2445 this.useDefaultHeader = b;
2448 setDefaultXhrHeader:function(b)
2450 this.useDefaultXhrHeader = b;
2453 setPollingInterval:function(i)
2455 if (typeof i == 'number' && isFinite(i)) {
2456 this.pollInterval = i;
2460 createXhrObject:function(transactionId)
2466 http = new XMLHttpRequest();
2468 obj = { conn:http, tId:transactionId };
2472 for (var i = 0; i < this.activeX.length; ++i) {
2476 http = new ActiveXObject(this.activeX[i]);
2478 obj = { conn:http, tId:transactionId };
2491 getConnectionObject:function()
2494 var tId = this.transactionId;
2498 o = this.createXhrObject(tId);
2500 this.transactionId++;
2511 asyncRequest:function(method, uri, callback, postData)
2513 var o = this.getConnectionObject();
2519 o.conn.open(method, uri, true);
2521 if (this.useDefaultXhrHeader) {
2522 if (!this.defaultHeaders['X-Requested-With']) {
2523 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2527 if(postData && this.useDefaultHeader){
2528 this.initHeader('Content-Type', this.defaultPostHeader);
2531 if (this.hasDefaultHeaders || this.hasHeaders) {
2535 this.handleReadyState(o, callback);
2536 o.conn.send(postData || null);
2542 handleReadyState:function(o, callback)
2546 if (callback && callback.timeout) {
2547 this.timeout[o.tId] = window.setTimeout(function() {
2548 oConn.abort(o, callback, true);
2549 }, callback.timeout);
2552 this.poll[o.tId] = window.setInterval(
2554 if (o.conn && o.conn.readyState == 4) {
2555 window.clearInterval(oConn.poll[o.tId]);
2556 delete oConn.poll[o.tId];
2558 if(callback && callback.timeout) {
2559 window.clearTimeout(oConn.timeout[o.tId]);
2560 delete oConn.timeout[o.tId];
2563 oConn.handleTransactionResponse(o, callback);
2566 , this.pollInterval);
2569 handleTransactionResponse:function(o, callback, isAbort)
2573 this.releaseObject(o);
2577 var httpStatus, responseObject;
2581 if (o.conn.status !== undefined && o.conn.status != 0) {
2582 httpStatus = o.conn.status;
2594 if (httpStatus >= 200 && httpStatus < 300) {
2595 responseObject = this.createResponseObject(o, callback.argument);
2596 if (callback.success) {
2597 if (!callback.scope) {
2598 callback.success(responseObject);
2603 callback.success.apply(callback.scope, [responseObject]);
2608 switch (httpStatus) {
2616 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2617 if (callback.failure) {
2618 if (!callback.scope) {
2619 callback.failure(responseObject);
2622 callback.failure.apply(callback.scope, [responseObject]);
2627 responseObject = this.createResponseObject(o, callback.argument);
2628 if (callback.failure) {
2629 if (!callback.scope) {
2630 callback.failure(responseObject);
2633 callback.failure.apply(callback.scope, [responseObject]);
2639 this.releaseObject(o);
2640 responseObject = null;
2643 createResponseObject:function(o, callbackArg)
2650 var headerStr = o.conn.getAllResponseHeaders();
2651 var header = headerStr.split('\n');
2652 for (var i = 0; i < header.length; i++) {
2653 var delimitPos = header[i].indexOf(':');
2654 if (delimitPos != -1) {
2655 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2663 obj.status = o.conn.status;
2664 obj.statusText = o.conn.statusText;
2665 obj.getResponseHeader = headerObj;
2666 obj.getAllResponseHeaders = headerStr;
2667 obj.responseText = o.conn.responseText;
2668 obj.responseXML = o.conn.responseXML;
2670 if (typeof callbackArg !== undefined) {
2671 obj.argument = callbackArg;
2677 createExceptionObject:function(tId, callbackArg, isAbort)
2680 var COMM_ERROR = 'communication failure';
2681 var ABORT_CODE = -1;
2682 var ABORT_ERROR = 'transaction aborted';
2688 obj.status = ABORT_CODE;
2689 obj.statusText = ABORT_ERROR;
2692 obj.status = COMM_CODE;
2693 obj.statusText = COMM_ERROR;
2697 obj.argument = callbackArg;
2703 initHeader:function(label, value, isDefault)
2705 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2707 if (headerObj[label] === undefined) {
2708 headerObj[label] = value;
2713 headerObj[label] = value + "," + headerObj[label];
2717 this.hasDefaultHeaders = true;
2720 this.hasHeaders = true;
2725 setHeader:function(o)
2727 if (this.hasDefaultHeaders) {
2728 for (var prop in this.defaultHeaders) {
2729 if (this.defaultHeaders.hasOwnProperty(prop)) {
2730 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2735 if (this.hasHeaders) {
2736 for (var prop in this.headers) {
2737 if (this.headers.hasOwnProperty(prop)) {
2738 o.conn.setRequestHeader(prop, this.headers[prop]);
2742 this.hasHeaders = false;
2746 resetDefaultHeaders:function() {
2747 delete this.defaultHeaders;
2748 this.defaultHeaders = {};
2749 this.hasDefaultHeaders = false;
2752 abort:function(o, callback, isTimeout)
2754 if(this.isCallInProgress(o)) {
2756 window.clearInterval(this.poll[o.tId]);
2757 delete this.poll[o.tId];
2759 delete this.timeout[o.tId];
2762 this.handleTransactionResponse(o, callback, true);
2772 isCallInProgress:function(o)
2775 return o.conn.readyState != 4 && o.conn.readyState != 0;
2784 releaseObject:function(o)
2793 'MSXML2.XMLHTTP.3.0',
2801 * Portions of this file are based on pieces of Yahoo User Interface Library
2802 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2803 * YUI licensed under the BSD License:
2804 * http://developer.yahoo.net/yui/license.txt
2805 * <script type="text/javascript">
2809 Roo.lib.Region = function(t, r, b, l) {
2819 Roo.lib.Region.prototype = {
2820 contains : function(region) {
2821 return ( region.left >= this.left &&
2822 region.right <= this.right &&
2823 region.top >= this.top &&
2824 region.bottom <= this.bottom );
2828 getArea : function() {
2829 return ( (this.bottom - this.top) * (this.right - this.left) );
2832 intersect : function(region) {
2833 var t = Math.max(this.top, region.top);
2834 var r = Math.min(this.right, region.right);
2835 var b = Math.min(this.bottom, region.bottom);
2836 var l = Math.max(this.left, region.left);
2838 if (b >= t && r >= l) {
2839 return new Roo.lib.Region(t, r, b, l);
2844 union : function(region) {
2845 var t = Math.min(this.top, region.top);
2846 var r = Math.max(this.right, region.right);
2847 var b = Math.max(this.bottom, region.bottom);
2848 var l = Math.min(this.left, region.left);
2850 return new Roo.lib.Region(t, r, b, l);
2853 adjust : function(t, l, b, r) {
2862 Roo.lib.Region.getRegion = function(el) {
2863 var p = Roo.lib.Dom.getXY(el);
2866 var r = p[0] + el.offsetWidth;
2867 var b = p[1] + el.offsetHeight;
2870 return new Roo.lib.Region(t, r, b, l);
2873 * Portions of this file are based on pieces of Yahoo User Interface Library
2874 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2875 * YUI licensed under the BSD License:
2876 * http://developer.yahoo.net/yui/license.txt
2877 * <script type="text/javascript">
2880 //@@dep Roo.lib.Region
2883 Roo.lib.Point = function(x, y) {
2884 if (x instanceof Array) {
2888 this.x = this.right = this.left = this[0] = x;
2889 this.y = this.top = this.bottom = this[1] = y;
2892 Roo.lib.Point.prototype = new Roo.lib.Region();
2894 * Portions of this file are based on pieces of Yahoo User Interface Library
2895 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2896 * YUI licensed under the BSD License:
2897 * http://developer.yahoo.net/yui/license.txt
2898 * <script type="text/javascript">
2905 scroll : function(el, args, duration, easing, cb, scope) {
2906 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2909 motion : function(el, args, duration, easing, cb, scope) {
2910 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2913 color : function(el, args, duration, easing, cb, scope) {
2914 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2917 run : function(el, args, duration, easing, cb, scope, type) {
2918 type = type || Roo.lib.AnimBase;
2919 if (typeof easing == "string") {
2920 easing = Roo.lib.Easing[easing];
2922 var anim = new type(el, args, duration, easing);
2923 anim.animateX(function() {
2924 Roo.callback(cb, scope);
2930 * Portions of this file are based on pieces of Yahoo User Interface Library
2931 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2932 * YUI licensed under the BSD License:
2933 * http://developer.yahoo.net/yui/license.txt
2934 * <script type="text/javascript">
2942 if (!libFlyweight) {
2943 libFlyweight = new Roo.Element.Flyweight();
2945 libFlyweight.dom = el;
2946 return libFlyweight;
2949 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2953 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2955 this.init(el, attributes, duration, method);
2959 Roo.lib.AnimBase.fly = fly;
2963 Roo.lib.AnimBase.prototype = {
2965 toString: function() {
2966 var el = this.getEl();
2967 var id = el.id || el.tagName;
2968 return ("Anim " + id);
2972 noNegatives: /width|height|opacity|padding/i,
2973 offsetAttribute: /^((width|height)|(top|left))$/,
2974 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
2975 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
2979 doMethod: function(attr, start, end) {
2980 return this.method(this.currentFrame, start, end - start, this.totalFrames);
2984 setAttribute: function(attr, val, unit) {
2985 if (this.patterns.noNegatives.test(attr)) {
2986 val = (val > 0) ? val : 0;
2989 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
2993 getAttribute: function(attr) {
2994 var el = this.getEl();
2995 var val = fly(el).getStyle(attr);
2997 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
2998 return parseFloat(val);
3001 var a = this.patterns.offsetAttribute.exec(attr) || [];
3002 var pos = !!( a[3] );
3003 var box = !!( a[2] );
3006 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3007 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3016 getDefaultUnit: function(attr) {
3017 if (this.patterns.defaultUnit.test(attr)) {
3024 animateX : function(callback, scope) {
3025 var f = function() {
3026 this.onComplete.removeListener(f);
3027 if (typeof callback == "function") {
3028 callback.call(scope || this, this);
3031 this.onComplete.addListener(f, this);
3036 setRuntimeAttribute: function(attr) {
3039 var attributes = this.attributes;
3041 this.runtimeAttributes[attr] = {};
3043 var isset = function(prop) {
3044 return (typeof prop !== 'undefined');
3047 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3051 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3054 if (isset(attributes[attr]['to'])) {
3055 end = attributes[attr]['to'];
3056 } else if (isset(attributes[attr]['by'])) {
3057 if (start.constructor == Array) {
3059 for (var i = 0, len = start.length; i < len; ++i) {
3060 end[i] = start[i] + attributes[attr]['by'][i];
3063 end = start + attributes[attr]['by'];
3067 this.runtimeAttributes[attr].start = start;
3068 this.runtimeAttributes[attr].end = end;
3071 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3075 init: function(el, attributes, duration, method) {
3077 var isAnimated = false;
3080 var startTime = null;
3083 var actualFrames = 0;
3086 el = Roo.getDom(el);
3089 this.attributes = attributes || {};
3092 this.duration = duration || 1;
3095 this.method = method || Roo.lib.Easing.easeNone;
3098 this.useSeconds = true;
3101 this.currentFrame = 0;
3104 this.totalFrames = Roo.lib.AnimMgr.fps;
3107 this.getEl = function() {
3112 this.isAnimated = function() {
3117 this.getStartTime = function() {
3121 this.runtimeAttributes = {};
3124 this.animate = function() {
3125 if (this.isAnimated()) {
3129 this.currentFrame = 0;
3131 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3133 Roo.lib.AnimMgr.registerElement(this);
3137 this.stop = function(finish) {
3139 this.currentFrame = this.totalFrames;
3140 this._onTween.fire();
3142 Roo.lib.AnimMgr.stop(this);
3145 var onStart = function() {
3146 this.onStart.fire();
3148 this.runtimeAttributes = {};
3149 for (var attr in this.attributes) {
3150 this.setRuntimeAttribute(attr);
3155 startTime = new Date();
3159 var onTween = function() {
3161 duration: new Date() - this.getStartTime(),
3162 currentFrame: this.currentFrame
3165 data.toString = function() {
3167 'duration: ' + data.duration +
3168 ', currentFrame: ' + data.currentFrame
3172 this.onTween.fire(data);
3174 var runtimeAttributes = this.runtimeAttributes;
3176 for (var attr in runtimeAttributes) {
3177 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3183 var onComplete = function() {
3184 var actual_duration = (new Date() - startTime) / 1000 ;
3187 duration: actual_duration,
3188 frames: actualFrames,
3189 fps: actualFrames / actual_duration
3192 data.toString = function() {
3194 'duration: ' + data.duration +
3195 ', frames: ' + data.frames +
3196 ', fps: ' + data.fps
3202 this.onComplete.fire(data);
3206 this._onStart = new Roo.util.Event(this);
3207 this.onStart = new Roo.util.Event(this);
3208 this.onTween = new Roo.util.Event(this);
3209 this._onTween = new Roo.util.Event(this);
3210 this.onComplete = new Roo.util.Event(this);
3211 this._onComplete = new Roo.util.Event(this);
3212 this._onStart.addListener(onStart);
3213 this._onTween.addListener(onTween);
3214 this._onComplete.addListener(onComplete);
3219 * Portions of this file are based on pieces of Yahoo User Interface Library
3220 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3221 * YUI licensed under the BSD License:
3222 * http://developer.yahoo.net/yui/license.txt
3223 * <script type="text/javascript">
3227 Roo.lib.AnimMgr = new function() {
3244 this.registerElement = function(tween) {
3245 queue[queue.length] = tween;
3247 tween._onStart.fire();
3252 this.unRegister = function(tween, index) {
3253 tween._onComplete.fire();
3254 index = index || getIndex(tween);
3256 queue.splice(index, 1);
3260 if (tweenCount <= 0) {
3266 this.start = function() {
3267 if (thread === null) {
3268 thread = setInterval(this.run, this.delay);
3273 this.stop = function(tween) {
3275 clearInterval(thread);
3277 for (var i = 0, len = queue.length; i < len; ++i) {
3278 if (queue[0].isAnimated()) {
3279 this.unRegister(queue[0], 0);
3288 this.unRegister(tween);
3293 this.run = function() {
3294 for (var i = 0, len = queue.length; i < len; ++i) {
3295 var tween = queue[i];
3296 if (!tween || !tween.isAnimated()) {
3300 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3302 tween.currentFrame += 1;
3304 if (tween.useSeconds) {
3305 correctFrame(tween);
3307 tween._onTween.fire();
3310 Roo.lib.AnimMgr.stop(tween, i);
3315 var getIndex = function(anim) {
3316 for (var i = 0, len = queue.length; i < len; ++i) {
3317 if (queue[i] == anim) {
3325 var correctFrame = function(tween) {
3326 var frames = tween.totalFrames;
3327 var frame = tween.currentFrame;
3328 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3329 var elapsed = (new Date() - tween.getStartTime());
3332 if (elapsed < tween.duration * 1000) {
3333 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3335 tweak = frames - (frame + 1);
3337 if (tweak > 0 && isFinite(tweak)) {
3338 if (tween.currentFrame + tweak >= frames) {
3339 tweak = frames - (frame + 1);
3342 tween.currentFrame += tweak;
3346 * Portions of this file are based on pieces of Yahoo User Interface Library
3347 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3348 * YUI licensed under the BSD License:
3349 * http://developer.yahoo.net/yui/license.txt
3350 * <script type="text/javascript">
3353 Roo.lib.Bezier = new function() {
3355 this.getPosition = function(points, t) {
3356 var n = points.length;
3359 for (var i = 0; i < n; ++i) {
3360 tmp[i] = [points[i][0], points[i][1]];
3363 for (var j = 1; j < n; ++j) {
3364 for (i = 0; i < n - j; ++i) {
3365 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3366 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3370 return [ tmp[0][0], tmp[0][1] ];
3374 * Portions of this file are based on pieces of Yahoo User Interface Library
3375 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3376 * YUI licensed under the BSD License:
3377 * http://developer.yahoo.net/yui/license.txt
3378 * <script type="text/javascript">
3383 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3384 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3387 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3389 var fly = Roo.lib.AnimBase.fly;
3391 var superclass = Y.ColorAnim.superclass;
3392 var proto = Y.ColorAnim.prototype;
3394 proto.toString = function() {
3395 var el = this.getEl();
3396 var id = el.id || el.tagName;
3397 return ("ColorAnim " + id);
3400 proto.patterns.color = /color$/i;
3401 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3402 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3403 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3404 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3407 proto.parseColor = function(s) {
3408 if (s.length == 3) {
3412 var c = this.patterns.hex.exec(s);
3413 if (c && c.length == 4) {
3414 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3417 c = this.patterns.rgb.exec(s);
3418 if (c && c.length == 4) {
3419 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3422 c = this.patterns.hex3.exec(s);
3423 if (c && c.length == 4) {
3424 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3429 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3430 proto.getAttribute = function(attr) {
3431 var el = this.getEl();
3432 if (this.patterns.color.test(attr)) {
3433 var val = fly(el).getStyle(attr);
3435 if (this.patterns.transparent.test(val)) {
3436 var parent = el.parentNode;
3437 val = fly(parent).getStyle(attr);
3439 while (parent && this.patterns.transparent.test(val)) {
3440 parent = parent.parentNode;
3441 val = fly(parent).getStyle(attr);
3442 if (parent.tagName.toUpperCase() == 'HTML') {
3448 val = superclass.getAttribute.call(this, attr);
3453 proto.getAttribute = function(attr) {
3454 var el = this.getEl();
3455 if (this.patterns.color.test(attr)) {
3456 var val = fly(el).getStyle(attr);
3458 if (this.patterns.transparent.test(val)) {
3459 var parent = el.parentNode;
3460 val = fly(parent).getStyle(attr);
3462 while (parent && this.patterns.transparent.test(val)) {
3463 parent = parent.parentNode;
3464 val = fly(parent).getStyle(attr);
3465 if (parent.tagName.toUpperCase() == 'HTML') {
3471 val = superclass.getAttribute.call(this, attr);
3477 proto.doMethod = function(attr, start, end) {
3480 if (this.patterns.color.test(attr)) {
3482 for (var i = 0, len = start.length; i < len; ++i) {
3483 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3486 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3489 val = superclass.doMethod.call(this, attr, start, end);
3495 proto.setRuntimeAttribute = function(attr) {
3496 superclass.setRuntimeAttribute.call(this, attr);
3498 if (this.patterns.color.test(attr)) {
3499 var attributes = this.attributes;
3500 var start = this.parseColor(this.runtimeAttributes[attr].start);
3501 var end = this.parseColor(this.runtimeAttributes[attr].end);
3503 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3504 end = this.parseColor(attributes[attr].by);
3506 for (var i = 0, len = start.length; i < len; ++i) {
3507 end[i] = start[i] + end[i];
3511 this.runtimeAttributes[attr].start = start;
3512 this.runtimeAttributes[attr].end = end;
3518 * Portions of this file are based on pieces of Yahoo User Interface Library
3519 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3520 * YUI licensed under the BSD License:
3521 * http://developer.yahoo.net/yui/license.txt
3522 * <script type="text/javascript">
3528 easeNone: function (t, b, c, d) {
3529 return c * t / d + b;
3533 easeIn: function (t, b, c, d) {
3534 return c * (t /= d) * t + b;
3538 easeOut: function (t, b, c, d) {
3539 return -c * (t /= d) * (t - 2) + b;
3543 easeBoth: function (t, b, c, d) {
3544 if ((t /= d / 2) < 1) {
3545 return c / 2 * t * t + b;
3548 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3552 easeInStrong: function (t, b, c, d) {
3553 return c * (t /= d) * t * t * t + b;
3557 easeOutStrong: function (t, b, c, d) {
3558 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3562 easeBothStrong: function (t, b, c, d) {
3563 if ((t /= d / 2) < 1) {
3564 return c / 2 * t * t * t * t + b;
3567 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3572 elasticIn: function (t, b, c, d, a, p) {
3576 if ((t /= d) == 1) {
3583 if (!a || a < Math.abs(c)) {
3588 var s = p / (2 * Math.PI) * Math.asin(c / a);
3591 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3595 elasticOut: function (t, b, c, d, a, p) {
3599 if ((t /= d) == 1) {
3606 if (!a || a < Math.abs(c)) {
3611 var s = p / (2 * Math.PI) * Math.asin(c / a);
3614 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3618 elasticBoth: function (t, b, c, d, a, p) {
3623 if ((t /= d / 2) == 2) {
3631 if (!a || a < Math.abs(c)) {
3636 var s = p / (2 * Math.PI) * Math.asin(c / a);
3640 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3641 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3643 return a * Math.pow(2, -10 * (t -= 1)) *
3644 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3649 backIn: function (t, b, c, d, s) {
3650 if (typeof s == 'undefined') {
3653 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3657 backOut: function (t, b, c, d, s) {
3658 if (typeof s == 'undefined') {
3661 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3665 backBoth: function (t, b, c, d, s) {
3666 if (typeof s == 'undefined') {
3670 if ((t /= d / 2 ) < 1) {
3671 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3673 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3677 bounceIn: function (t, b, c, d) {
3678 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3682 bounceOut: function (t, b, c, d) {
3683 if ((t /= d) < (1 / 2.75)) {
3684 return c * (7.5625 * t * t) + b;
3685 } else if (t < (2 / 2.75)) {
3686 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3687 } else if (t < (2.5 / 2.75)) {
3688 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3690 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3694 bounceBoth: function (t, b, c, d) {
3696 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3698 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3701 * Portions of this file are based on pieces of Yahoo User Interface Library
3702 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3703 * YUI licensed under the BSD License:
3704 * http://developer.yahoo.net/yui/license.txt
3705 * <script type="text/javascript">
3709 Roo.lib.Motion = function(el, attributes, duration, method) {
3711 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3715 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3719 var superclass = Y.Motion.superclass;
3720 var proto = Y.Motion.prototype;
3722 proto.toString = function() {
3723 var el = this.getEl();
3724 var id = el.id || el.tagName;
3725 return ("Motion " + id);
3728 proto.patterns.points = /^points$/i;
3730 proto.setAttribute = function(attr, val, unit) {
3731 if (this.patterns.points.test(attr)) {
3732 unit = unit || 'px';
3733 superclass.setAttribute.call(this, 'left', val[0], unit);
3734 superclass.setAttribute.call(this, 'top', val[1], unit);
3736 superclass.setAttribute.call(this, attr, val, unit);
3740 proto.getAttribute = function(attr) {
3741 if (this.patterns.points.test(attr)) {
3743 superclass.getAttribute.call(this, 'left'),
3744 superclass.getAttribute.call(this, 'top')
3747 val = superclass.getAttribute.call(this, attr);
3753 proto.doMethod = function(attr, start, end) {
3756 if (this.patterns.points.test(attr)) {
3757 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3758 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3760 val = superclass.doMethod.call(this, attr, start, end);
3765 proto.setRuntimeAttribute = function(attr) {
3766 if (this.patterns.points.test(attr)) {
3767 var el = this.getEl();
3768 var attributes = this.attributes;
3770 var control = attributes['points']['control'] || [];
3774 if (control.length > 0 && !(control[0] instanceof Array)) {
3775 control = [control];
3778 for (i = 0,len = control.length; i < len; ++i) {
3779 tmp[i] = control[i];
3784 Roo.fly(el).position();
3786 if (isset(attributes['points']['from'])) {
3787 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3790 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3793 start = this.getAttribute('points');
3796 if (isset(attributes['points']['to'])) {
3797 end = translateValues.call(this, attributes['points']['to'], start);
3799 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3800 for (i = 0,len = control.length; i < len; ++i) {
3801 control[i] = translateValues.call(this, control[i], start);
3805 } else if (isset(attributes['points']['by'])) {
3806 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3808 for (i = 0,len = control.length; i < len; ++i) {
3809 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3813 this.runtimeAttributes[attr] = [start];
3815 if (control.length > 0) {
3816 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3819 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3822 superclass.setRuntimeAttribute.call(this, attr);
3826 var translateValues = function(val, start) {
3827 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3828 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3833 var isset = function(prop) {
3834 return (typeof prop !== 'undefined');
3838 * Portions of this file are based on pieces of Yahoo User Interface Library
3839 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3840 * YUI licensed under the BSD License:
3841 * http://developer.yahoo.net/yui/license.txt
3842 * <script type="text/javascript">
3846 Roo.lib.Scroll = function(el, attributes, duration, method) {
3848 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3852 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3856 var superclass = Y.Scroll.superclass;
3857 var proto = Y.Scroll.prototype;
3859 proto.toString = function() {
3860 var el = this.getEl();
3861 var id = el.id || el.tagName;
3862 return ("Scroll " + id);
3865 proto.doMethod = function(attr, start, end) {
3868 if (attr == 'scroll') {
3870 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3871 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3875 val = superclass.doMethod.call(this, attr, start, end);
3880 proto.getAttribute = function(attr) {
3882 var el = this.getEl();
3884 if (attr == 'scroll') {
3885 val = [ el.scrollLeft, el.scrollTop ];
3887 val = superclass.getAttribute.call(this, attr);
3893 proto.setAttribute = function(attr, val, unit) {
3894 var el = this.getEl();
3896 if (attr == 'scroll') {
3897 el.scrollLeft = val[0];
3898 el.scrollTop = val[1];
3900 superclass.setAttribute.call(this, attr, val, unit);
3906 * Ext JS Library 1.1.1
3907 * Copyright(c) 2006-2007, Ext JS, LLC.
3909 * Originally Released Under LGPL - original licence link has changed is not relivant.
3912 * <script type="text/javascript">
3917 * @class Roo.DomHelper
3918 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3919 * 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>.
3922 Roo.DomHelper = function(){
3923 var tempTableEl = null;
3924 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3925 var tableRe = /^table|tbody|tr|td$/i;
3927 // build as innerHTML where available
3929 var createHtml = function(o){
3930 if(typeof o == 'string'){
3939 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3940 if(attr == "style"){
3942 if(typeof s == "function"){
3945 if(typeof s == "string"){
3946 b += ' style="' + s + '"';
3947 }else if(typeof s == "object"){
3950 if(typeof s[key] != "function"){
3951 b += key + ":" + s[key] + ";";
3958 b += ' class="' + o["cls"] + '"';
3959 }else if(attr == "htmlFor"){
3960 b += ' for="' + o["htmlFor"] + '"';
3962 b += " " + attr + '="' + o[attr] + '"';
3966 if(emptyTags.test(o.tag)){
3970 var cn = o.children || o.cn;
3972 //http://bugs.kde.org/show_bug.cgi?id=71506
3973 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
3974 for(var i = 0, len = cn.length; i < len; i++) {
3975 b += createHtml(cn[i], b);
3978 b += createHtml(cn, b);
3984 b += "</" + o.tag + ">";
3991 var createDom = function(o, parentNode){
3993 // defininition craeted..
3995 if (o.ns && o.ns != 'html') {
3997 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
3998 xmlns[o.ns] = o.xmlns;
4001 if (typeof(xmlns[o.ns]) == 'undefined') {
4002 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4008 if (typeof(o) == 'string') {
4009 return parentNode.appendChild(document.createTextNode(o));
4011 o.tag = o.tag || div;
4012 if (o.ns && Roo.isIE) {
4014 o.tag = o.ns + ':' + o.tag;
4017 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4018 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4021 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4022 attr == "style" || typeof o[attr] == "function") continue;
4024 if(attr=="cls" && Roo.isIE){
4025 el.className = o["cls"];
4027 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4028 else el[attr] = o[attr];
4031 Roo.DomHelper.applyStyles(el, o.style);
4032 var cn = o.children || o.cn;
4034 //http://bugs.kde.org/show_bug.cgi?id=71506
4035 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4036 for(var i = 0, len = cn.length; i < len; i++) {
4037 createDom(cn[i], el);
4044 el.innerHTML = o.html;
4047 parentNode.appendChild(el);
4052 var ieTable = function(depth, s, h, e){
4053 tempTableEl.innerHTML = [s, h, e].join('');
4054 var i = -1, el = tempTableEl;
4061 // kill repeat to save bytes
4065 tbe = '</tbody>'+te,
4071 * Nasty code for IE's broken table implementation
4073 var insertIntoTable = function(tag, where, el, html){
4075 tempTableEl = document.createElement('div');
4080 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4083 if(where == 'beforebegin'){
4087 before = el.nextSibling;
4090 node = ieTable(4, trs, html, tre);
4092 else if(tag == 'tr'){
4093 if(where == 'beforebegin'){
4096 node = ieTable(3, tbs, html, tbe);
4097 } else if(where == 'afterend'){
4098 before = el.nextSibling;
4100 node = ieTable(3, tbs, html, tbe);
4101 } else{ // INTO a TR
4102 if(where == 'afterbegin'){
4103 before = el.firstChild;
4105 node = ieTable(4, trs, html, tre);
4107 } else if(tag == 'tbody'){
4108 if(where == 'beforebegin'){
4111 node = ieTable(2, ts, html, te);
4112 } else if(where == 'afterend'){
4113 before = el.nextSibling;
4115 node = ieTable(2, ts, html, te);
4117 if(where == 'afterbegin'){
4118 before = el.firstChild;
4120 node = ieTable(3, tbs, html, tbe);
4123 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4126 if(where == 'afterbegin'){
4127 before = el.firstChild;
4129 node = ieTable(2, ts, html, te);
4131 el.insertBefore(node, before);
4136 /** True to force the use of DOM instead of html fragments @type Boolean */
4140 * Returns the markup for the passed Element(s) config
4141 * @param {Object} o The Dom object spec (and children)
4144 markup : function(o){
4145 return createHtml(o);
4149 * Applies a style specification to an element
4150 * @param {String/HTMLElement} el The element to apply styles to
4151 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4152 * a function which returns such a specification.
4154 applyStyles : function(el, styles){
4157 if(typeof styles == "string"){
4158 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4160 while ((matches = re.exec(styles)) != null){
4161 el.setStyle(matches[1], matches[2]);
4163 }else if (typeof styles == "object"){
4164 for (var style in styles){
4165 el.setStyle(style, styles[style]);
4167 }else if (typeof styles == "function"){
4168 Roo.DomHelper.applyStyles(el, styles.call());
4174 * Inserts an HTML fragment into the Dom
4175 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4176 * @param {HTMLElement} el The context element
4177 * @param {String} html The HTML fragmenet
4178 * @return {HTMLElement} The new node
4180 insertHtml : function(where, el, html){
4181 where = where.toLowerCase();
4182 if(el.insertAdjacentHTML){
4183 if(tableRe.test(el.tagName)){
4185 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4191 el.insertAdjacentHTML('BeforeBegin', html);
4192 return el.previousSibling;
4194 el.insertAdjacentHTML('AfterBegin', html);
4195 return el.firstChild;
4197 el.insertAdjacentHTML('BeforeEnd', html);
4198 return el.lastChild;
4200 el.insertAdjacentHTML('AfterEnd', html);
4201 return el.nextSibling;
4203 throw 'Illegal insertion point -> "' + where + '"';
4205 var range = el.ownerDocument.createRange();
4209 range.setStartBefore(el);
4210 frag = range.createContextualFragment(html);
4211 el.parentNode.insertBefore(frag, el);
4212 return el.previousSibling;
4215 range.setStartBefore(el.firstChild);
4216 frag = range.createContextualFragment(html);
4217 el.insertBefore(frag, el.firstChild);
4218 return el.firstChild;
4220 el.innerHTML = html;
4221 return el.firstChild;
4225 range.setStartAfter(el.lastChild);
4226 frag = range.createContextualFragment(html);
4227 el.appendChild(frag);
4228 return el.lastChild;
4230 el.innerHTML = html;
4231 return el.lastChild;
4234 range.setStartAfter(el);
4235 frag = range.createContextualFragment(html);
4236 el.parentNode.insertBefore(frag, el.nextSibling);
4237 return el.nextSibling;
4239 throw 'Illegal insertion point -> "' + where + '"';
4243 * Creates new Dom element(s) and inserts them before el
4244 * @param {String/HTMLElement/Element} el The context element
4245 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4246 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4247 * @return {HTMLElement/Roo.Element} The new node
4249 insertBefore : function(el, o, returnElement){
4250 return this.doInsert(el, o, returnElement, "beforeBegin");
4254 * Creates new Dom element(s) and inserts them after el
4255 * @param {String/HTMLElement/Element} el The context element
4256 * @param {Object} o The Dom object spec (and children)
4257 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4258 * @return {HTMLElement/Roo.Element} The new node
4260 insertAfter : function(el, o, returnElement){
4261 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4265 * Creates new Dom element(s) and inserts them as the first child of el
4266 * @param {String/HTMLElement/Element} el The context element
4267 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4268 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4269 * @return {HTMLElement/Roo.Element} The new node
4271 insertFirst : function(el, o, returnElement){
4272 return this.doInsert(el, o, returnElement, "afterBegin");
4276 doInsert : function(el, o, returnElement, pos, sibling){
4277 el = Roo.getDom(el);
4279 if(this.useDom || o.ns){
4280 newNode = createDom(o, null);
4281 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4283 var html = createHtml(o);
4284 newNode = this.insertHtml(pos, el, html);
4286 return returnElement ? Roo.get(newNode, true) : newNode;
4290 * Creates new Dom element(s) and appends them to el
4291 * @param {String/HTMLElement/Element} el The context element
4292 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4293 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4294 * @return {HTMLElement/Roo.Element} The new node
4296 append : function(el, o, returnElement){
4297 el = Roo.getDom(el);
4299 if(this.useDom || o.ns){
4300 newNode = createDom(o, null);
4301 el.appendChild(newNode);
4303 var html = createHtml(o);
4304 newNode = this.insertHtml("beforeEnd", el, html);
4306 return returnElement ? Roo.get(newNode, true) : newNode;
4310 * Creates new Dom element(s) and overwrites the contents of el with them
4311 * @param {String/HTMLElement/Element} el The context element
4312 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4313 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4314 * @return {HTMLElement/Roo.Element} The new node
4316 overwrite : function(el, o, returnElement){
4317 el = Roo.getDom(el);
4320 while (el.childNodes.length) {
4321 el.removeChild(el.firstChild);
4325 el.innerHTML = createHtml(o);
4328 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4332 * Creates a new Roo.DomHelper.Template from the Dom object spec
4333 * @param {Object} o The Dom object spec (and children)
4334 * @return {Roo.DomHelper.Template} The new template
4336 createTemplate : function(o){
4337 var html = createHtml(o);
4338 return new Roo.Template(html);
4344 * Ext JS Library 1.1.1
4345 * Copyright(c) 2006-2007, Ext JS, LLC.
4347 * Originally Released Under LGPL - original licence link has changed is not relivant.
4350 * <script type="text/javascript">
4354 * @class Roo.Template
4355 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4356 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4359 var t = new Roo.Template(
4360 '<div name="{id}">',
4361 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4364 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4366 * 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>.
4368 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4370 Roo.Template = function(html){
4371 if(html instanceof Array){
4372 html = html.join("");
4373 }else if(arguments.length > 1){
4374 html = Array.prototype.join.call(arguments, "");
4380 Roo.Template.prototype = {
4382 * Returns an HTML fragment of this template with the specified values applied.
4383 * @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'})
4384 * @return {String} The HTML fragment
4386 applyTemplate : function(values){
4388 return this.compiled(values);
4390 var useF = this.disableFormats !== true;
4391 var fm = Roo.util.Format, tpl = this;
4392 var fn = function(m, name, format, args){
4394 if(format.substr(0, 5) == "this."){
4395 return tpl.call(format.substr(5), values[name], values);
4398 // quoted values are required for strings in compiled templates,
4399 // but for non compiled we need to strip them
4400 // quoted reversed for jsmin
4401 var re = /^\s*['"](.*)["']\s*$/;
4402 args = args.split(',');
4403 for(var i = 0, len = args.length; i < len; i++){
4404 args[i] = args[i].replace(re, "$1");
4406 args = [values[name]].concat(args);
4408 args = [values[name]];
4410 return fm[format].apply(fm, args);
4413 return values[name] !== undefined ? values[name] : "";
4416 return this.html.replace(this.re, fn);
4420 * Sets the HTML used as the template and optionally compiles it.
4421 * @param {String} html
4422 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4423 * @return {Roo.Template} this
4425 set : function(html, compile){
4427 this.compiled = null;
4435 * True to disable format functions (defaults to false)
4438 disableFormats : false,
4441 * The regular expression used to match template variables
4445 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4448 * Compiles the template into an internal function, eliminating the RegEx overhead.
4449 * @return {Roo.Template} this
4451 compile : function(){
4452 var fm = Roo.util.Format;
4453 var useF = this.disableFormats !== true;
4454 var sep = Roo.isGecko ? "+" : ",";
4455 var fn = function(m, name, format, args){
4457 args = args ? ',' + args : "";
4458 if(format.substr(0, 5) != "this."){
4459 format = "fm." + format + '(';
4461 format = 'this.call("'+ format.substr(5) + '", ';
4465 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4467 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4470 // branched to use + in gecko and [].join() in others
4472 body = "this.compiled = function(values){ return '" +
4473 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4476 body = ["this.compiled = function(values){ return ['"];
4477 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4478 body.push("'].join('');};");
4479 body = body.join('');
4489 // private function used to call members
4490 call : function(fnName, value, allValues){
4491 return this[fnName](value, allValues);
4495 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4496 * @param {String/HTMLElement/Roo.Element} el The context element
4497 * @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'})
4498 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4499 * @return {HTMLElement/Roo.Element} The new node or Element
4501 insertFirst: function(el, values, returnElement){
4502 return this.doInsert('afterBegin', el, values, returnElement);
4506 * Applies the supplied values to the template and inserts the new node(s) before el.
4507 * @param {String/HTMLElement/Roo.Element} el The context element
4508 * @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'})
4509 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4510 * @return {HTMLElement/Roo.Element} The new node or Element
4512 insertBefore: function(el, values, returnElement){
4513 return this.doInsert('beforeBegin', el, values, returnElement);
4517 * Applies the supplied values to the template and inserts the new node(s) after el.
4518 * @param {String/HTMLElement/Roo.Element} el The context element
4519 * @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'})
4520 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4521 * @return {HTMLElement/Roo.Element} The new node or Element
4523 insertAfter : function(el, values, returnElement){
4524 return this.doInsert('afterEnd', el, values, returnElement);
4528 * Applies the supplied values to the template and appends the new node(s) to el.
4529 * @param {String/HTMLElement/Roo.Element} el The context element
4530 * @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'})
4531 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4532 * @return {HTMLElement/Roo.Element} The new node or Element
4534 append : function(el, values, returnElement){
4535 return this.doInsert('beforeEnd', el, values, returnElement);
4538 doInsert : function(where, el, values, returnEl){
4539 el = Roo.getDom(el);
4540 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4541 return returnEl ? Roo.get(newNode, true) : newNode;
4545 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4546 * @param {String/HTMLElement/Roo.Element} el The context element
4547 * @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'})
4548 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4549 * @return {HTMLElement/Roo.Element} The new node or Element
4551 overwrite : function(el, values, returnElement){
4552 el = Roo.getDom(el);
4553 el.innerHTML = this.applyTemplate(values);
4554 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4558 * Alias for {@link #applyTemplate}
4561 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4564 Roo.DomHelper.Template = Roo.Template;
4567 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4568 * @param {String/HTMLElement} el A DOM element or its id
4569 * @returns {Roo.Template} The created template
4572 Roo.Template.from = function(el){
4573 el = Roo.getDom(el);
4574 return new Roo.Template(el.value || el.innerHTML);
4577 * Ext JS Library 1.1.1
4578 * Copyright(c) 2006-2007, Ext JS, LLC.
4580 * Originally Released Under LGPL - original licence link has changed is not relivant.
4583 * <script type="text/javascript">
4588 * This is code is also distributed under MIT license for use
4589 * with jQuery and prototype JavaScript libraries.
4592 * @class Roo.DomQuery
4593 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).
4595 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>
4598 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.
4600 <h4>Element Selectors:</h4>
4602 <li> <b>*</b> any element</li>
4603 <li> <b>E</b> an element with the tag E</li>
4604 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4605 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4606 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4607 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4609 <h4>Attribute Selectors:</h4>
4610 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4612 <li> <b>E[foo]</b> has an attribute "foo"</li>
4613 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4614 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4615 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4616 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4617 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4618 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4620 <h4>Pseudo Classes:</h4>
4622 <li> <b>E:first-child</b> E is the first child of its parent</li>
4623 <li> <b>E:last-child</b> E is the last child of its parent</li>
4624 <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>
4625 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4626 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4627 <li> <b>E:only-child</b> E is the only child of its parent</li>
4628 <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>
4629 <li> <b>E:first</b> the first E in the resultset</li>
4630 <li> <b>E:last</b> the last E in the resultset</li>
4631 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4632 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4633 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4634 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4635 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4636 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4637 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4638 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4639 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4641 <h4>CSS Value Selectors:</h4>
4643 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4644 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4645 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4646 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4647 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4648 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4652 Roo.DomQuery = function(){
4653 var cache = {}, simpleCache = {}, valueCache = {};
4654 var nonSpace = /\S/;
4655 var trimRe = /^\s+|\s+$/g;
4656 var tplRe = /\{(\d+)\}/g;
4657 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4658 var tagTokenRe = /^(#)?([\w-\*]+)/;
4659 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4661 function child(p, index){
4663 var n = p.firstChild;
4665 if(n.nodeType == 1){
4676 while((n = n.nextSibling) && n.nodeType != 1);
4681 while((n = n.previousSibling) && n.nodeType != 1);
4685 function children(d){
4686 var n = d.firstChild, ni = -1;
4688 var nx = n.nextSibling;
4689 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4699 function byClassName(c, a, v){
4703 var r = [], ri = -1, cn;
4704 for(var i = 0, ci; ci = c[i]; i++){
4705 if((' '+ci.className+' ').indexOf(v) != -1){
4712 function attrValue(n, attr){
4713 if(!n.tagName && typeof n.length != "undefined"){
4722 if(attr == "class" || attr == "className"){
4725 return n.getAttribute(attr) || n[attr];
4729 function getNodes(ns, mode, tagName){
4730 var result = [], ri = -1, cs;
4734 tagName = tagName || "*";
4735 if(typeof ns.getElementsByTagName != "undefined"){
4739 for(var i = 0, ni; ni = ns[i]; i++){
4740 cs = ni.getElementsByTagName(tagName);
4741 for(var j = 0, ci; ci = cs[j]; j++){
4745 }else if(mode == "/" || mode == ">"){
4746 var utag = tagName.toUpperCase();
4747 for(var i = 0, ni, cn; ni = ns[i]; i++){
4748 cn = ni.children || ni.childNodes;
4749 for(var j = 0, cj; cj = cn[j]; j++){
4750 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4755 }else if(mode == "+"){
4756 var utag = tagName.toUpperCase();
4757 for(var i = 0, n; n = ns[i]; i++){
4758 while((n = n.nextSibling) && n.nodeType != 1);
4759 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4763 }else if(mode == "~"){
4764 for(var i = 0, n; n = ns[i]; i++){
4765 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4774 function concat(a, b){
4778 for(var i = 0, l = b.length; i < l; i++){
4784 function byTag(cs, tagName){
4785 if(cs.tagName || cs == document){
4791 var r = [], ri = -1;
4792 tagName = tagName.toLowerCase();
4793 for(var i = 0, ci; ci = cs[i]; i++){
4794 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4801 function byId(cs, attr, id){
4802 if(cs.tagName || cs == document){
4808 var r = [], ri = -1;
4809 for(var i = 0,ci; ci = cs[i]; i++){
4810 if(ci && ci.id == id){
4818 function byAttribute(cs, attr, value, op, custom){
4819 var r = [], ri = -1, st = custom=="{";
4820 var f = Roo.DomQuery.operators[op];
4821 for(var i = 0, ci; ci = cs[i]; i++){
4824 a = Roo.DomQuery.getStyle(ci, attr);
4826 else if(attr == "class" || attr == "className"){
4828 }else if(attr == "for"){
4830 }else if(attr == "href"){
4831 a = ci.getAttribute("href", 2);
4833 a = ci.getAttribute(attr);
4835 if((f && f(a, value)) || (!f && a)){
4842 function byPseudo(cs, name, value){
4843 return Roo.DomQuery.pseudos[name](cs, value);
4846 // This is for IE MSXML which does not support expandos.
4847 // IE runs the same speed using setAttribute, however FF slows way down
4848 // and Safari completely fails so they need to continue to use expandos.
4849 var isIE = window.ActiveXObject ? true : false;
4851 // this eval is stop the compressor from
4852 // renaming the variable to something shorter
4854 /** eval:var:batch */
4859 function nodupIEXml(cs){
4861 cs[0].setAttribute("_nodup", d);
4863 for(var i = 1, len = cs.length; i < len; i++){
4865 if(!c.getAttribute("_nodup") != d){
4866 c.setAttribute("_nodup", d);
4870 for(var i = 0, len = cs.length; i < len; i++){
4871 cs[i].removeAttribute("_nodup");
4880 var len = cs.length, c, i, r = cs, cj, ri = -1;
4881 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4884 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4885 return nodupIEXml(cs);
4889 for(i = 1; c = cs[i]; i++){
4894 for(var j = 0; j < i; j++){
4897 for(j = i+1; cj = cs[j]; j++){
4909 function quickDiffIEXml(c1, c2){
4911 for(var i = 0, len = c1.length; i < len; i++){
4912 c1[i].setAttribute("_qdiff", d);
4915 for(var i = 0, len = c2.length; i < len; i++){
4916 if(c2[i].getAttribute("_qdiff") != d){
4917 r[r.length] = c2[i];
4920 for(var i = 0, len = c1.length; i < len; i++){
4921 c1[i].removeAttribute("_qdiff");
4926 function quickDiff(c1, c2){
4927 var len1 = c1.length;
4931 if(isIE && c1[0].selectSingleNode){
4932 return quickDiffIEXml(c1, c2);
4935 for(var i = 0; i < len1; i++){
4939 for(var i = 0, len = c2.length; i < len; i++){
4940 if(c2[i]._qdiff != d){
4941 r[r.length] = c2[i];
4947 function quickId(ns, mode, root, id){
4949 var d = root.ownerDocument || root;
4950 return d.getElementById(id);
4952 ns = getNodes(ns, mode, "*");
4953 return byId(ns, null, id);
4957 getStyle : function(el, name){
4958 return Roo.fly(el).getStyle(name);
4961 * Compiles a selector/xpath query into a reusable function. The returned function
4962 * takes one parameter "root" (optional), which is the context node from where the query should start.
4963 * @param {String} selector The selector/xpath query
4964 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4965 * @return {Function}
4967 compile : function(path, type){
4968 type = type || "select";
4970 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
4971 var q = path, mode, lq;
4972 var tk = Roo.DomQuery.matchers;
4973 var tklen = tk.length;
4976 // accept leading mode switch
4977 var lmode = q.match(modeRe);
4978 if(lmode && lmode[1]){
4979 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
4980 q = q.replace(lmode[1], "");
4982 // strip leading slashes
4983 while(path.substr(0, 1)=="/"){
4984 path = path.substr(1);
4987 while(q && lq != q){
4989 var tm = q.match(tagTokenRe);
4990 if(type == "select"){
4993 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
4995 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
4997 q = q.replace(tm[0], "");
4998 }else if(q.substr(0, 1) != '@'){
4999 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5004 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5006 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5008 q = q.replace(tm[0], "");
5011 while(!(mm = q.match(modeRe))){
5012 var matched = false;
5013 for(var j = 0; j < tklen; j++){
5015 var m = q.match(t.re);
5017 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5020 q = q.replace(m[0], "");
5025 // prevent infinite loop on bad selector
5027 throw 'Error parsing selector, parsing failed at "' + q + '"';
5031 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5032 q = q.replace(mm[1], "");
5035 fn[fn.length] = "return nodup(n);\n}";
5038 * list of variables that need from compression as they are used by eval.
5048 * eval:var:byClassName
5050 * eval:var:byAttribute
5051 * eval:var:attrValue
5059 * Selects a group of elements.
5060 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5061 * @param {Node} root (optional) The start of the query (defaults to document).
5064 select : function(path, root, type){
5065 if(!root || root == document){
5068 if(typeof root == "string"){
5069 root = document.getElementById(root);
5071 var paths = path.split(",");
5073 for(var i = 0, len = paths.length; i < len; i++){
5074 var p = paths[i].replace(trimRe, "");
5076 cache[p] = Roo.DomQuery.compile(p);
5078 throw p + " is not a valid selector";
5081 var result = cache[p](root);
5082 if(result && result != document){
5083 results = results.concat(result);
5086 if(paths.length > 1){
5087 return nodup(results);
5093 * Selects a single element.
5094 * @param {String} selector The selector/xpath query
5095 * @param {Node} root (optional) The start of the query (defaults to document).
5098 selectNode : function(path, root){
5099 return Roo.DomQuery.select(path, root)[0];
5103 * Selects the value of a node, optionally replacing null with the defaultValue.
5104 * @param {String} selector The selector/xpath query
5105 * @param {Node} root (optional) The start of the query (defaults to document).
5106 * @param {String} defaultValue
5108 selectValue : function(path, root, defaultValue){
5109 path = path.replace(trimRe, "");
5110 if(!valueCache[path]){
5111 valueCache[path] = Roo.DomQuery.compile(path, "select");
5113 var n = valueCache[path](root);
5114 n = n[0] ? n[0] : n;
5115 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5116 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5120 * Selects the value of a node, parsing integers and floats.
5121 * @param {String} selector The selector/xpath query
5122 * @param {Node} root (optional) The start of the query (defaults to document).
5123 * @param {Number} defaultValue
5126 selectNumber : function(path, root, defaultValue){
5127 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5128 return parseFloat(v);
5132 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5133 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5134 * @param {String} selector The simple selector to test
5137 is : function(el, ss){
5138 if(typeof el == "string"){
5139 el = document.getElementById(el);
5141 var isArray = (el instanceof Array);
5142 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5143 return isArray ? (result.length == el.length) : (result.length > 0);
5147 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5148 * @param {Array} el An array of elements to filter
5149 * @param {String} selector The simple selector to test
5150 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5151 * the selector instead of the ones that match
5154 filter : function(els, ss, nonMatches){
5155 ss = ss.replace(trimRe, "");
5156 if(!simpleCache[ss]){
5157 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5159 var result = simpleCache[ss](els);
5160 return nonMatches ? quickDiff(result, els) : result;
5164 * Collection of matching regular expressions and code snippets.
5168 select: 'n = byClassName(n, null, " {1} ");'
5170 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5171 select: 'n = byPseudo(n, "{1}", "{2}");'
5173 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5174 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5177 select: 'n = byId(n, null, "{1}");'
5180 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5185 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5186 * 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, > <.
5189 "=" : function(a, v){
5192 "!=" : function(a, v){
5195 "^=" : function(a, v){
5196 return a && a.substr(0, v.length) == v;
5198 "$=" : function(a, v){
5199 return a && a.substr(a.length-v.length) == v;
5201 "*=" : function(a, v){
5202 return a && a.indexOf(v) !== -1;
5204 "%=" : function(a, v){
5205 return (a % v) == 0;
5207 "|=" : function(a, v){
5208 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5210 "~=" : function(a, v){
5211 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5216 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5217 * and the argument (if any) supplied in the selector.
5220 "first-child" : function(c){
5221 var r = [], ri = -1, n;
5222 for(var i = 0, ci; ci = n = c[i]; i++){
5223 while((n = n.previousSibling) && n.nodeType != 1);
5231 "last-child" : function(c){
5232 var r = [], ri = -1, n;
5233 for(var i = 0, ci; ci = n = c[i]; i++){
5234 while((n = n.nextSibling) && n.nodeType != 1);
5242 "nth-child" : function(c, a) {
5243 var r = [], ri = -1;
5244 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5245 var f = (m[1] || 1) - 0, l = m[2] - 0;
5246 for(var i = 0, n; n = c[i]; i++){
5247 var pn = n.parentNode;
5248 if (batch != pn._batch) {
5250 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5251 if(cn.nodeType == 1){
5258 if (l == 0 || n.nodeIndex == l){
5261 } else if ((n.nodeIndex + l) % f == 0){
5269 "only-child" : function(c){
5270 var r = [], ri = -1;;
5271 for(var i = 0, ci; ci = c[i]; i++){
5272 if(!prev(ci) && !next(ci)){
5279 "empty" : function(c){
5280 var r = [], ri = -1;
5281 for(var i = 0, ci; ci = c[i]; i++){
5282 var cns = ci.childNodes, j = 0, cn, empty = true;
5285 if(cn.nodeType == 1 || cn.nodeType == 3){
5297 "contains" : function(c, v){
5298 var r = [], ri = -1;
5299 for(var i = 0, ci; ci = c[i]; i++){
5300 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5307 "nodeValue" : function(c, v){
5308 var r = [], ri = -1;
5309 for(var i = 0, ci; ci = c[i]; i++){
5310 if(ci.firstChild && ci.firstChild.nodeValue == v){
5317 "checked" : function(c){
5318 var r = [], ri = -1;
5319 for(var i = 0, ci; ci = c[i]; i++){
5320 if(ci.checked == true){
5327 "not" : function(c, ss){
5328 return Roo.DomQuery.filter(c, ss, true);
5331 "odd" : function(c){
5332 return this["nth-child"](c, "odd");
5335 "even" : function(c){
5336 return this["nth-child"](c, "even");
5339 "nth" : function(c, a){
5340 return c[a-1] || [];
5343 "first" : function(c){
5347 "last" : function(c){
5348 return c[c.length-1] || [];
5351 "has" : function(c, ss){
5352 var s = Roo.DomQuery.select;
5353 var r = [], ri = -1;
5354 for(var i = 0, ci; ci = c[i]; i++){
5355 if(s(ss, ci).length > 0){
5362 "next" : function(c, ss){
5363 var is = Roo.DomQuery.is;
5364 var r = [], ri = -1;
5365 for(var i = 0, ci; ci = c[i]; i++){
5374 "prev" : function(c, ss){
5375 var is = Roo.DomQuery.is;
5376 var r = [], ri = -1;
5377 for(var i = 0, ci; ci = c[i]; i++){
5390 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5391 * @param {String} path The selector/xpath query
5392 * @param {Node} root (optional) The start of the query (defaults to document).
5397 Roo.query = Roo.DomQuery.select;
5400 * Ext JS Library 1.1.1
5401 * Copyright(c) 2006-2007, Ext JS, LLC.
5403 * Originally Released Under LGPL - original licence link has changed is not relivant.
5406 * <script type="text/javascript">
5410 * @class Roo.util.Observable
5411 * Base class that provides a common interface for publishing events. Subclasses are expected to
5412 * to have a property "events" with all the events defined.<br>
5415 Employee = function(name){
5422 Roo.extend(Employee, Roo.util.Observable);
5424 * @param {Object} config properties to use (incuding events / listeners)
5427 Roo.util.Observable = function(cfg){
5430 this.addEvents(cfg.events || {});
5432 delete cfg.events; // make sure
5435 Roo.apply(this, cfg);
5438 this.on(this.listeners);
5439 delete this.listeners;
5442 Roo.util.Observable.prototype = {
5444 * @cfg {Object} listeners list of events and functions to call for this object,
5448 'click' : function(e) {
5458 * Fires the specified event with the passed parameters (minus the event name).
5459 * @param {String} eventName
5460 * @param {Object...} args Variable number of parameters are passed to handlers
5461 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5463 fireEvent : function(){
5464 var ce = this.events[arguments[0].toLowerCase()];
5465 if(typeof ce == "object"){
5466 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5473 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5476 * Appends an event handler to this component
5477 * @param {String} eventName The type of event to listen for
5478 * @param {Function} handler The method the event invokes
5479 * @param {Object} scope (optional) The scope in which to execute the handler
5480 * function. The handler function's "this" context.
5481 * @param {Object} options (optional) An object containing handler configuration
5482 * properties. This may contain any of the following properties:<ul>
5483 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5484 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5485 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5486 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5487 * by the specified number of milliseconds. If the event fires again within that time, the original
5488 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5491 * <b>Combining Options</b><br>
5492 * Using the options argument, it is possible to combine different types of listeners:<br>
5494 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5496 el.on('click', this.onClick, this, {
5503 * <b>Attaching multiple handlers in 1 call</b><br>
5504 * The method also allows for a single argument to be passed which is a config object containing properties
5505 * which specify multiple handlers.
5514 fn: this.onMouseOver,
5518 fn: this.onMouseOut,
5524 * Or a shorthand syntax which passes the same scope object to all handlers:
5527 'click': this.onClick,
5528 'mouseover': this.onMouseOver,
5529 'mouseout': this.onMouseOut,
5534 addListener : function(eventName, fn, scope, o){
5535 if(typeof eventName == "object"){
5538 if(this.filterOptRe.test(e)){
5541 if(typeof o[e] == "function"){
5543 this.addListener(e, o[e], o.scope, o);
5545 // individual options
5546 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5551 o = (!o || typeof o == "boolean") ? {} : o;
5552 eventName = eventName.toLowerCase();
5553 var ce = this.events[eventName] || true;
5554 if(typeof ce == "boolean"){
5555 ce = new Roo.util.Event(this, eventName);
5556 this.events[eventName] = ce;
5558 ce.addListener(fn, scope, o);
5562 * Removes a listener
5563 * @param {String} eventName The type of event to listen for
5564 * @param {Function} handler The handler to remove
5565 * @param {Object} scope (optional) The scope (this object) for the handler
5567 removeListener : function(eventName, fn, scope){
5568 var ce = this.events[eventName.toLowerCase()];
5569 if(typeof ce == "object"){
5570 ce.removeListener(fn, scope);
5575 * Removes all listeners for this object
5577 purgeListeners : function(){
5578 for(var evt in this.events){
5579 if(typeof this.events[evt] == "object"){
5580 this.events[evt].clearListeners();
5585 relayEvents : function(o, events){
5586 var createHandler = function(ename){
5588 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5591 for(var i = 0, len = events.length; i < len; i++){
5592 var ename = events[i];
5593 if(!this.events[ename]){ this.events[ename] = true; };
5594 o.on(ename, createHandler(ename), this);
5599 * Used to define events on this Observable
5600 * @param {Object} object The object with the events defined
5602 addEvents : function(o){
5606 Roo.applyIf(this.events, o);
5610 * Checks to see if this object has any listeners for a specified event
5611 * @param {String} eventName The name of the event to check for
5612 * @return {Boolean} True if the event is being listened for, else false
5614 hasListener : function(eventName){
5615 var e = this.events[eventName];
5616 return typeof e == "object" && e.listeners.length > 0;
5620 * Appends an event handler to this element (shorthand for addListener)
5621 * @param {String} eventName The type of event to listen for
5622 * @param {Function} handler The method the event invokes
5623 * @param {Object} scope (optional) The scope in which to execute the handler
5624 * function. The handler function's "this" context.
5625 * @param {Object} options (optional)
5628 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5630 * Removes a listener (shorthand for removeListener)
5631 * @param {String} eventName The type of event to listen for
5632 * @param {Function} handler The handler to remove
5633 * @param {Object} scope (optional) The scope (this object) for the handler
5636 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5639 * Starts capture on the specified Observable. All events will be passed
5640 * to the supplied function with the event name + standard signature of the event
5641 * <b>before</b> the event is fired. If the supplied function returns false,
5642 * the event will not fire.
5643 * @param {Observable} o The Observable to capture
5644 * @param {Function} fn The function to call
5645 * @param {Object} scope (optional) The scope (this object) for the fn
5648 Roo.util.Observable.capture = function(o, fn, scope){
5649 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5653 * Removes <b>all</b> added captures from the Observable.
5654 * @param {Observable} o The Observable to release
5657 Roo.util.Observable.releaseCapture = function(o){
5658 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5663 var createBuffered = function(h, o, scope){
5664 var task = new Roo.util.DelayedTask();
5666 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5670 var createSingle = function(h, e, fn, scope){
5672 e.removeListener(fn, scope);
5673 return h.apply(scope, arguments);
5677 var createDelayed = function(h, o, scope){
5679 var args = Array.prototype.slice.call(arguments, 0);
5680 setTimeout(function(){
5681 h.apply(scope, args);
5686 Roo.util.Event = function(obj, name){
5689 this.listeners = [];
5692 Roo.util.Event.prototype = {
5693 addListener : function(fn, scope, options){
5694 var o = options || {};
5695 scope = scope || this.obj;
5696 if(!this.isListening(fn, scope)){
5697 var l = {fn: fn, scope: scope, options: o};
5700 h = createDelayed(h, o, scope);
5703 h = createSingle(h, this, fn, scope);
5706 h = createBuffered(h, o, scope);
5709 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5710 this.listeners.push(l);
5712 this.listeners = this.listeners.slice(0);
5713 this.listeners.push(l);
5718 findListener : function(fn, scope){
5719 scope = scope || this.obj;
5720 var ls = this.listeners;
5721 for(var i = 0, len = ls.length; i < len; i++){
5723 if(l.fn == fn && l.scope == scope){
5730 isListening : function(fn, scope){
5731 return this.findListener(fn, scope) != -1;
5734 removeListener : function(fn, scope){
5736 if((index = this.findListener(fn, scope)) != -1){
5738 this.listeners.splice(index, 1);
5740 this.listeners = this.listeners.slice(0);
5741 this.listeners.splice(index, 1);
5748 clearListeners : function(){
5749 this.listeners = [];
5753 var ls = this.listeners, scope, len = ls.length;
5756 var args = Array.prototype.slice.call(arguments, 0);
5757 for(var i = 0; i < len; i++){
5759 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5760 this.firing = false;
5764 this.firing = false;
5771 * Ext JS Library 1.1.1
5772 * Copyright(c) 2006-2007, Ext JS, LLC.
5774 * Originally Released Under LGPL - original licence link has changed is not relivant.
5777 * <script type="text/javascript">
5781 * @class Roo.EventManager
5782 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5783 * several useful events directly.
5784 * See {@link Roo.EventObject} for more details on normalized event objects.
5787 Roo.EventManager = function(){
5788 var docReadyEvent, docReadyProcId, docReadyState = false;
5789 var resizeEvent, resizeTask, textEvent, textSize;
5790 var E = Roo.lib.Event;
5791 var D = Roo.lib.Dom;
5794 var fireDocReady = function(){
5796 docReadyState = true;
5799 clearInterval(docReadyProcId);
5801 if(Roo.isGecko || Roo.isOpera) {
5802 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5805 var defer = document.getElementById("ie-deferred-loader");
5807 defer.onreadystatechange = null;
5808 defer.parentNode.removeChild(defer);
5812 docReadyEvent.fire();
5813 docReadyEvent.clearListeners();
5818 var initDocReady = function(){
5819 docReadyEvent = new Roo.util.Event();
5820 if(Roo.isGecko || Roo.isOpera) {
5821 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5823 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5824 var defer = document.getElementById("ie-deferred-loader");
5825 defer.onreadystatechange = function(){
5826 if(this.readyState == "complete"){
5830 }else if(Roo.isSafari){
5831 docReadyProcId = setInterval(function(){
5832 var rs = document.readyState;
5833 if(rs == "complete") {
5838 // no matter what, make sure it fires on load
5839 E.on(window, "load", fireDocReady);
5842 var createBuffered = function(h, o){
5843 var task = new Roo.util.DelayedTask(h);
5845 // create new event object impl so new events don't wipe out properties
5846 e = new Roo.EventObjectImpl(e);
5847 task.delay(o.buffer, h, null, [e]);
5851 var createSingle = function(h, el, ename, fn){
5853 Roo.EventManager.removeListener(el, ename, fn);
5858 var createDelayed = function(h, o){
5860 // create new event object impl so new events don't wipe out properties
5861 e = new Roo.EventObjectImpl(e);
5862 setTimeout(function(){
5868 var listen = function(element, ename, opt, fn, scope){
5869 var o = (!opt || typeof opt == "boolean") ? {} : opt;
5870 fn = fn || o.fn; scope = scope || o.scope;
5871 var el = Roo.getDom(element);
5873 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
5875 var h = function(e){
5876 e = Roo.EventObject.setEvent(e);
5879 t = e.getTarget(o.delegate, el);
5886 if(o.stopEvent === true){
5889 if(o.preventDefault === true){
5892 if(o.stopPropagation === true){
5893 e.stopPropagation();
5896 if(o.normalized === false){
5900 fn.call(scope || el, e, t, o);
5903 h = createDelayed(h, o);
5906 h = createSingle(h, el, ename, fn);
5909 h = createBuffered(h, o);
5911 fn._handlers = fn._handlers || [];
5912 fn._handlers.push([Roo.id(el), ename, h]);
5915 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
5916 el.addEventListener("DOMMouseScroll", h, false);
5917 E.on(window, 'unload', function(){
5918 el.removeEventListener("DOMMouseScroll", h, false);
5921 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5922 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
5927 var stopListening = function(el, ename, fn){
5928 var id = Roo.id(el), hds = fn._handlers, hd = fn;
5930 for(var i = 0, len = hds.length; i < len; i++){
5932 if(h[0] == id && h[1] == ename){
5939 E.un(el, ename, hd);
5940 el = Roo.getDom(el);
5941 if(ename == "mousewheel" && el.addEventListener){
5942 el.removeEventListener("DOMMouseScroll", hd, false);
5944 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5945 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
5949 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
5956 * @scope Roo.EventManager
5961 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
5962 * object with a Roo.EventObject
5963 * @param {Function} fn The method the event invokes
5964 * @param {Object} scope An object that becomes the scope of the handler
5965 * @param {boolean} override If true, the obj passed in becomes
5966 * the execution scope of the listener
5967 * @return {Function} The wrapped function
5970 wrap : function(fn, scope, override){
5972 Roo.EventObject.setEvent(e);
5973 fn.call(override ? scope || window : window, Roo.EventObject, scope);
5978 * Appends an event handler to an element (shorthand for addListener)
5979 * @param {String/HTMLElement} element The html element or id to assign the
5980 * @param {String} eventName The type of event to listen for
5981 * @param {Function} handler The method the event invokes
5982 * @param {Object} scope (optional) The scope in which to execute the handler
5983 * function. The handler function's "this" context.
5984 * @param {Object} options (optional) An object containing handler configuration
5985 * properties. This may contain any of the following properties:<ul>
5986 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5987 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
5988 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
5989 * <li>preventDefault {Boolean} True to prevent the default action</li>
5990 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
5991 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
5992 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5993 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5994 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5995 * by the specified number of milliseconds. If the event fires again within that time, the original
5996 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5999 * <b>Combining Options</b><br>
6000 * Using the options argument, it is possible to combine different types of listeners:<br>
6002 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6004 el.on('click', this.onClick, this, {
6011 * <b>Attaching multiple handlers in 1 call</b><br>
6012 * The method also allows for a single argument to be passed which is a config object containing properties
6013 * which specify multiple handlers.
6023 fn: this.onMouseOver
6032 * Or a shorthand syntax:<br>
6035 'click' : this.onClick,
6036 'mouseover' : this.onMouseOver,
6037 'mouseout' : this.onMouseOut
6041 addListener : function(element, eventName, fn, scope, options){
6042 if(typeof eventName == "object"){
6048 if(typeof o[e] == "function"){
6050 listen(element, e, o, o[e], o.scope);
6052 // individual options
6053 listen(element, e, o[e]);
6058 return listen(element, eventName, options, fn, scope);
6062 * Removes an event handler
6064 * @param {String/HTMLElement} element The id or html element to remove the
6066 * @param {String} eventName The type of event
6067 * @param {Function} fn
6068 * @return {Boolean} True if a listener was actually removed
6070 removeListener : function(element, eventName, fn){
6071 return stopListening(element, eventName, fn);
6075 * Fires when the document is ready (before onload and before images are loaded). Can be
6076 * accessed shorthanded Roo.onReady().
6077 * @param {Function} fn The method the event invokes
6078 * @param {Object} scope An object that becomes the scope of the handler
6079 * @param {boolean} options
6081 onDocumentReady : function(fn, scope, options){
6082 if(docReadyState){ // if it already fired
6083 docReadyEvent.addListener(fn, scope, options);
6084 docReadyEvent.fire();
6085 docReadyEvent.clearListeners();
6091 docReadyEvent.addListener(fn, scope, options);
6095 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6096 * @param {Function} fn The method the event invokes
6097 * @param {Object} scope An object that becomes the scope of the handler
6098 * @param {boolean} options
6100 onWindowResize : function(fn, scope, options){
6102 resizeEvent = new Roo.util.Event();
6103 resizeTask = new Roo.util.DelayedTask(function(){
6104 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6106 E.on(window, "resize", function(){
6108 resizeTask.delay(50);
6110 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6114 resizeEvent.addListener(fn, scope, options);
6118 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6119 * @param {Function} fn The method the event invokes
6120 * @param {Object} scope An object that becomes the scope of the handler
6121 * @param {boolean} options
6123 onTextResize : function(fn, scope, options){
6125 textEvent = new Roo.util.Event();
6126 var textEl = new Roo.Element(document.createElement('div'));
6127 textEl.dom.className = 'x-text-resize';
6128 textEl.dom.innerHTML = 'X';
6129 textEl.appendTo(document.body);
6130 textSize = textEl.dom.offsetHeight;
6131 setInterval(function(){
6132 if(textEl.dom.offsetHeight != textSize){
6133 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6135 }, this.textResizeInterval);
6137 textEvent.addListener(fn, scope, options);
6141 * Removes the passed window resize listener.
6142 * @param {Function} fn The method the event invokes
6143 * @param {Object} scope The scope of handler
6145 removeResizeListener : function(fn, scope){
6147 resizeEvent.removeListener(fn, scope);
6152 fireResize : function(){
6154 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6158 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6162 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6164 textResizeInterval : 50
6169 * @scopeAlias pub=Roo.EventManager
6173 * Appends an event handler to an element (shorthand for addListener)
6174 * @param {String/HTMLElement} element The html element or id to assign the
6175 * @param {String} eventName The type of event to listen for
6176 * @param {Function} handler The method the event invokes
6177 * @param {Object} scope (optional) The scope in which to execute the handler
6178 * function. The handler function's "this" context.
6179 * @param {Object} options (optional) An object containing handler configuration
6180 * properties. This may contain any of the following properties:<ul>
6181 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6182 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6183 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6184 * <li>preventDefault {Boolean} True to prevent the default action</li>
6185 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6186 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6187 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6188 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6189 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6190 * by the specified number of milliseconds. If the event fires again within that time, the original
6191 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6194 * <b>Combining Options</b><br>
6195 * Using the options argument, it is possible to combine different types of listeners:<br>
6197 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6199 el.on('click', this.onClick, this, {
6206 * <b>Attaching multiple handlers in 1 call</b><br>
6207 * The method also allows for a single argument to be passed which is a config object containing properties
6208 * which specify multiple handlers.
6218 fn: this.onMouseOver
6227 * Or a shorthand syntax:<br>
6230 'click' : this.onClick,
6231 'mouseover' : this.onMouseOver,
6232 'mouseout' : this.onMouseOut
6236 pub.on = pub.addListener;
6237 pub.un = pub.removeListener;
6239 pub.stoppedMouseDownEvent = new Roo.util.Event();
6243 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6244 * @param {Function} fn The method the event invokes
6245 * @param {Object} scope An object that becomes the scope of the handler
6246 * @param {boolean} override If true, the obj passed in becomes
6247 * the execution scope of the listener
6251 Roo.onReady = Roo.EventManager.onDocumentReady;
6253 Roo.onReady(function(){
6254 var bd = Roo.get(document.body);
6259 : Roo.isGecko ? "roo-gecko"
6260 : Roo.isOpera ? "roo-opera"
6261 : Roo.isSafari ? "roo-safari" : ""];
6264 cls.push("roo-mac");
6267 cls.push("roo-linux");
6269 if(Roo.isBorderBox){
6270 cls.push('roo-border-box');
6272 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6273 var p = bd.dom.parentNode;
6275 p.className += ' roo-strict';
6278 bd.addClass(cls.join(' '));
6282 * @class Roo.EventObject
6283 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6284 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6287 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6289 var target = e.getTarget();
6292 var myDiv = Roo.get("myDiv");
6293 myDiv.on("click", handleClick);
6295 Roo.EventManager.on("myDiv", 'click', handleClick);
6296 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6300 Roo.EventObject = function(){
6302 var E = Roo.lib.Event;
6304 // safari keypress events for special keys return bad keycodes
6307 63235 : 39, // right
6310 63276 : 33, // page up
6311 63277 : 34, // page down
6312 63272 : 46, // delete
6317 // normalize button clicks
6318 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6319 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6321 Roo.EventObjectImpl = function(e){
6323 this.setEvent(e.browserEvent || e);
6326 Roo.EventObjectImpl.prototype = {
6328 * Used to fix doc tools.
6329 * @scope Roo.EventObject.prototype
6335 /** The normal browser event */
6336 browserEvent : null,
6337 /** The button pressed in a mouse event */
6339 /** True if the shift key was down during the event */
6341 /** True if the control key was down during the event */
6343 /** True if the alt key was down during the event */
6402 setEvent : function(e){
6403 if(e == this || (e && e.browserEvent)){ // already wrapped
6406 this.browserEvent = e;
6408 // normalize buttons
6409 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6410 if(e.type == 'click' && this.button == -1){
6414 this.shiftKey = e.shiftKey;
6415 // mac metaKey behaves like ctrlKey
6416 this.ctrlKey = e.ctrlKey || e.metaKey;
6417 this.altKey = e.altKey;
6418 // in getKey these will be normalized for the mac
6419 this.keyCode = e.keyCode;
6420 // keyup warnings on firefox.
6421 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6422 // cache the target for the delayed and or buffered events
6423 this.target = E.getTarget(e);
6425 this.xy = E.getXY(e);
6428 this.shiftKey = false;
6429 this.ctrlKey = false;
6430 this.altKey = false;
6440 * Stop the event (preventDefault and stopPropagation)
6442 stopEvent : function(){
6443 if(this.browserEvent){
6444 if(this.browserEvent.type == 'mousedown'){
6445 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6447 E.stopEvent(this.browserEvent);
6452 * Prevents the browsers default handling of the event.
6454 preventDefault : function(){
6455 if(this.browserEvent){
6456 E.preventDefault(this.browserEvent);
6461 isNavKeyPress : function(){
6462 var k = this.keyCode;
6463 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6464 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6467 isSpecialKey : function(){
6468 var k = this.keyCode;
6469 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6470 (k == 16) || (k == 17) ||
6471 (k >= 18 && k <= 20) ||
6472 (k >= 33 && k <= 35) ||
6473 (k >= 36 && k <= 39) ||
6474 (k >= 44 && k <= 45);
6477 * Cancels bubbling of the event.
6479 stopPropagation : function(){
6480 if(this.browserEvent){
6481 if(this.type == 'mousedown'){
6482 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6484 E.stopPropagation(this.browserEvent);
6489 * Gets the key code for the event.
6492 getCharCode : function(){
6493 return this.charCode || this.keyCode;
6497 * Returns a normalized keyCode for the event.
6498 * @return {Number} The key code
6500 getKey : function(){
6501 var k = this.keyCode || this.charCode;
6502 return Roo.isSafari ? (safariKeys[k] || k) : k;
6506 * Gets the x coordinate of the event.
6509 getPageX : function(){
6514 * Gets the y coordinate of the event.
6517 getPageY : function(){
6522 * Gets the time of the event.
6525 getTime : function(){
6526 if(this.browserEvent){
6527 return E.getTime(this.browserEvent);
6533 * Gets the page coordinates of the event.
6534 * @return {Array} The xy values like [x, y]
6541 * Gets the target for the event.
6542 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6543 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6544 search as a number or element (defaults to 10 || document.body)
6545 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6546 * @return {HTMLelement}
6548 getTarget : function(selector, maxDepth, returnEl){
6549 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6552 * Gets the related target.
6553 * @return {HTMLElement}
6555 getRelatedTarget : function(){
6556 if(this.browserEvent){
6557 return E.getRelatedTarget(this.browserEvent);
6563 * Normalizes mouse wheel delta across browsers
6564 * @return {Number} The delta
6566 getWheelDelta : function(){
6567 var e = this.browserEvent;
6569 if(e.wheelDelta){ /* IE/Opera. */
6570 delta = e.wheelDelta/120;
6571 }else if(e.detail){ /* Mozilla case. */
6572 delta = -e.detail/3;
6578 * Returns true if the control, meta, shift or alt key was pressed during this event.
6581 hasModifier : function(){
6582 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6586 * Returns true if the target of this event equals el or is a child of el
6587 * @param {String/HTMLElement/Element} el
6588 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6591 within : function(el, related){
6592 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6593 return t && Roo.fly(el).contains(t);
6596 getPoint : function(){
6597 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6601 return new Roo.EventObjectImpl();
6606 * Ext JS Library 1.1.1
6607 * Copyright(c) 2006-2007, Ext JS, LLC.
6609 * Originally Released Under LGPL - original licence link has changed is not relivant.
6612 * <script type="text/javascript">
6616 // was in Composite Element!??!?!
6619 var D = Roo.lib.Dom;
6620 var E = Roo.lib.Event;
6621 var A = Roo.lib.Anim;
6623 // local style camelizing for speed
6625 var camelRe = /(-[a-z])/gi;
6626 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6627 var view = document.defaultView;
6630 * @class Roo.Element
6631 * Represents an Element in the DOM.<br><br>
6634 var el = Roo.get("my-div");
6637 var el = getEl("my-div");
6639 // or with a DOM element
6640 var el = Roo.get(myDivElement);
6642 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6643 * each call instead of constructing a new one.<br><br>
6644 * <b>Animations</b><br />
6645 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6646 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6648 Option Default Description
6649 --------- -------- ---------------------------------------------
6650 duration .35 The duration of the animation in seconds
6651 easing easeOut The YUI easing method
6652 callback none A function to execute when the anim completes
6653 scope this The scope (this) of the callback function
6655 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6656 * manipulate the animation. Here's an example:
6658 var el = Roo.get("my-div");
6663 // default animation
6664 el.setWidth(100, true);
6666 // animation with some options set
6673 // using the "anim" property to get the Anim object
6679 el.setWidth(100, opt);
6681 if(opt.anim.isAnimated()){
6685 * <b> Composite (Collections of) Elements</b><br />
6686 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6687 * @constructor Create a new Element directly.
6688 * @param {String/HTMLElement} element
6689 * @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).
6691 Roo.Element = function(element, forceNew){
6692 var dom = typeof element == "string" ?
6693 document.getElementById(element) : element;
6694 if(!dom){ // invalid id/element
6698 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6699 return Roo.Element.cache[id];
6709 * The DOM element ID
6712 this.id = id || Roo.id(dom);
6715 var El = Roo.Element;
6719 * The element's default display mode (defaults to "")
6722 originalDisplay : "",
6726 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6731 * Sets the element's visibility mode. When setVisible() is called it
6732 * will use this to determine whether to set the visibility or the display property.
6733 * @param visMode Element.VISIBILITY or Element.DISPLAY
6734 * @return {Roo.Element} this
6736 setVisibilityMode : function(visMode){
6737 this.visibilityMode = visMode;
6741 * Convenience method for setVisibilityMode(Element.DISPLAY)
6742 * @param {String} display (optional) What to set display to when visible
6743 * @return {Roo.Element} this
6745 enableDisplayMode : function(display){
6746 this.setVisibilityMode(El.DISPLAY);
6747 if(typeof display != "undefined") this.originalDisplay = display;
6752 * 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)
6753 * @param {String} selector The simple selector to test
6754 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6755 search as a number or element (defaults to 10 || document.body)
6756 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6757 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6759 findParent : function(simpleSelector, maxDepth, returnEl){
6760 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6761 maxDepth = maxDepth || 50;
6762 if(typeof maxDepth != "number"){
6763 stopEl = Roo.getDom(maxDepth);
6766 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6767 if(dq.is(p, simpleSelector)){
6768 return returnEl ? Roo.get(p) : p;
6778 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6779 * @param {String} selector The simple selector to test
6780 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6781 search as a number or element (defaults to 10 || document.body)
6782 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6783 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6785 findParentNode : function(simpleSelector, maxDepth, returnEl){
6786 var p = Roo.fly(this.dom.parentNode, '_internal');
6787 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6791 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6792 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6793 * @param {String} selector The simple selector to test
6794 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6795 search as a number or element (defaults to 10 || document.body)
6796 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6798 up : function(simpleSelector, maxDepth){
6799 return this.findParentNode(simpleSelector, maxDepth, true);
6805 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6806 * @param {String} selector The simple selector to test
6807 * @return {Boolean} True if this element matches the selector, else false
6809 is : function(simpleSelector){
6810 return Roo.DomQuery.is(this.dom, simpleSelector);
6814 * Perform animation on this element.
6815 * @param {Object} args The YUI animation control args
6816 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6817 * @param {Function} onComplete (optional) Function to call when animation completes
6818 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6819 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6820 * @return {Roo.Element} this
6822 animate : function(args, duration, onComplete, easing, animType){
6823 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6828 * @private Internal animation call
6830 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6831 animType = animType || 'run';
6833 var anim = Roo.lib.Anim[animType](
6835 (opt.duration || defaultDur) || .35,
6836 (opt.easing || defaultEase) || 'easeOut',
6838 Roo.callback(cb, this);
6839 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6847 // private legacy anim prep
6848 preanim : function(a, i){
6849 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6853 * Removes worthless text nodes
6854 * @param {Boolean} forceReclean (optional) By default the element
6855 * keeps track if it has been cleaned already so
6856 * you can call this over and over. However, if you update the element and
6857 * need to force a reclean, you can pass true.
6859 clean : function(forceReclean){
6860 if(this.isCleaned && forceReclean !== true){
6864 var d = this.dom, n = d.firstChild, ni = -1;
6866 var nx = n.nextSibling;
6867 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
6874 this.isCleaned = true;
6879 calcOffsetsTo : function(el){
6882 var restorePos = false;
6883 if(el.getStyle('position') == 'static'){
6884 el.position('relative');
6889 while(op && op != d && op.tagName != 'HTML'){
6892 op = op.offsetParent;
6895 el.position('static');
6901 * Scrolls this element into view within the passed container.
6902 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
6903 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
6904 * @return {Roo.Element} this
6906 scrollIntoView : function(container, hscroll){
6907 var c = Roo.getDom(container) || document.body;
6910 var o = this.calcOffsetsTo(c),
6913 b = t+el.offsetHeight,
6914 r = l+el.offsetWidth;
6916 var ch = c.clientHeight;
6917 var ct = parseInt(c.scrollTop, 10);
6918 var cl = parseInt(c.scrollLeft, 10);
6920 var cr = cl + c.clientWidth;
6928 if(hscroll !== false){
6932 c.scrollLeft = r-c.clientWidth;
6939 scrollChildIntoView : function(child, hscroll){
6940 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
6944 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
6945 * the new height may not be available immediately.
6946 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
6947 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
6948 * @param {Function} onComplete (optional) Function to call when animation completes
6949 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
6950 * @return {Roo.Element} this
6952 autoHeight : function(animate, duration, onComplete, easing){
6953 var oldHeight = this.getHeight();
6955 this.setHeight(1); // force clipping
6956 setTimeout(function(){
6957 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
6959 this.setHeight(height);
6961 if(typeof onComplete == "function"){
6965 this.setHeight(oldHeight); // restore original height
6966 this.setHeight(height, animate, duration, function(){
6968 if(typeof onComplete == "function") onComplete();
6969 }.createDelegate(this), easing);
6971 }.createDelegate(this), 0);
6976 * Returns true if this element is an ancestor of the passed element
6977 * @param {HTMLElement/String} el The element to check
6978 * @return {Boolean} True if this element is an ancestor of el, else false
6980 contains : function(el){
6981 if(!el){return false;}
6982 return D.isAncestor(this.dom, el.dom ? el.dom : el);
6986 * Checks whether the element is currently visible using both visibility and display properties.
6987 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
6988 * @return {Boolean} True if the element is currently visible, else false
6990 isVisible : function(deep) {
6991 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
6992 if(deep !== true || !vis){
6995 var p = this.dom.parentNode;
6996 while(p && p.tagName.toLowerCase() != "body"){
6997 if(!Roo.fly(p, '_isVisible').isVisible()){
7006 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7007 * @param {String} selector The CSS selector
7008 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7009 * @return {CompositeElement/CompositeElementLite} The composite element
7011 select : function(selector, unique){
7012 return El.select(selector, unique, this.dom);
7016 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7017 * @param {String} selector The CSS selector
7018 * @return {Array} An array of the matched nodes
7020 query : function(selector, unique){
7021 return Roo.DomQuery.select(selector, this.dom);
7025 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7026 * @param {String} selector The CSS selector
7027 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7028 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7030 child : function(selector, returnDom){
7031 var n = Roo.DomQuery.selectNode(selector, this.dom);
7032 return returnDom ? n : Roo.get(n);
7036 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7037 * @param {String} selector The CSS selector
7038 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7039 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7041 down : function(selector, returnDom){
7042 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7043 return returnDom ? n : Roo.get(n);
7047 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7048 * @param {String} group The group the DD object is member of
7049 * @param {Object} config The DD config object
7050 * @param {Object} overrides An object containing methods to override/implement on the DD object
7051 * @return {Roo.dd.DD} The DD object
7053 initDD : function(group, config, overrides){
7054 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7055 return Roo.apply(dd, overrides);
7059 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7060 * @param {String} group The group the DDProxy object is member of
7061 * @param {Object} config The DDProxy config object
7062 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7063 * @return {Roo.dd.DDProxy} The DDProxy object
7065 initDDProxy : function(group, config, overrides){
7066 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7067 return Roo.apply(dd, overrides);
7071 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7072 * @param {String} group The group the DDTarget object is member of
7073 * @param {Object} config The DDTarget config object
7074 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7075 * @return {Roo.dd.DDTarget} The DDTarget object
7077 initDDTarget : function(group, config, overrides){
7078 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7079 return Roo.apply(dd, overrides);
7083 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7084 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7085 * @param {Boolean} visible Whether the element is visible
7086 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7087 * @return {Roo.Element} this
7089 setVisible : function(visible, animate){
7091 if(this.visibilityMode == El.DISPLAY){
7092 this.setDisplayed(visible);
7095 this.dom.style.visibility = visible ? "visible" : "hidden";
7098 // closure for composites
7100 var visMode = this.visibilityMode;
7102 this.setOpacity(.01);
7103 this.setVisible(true);
7105 this.anim({opacity: { to: (visible?1:0) }},
7106 this.preanim(arguments, 1),
7107 null, .35, 'easeIn', function(){
7109 if(visMode == El.DISPLAY){
7110 dom.style.display = "none";
7112 dom.style.visibility = "hidden";
7114 Roo.get(dom).setOpacity(1);
7122 * Returns true if display is not "none"
7125 isDisplayed : function() {
7126 return this.getStyle("display") != "none";
7130 * Toggles the element's visibility or display, depending on visibility mode.
7131 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7132 * @return {Roo.Element} this
7134 toggle : function(animate){
7135 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7140 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7141 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7142 * @return {Roo.Element} this
7144 setDisplayed : function(value) {
7145 if(typeof value == "boolean"){
7146 value = value ? this.originalDisplay : "none";
7148 this.setStyle("display", value);
7153 * Tries to focus the element. Any exceptions are caught and ignored.
7154 * @return {Roo.Element} this
7156 focus : function() {
7164 * Tries to blur the element. Any exceptions are caught and ignored.
7165 * @return {Roo.Element} this
7175 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7176 * @param {String/Array} className The CSS class to add, or an array of classes
7177 * @return {Roo.Element} this
7179 addClass : function(className){
7180 if(className instanceof Array){
7181 for(var i = 0, len = className.length; i < len; i++) {
7182 this.addClass(className[i]);
7185 if(className && !this.hasClass(className)){
7186 this.dom.className = this.dom.className + " " + className;
7193 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7194 * @param {String/Array} className The CSS class to add, or an array of classes
7195 * @return {Roo.Element} this
7197 radioClass : function(className){
7198 var siblings = this.dom.parentNode.childNodes;
7199 for(var i = 0; i < siblings.length; i++) {
7200 var s = siblings[i];
7201 if(s.nodeType == 1){
7202 Roo.get(s).removeClass(className);
7205 this.addClass(className);
7210 * Removes one or more CSS classes from the element.
7211 * @param {String/Array} className The CSS class to remove, or an array of classes
7212 * @return {Roo.Element} this
7214 removeClass : function(className){
7215 if(!className || !this.dom.className){
7218 if(className instanceof Array){
7219 for(var i = 0, len = className.length; i < len; i++) {
7220 this.removeClass(className[i]);
7223 if(this.hasClass(className)){
7224 var re = this.classReCache[className];
7226 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7227 this.classReCache[className] = re;
7229 this.dom.className =
7230 this.dom.className.replace(re, " ");
7240 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7241 * @param {String} className The CSS class to toggle
7242 * @return {Roo.Element} this
7244 toggleClass : function(className){
7245 if(this.hasClass(className)){
7246 this.removeClass(className);
7248 this.addClass(className);
7254 * Checks if the specified CSS class exists on this element's DOM node.
7255 * @param {String} className The CSS class to check for
7256 * @return {Boolean} True if the class exists, else false
7258 hasClass : function(className){
7259 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7263 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7264 * @param {String} oldClassName The CSS class to replace
7265 * @param {String} newClassName The replacement CSS class
7266 * @return {Roo.Element} this
7268 replaceClass : function(oldClassName, newClassName){
7269 this.removeClass(oldClassName);
7270 this.addClass(newClassName);
7275 * Returns an object with properties matching the styles requested.
7276 * For example, el.getStyles('color', 'font-size', 'width') might return
7277 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7278 * @param {String} style1 A style name
7279 * @param {String} style2 A style name
7280 * @param {String} etc.
7281 * @return {Object} The style object
7283 getStyles : function(){
7284 var a = arguments, len = a.length, r = {};
7285 for(var i = 0; i < len; i++){
7286 r[a[i]] = this.getStyle(a[i]);
7292 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7293 * @param {String} property The style property whose value is returned.
7294 * @return {String} The current value of the style property for this element.
7296 getStyle : function(){
7297 return view && view.getComputedStyle ?
7299 var el = this.dom, v, cs, camel;
7300 if(prop == 'float'){
7303 if(el.style && (v = el.style[prop])){
7306 if(cs = view.getComputedStyle(el, "")){
7307 if(!(camel = propCache[prop])){
7308 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7315 var el = this.dom, v, cs, camel;
7316 if(prop == 'opacity'){
7317 if(typeof el.style.filter == 'string'){
7318 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7320 var fv = parseFloat(m[1]);
7322 return fv ? fv / 100 : 0;
7327 }else if(prop == 'float'){
7328 prop = "styleFloat";
7330 if(!(camel = propCache[prop])){
7331 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7333 if(v = el.style[camel]){
7336 if(cs = el.currentStyle){
7344 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7345 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7346 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7347 * @return {Roo.Element} this
7349 setStyle : function(prop, value){
7350 if(typeof prop == "string"){
7352 if(!(camel = propCache[prop])){
7353 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7355 if(camel == 'opacity') {
7356 this.setOpacity(value);
7358 this.dom.style[camel] = value;
7361 for(var style in prop){
7362 if(typeof prop[style] != "function"){
7363 this.setStyle(style, prop[style]);
7371 * More flexible version of {@link #setStyle} for setting style properties.
7372 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7373 * a function which returns such a specification.
7374 * @return {Roo.Element} this
7376 applyStyles : function(style){
7377 Roo.DomHelper.applyStyles(this.dom, style);
7382 * 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).
7383 * @return {Number} The X position of the element
7386 return D.getX(this.dom);
7390 * 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).
7391 * @return {Number} The Y position of the element
7394 return D.getY(this.dom);
7398 * 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).
7399 * @return {Array} The XY position of the element
7402 return D.getXY(this.dom);
7406 * 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).
7407 * @param {Number} The X position of the element
7408 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7409 * @return {Roo.Element} this
7411 setX : function(x, animate){
7413 D.setX(this.dom, x);
7415 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7421 * 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).
7422 * @param {Number} The Y position of the element
7423 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7424 * @return {Roo.Element} this
7426 setY : function(y, animate){
7428 D.setY(this.dom, y);
7430 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7436 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7437 * @param {String} left The left CSS property value
7438 * @return {Roo.Element} this
7440 setLeft : function(left){
7441 this.setStyle("left", this.addUnits(left));
7446 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7447 * @param {String} top The top CSS property value
7448 * @return {Roo.Element} this
7450 setTop : function(top){
7451 this.setStyle("top", this.addUnits(top));
7456 * Sets the element's CSS right style.
7457 * @param {String} right The right CSS property value
7458 * @return {Roo.Element} this
7460 setRight : function(right){
7461 this.setStyle("right", this.addUnits(right));
7466 * Sets the element's CSS bottom style.
7467 * @param {String} bottom The bottom CSS property value
7468 * @return {Roo.Element} this
7470 setBottom : function(bottom){
7471 this.setStyle("bottom", this.addUnits(bottom));
7476 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7477 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7478 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7479 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7480 * @return {Roo.Element} this
7482 setXY : function(pos, animate){
7484 D.setXY(this.dom, pos);
7486 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7492 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7493 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7494 * @param {Number} x X value for new position (coordinates are page-based)
7495 * @param {Number} y Y value for new position (coordinates are page-based)
7496 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7497 * @return {Roo.Element} this
7499 setLocation : function(x, y, animate){
7500 this.setXY([x, y], this.preanim(arguments, 2));
7505 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7506 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7507 * @param {Number} x X value for new position (coordinates are page-based)
7508 * @param {Number} y Y value for new position (coordinates are page-based)
7509 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7510 * @return {Roo.Element} this
7512 moveTo : function(x, y, animate){
7513 this.setXY([x, y], this.preanim(arguments, 2));
7518 * Returns the region of the given element.
7519 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7520 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7522 getRegion : function(){
7523 return D.getRegion(this.dom);
7527 * Returns the offset height of the element
7528 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7529 * @return {Number} The element's height
7531 getHeight : function(contentHeight){
7532 var h = this.dom.offsetHeight || 0;
7533 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7537 * Returns the offset width of the element
7538 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7539 * @return {Number} The element's width
7541 getWidth : function(contentWidth){
7542 var w = this.dom.offsetWidth || 0;
7543 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7547 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7548 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7549 * if a height has not been set using CSS.
7552 getComputedHeight : function(){
7553 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7555 h = parseInt(this.getStyle('height'), 10) || 0;
7556 if(!this.isBorderBox()){
7557 h += this.getFrameWidth('tb');
7564 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7565 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7566 * if a width has not been set using CSS.
7569 getComputedWidth : function(){
7570 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7572 w = parseInt(this.getStyle('width'), 10) || 0;
7573 if(!this.isBorderBox()){
7574 w += this.getFrameWidth('lr');
7581 * Returns the size of the element.
7582 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7583 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7585 getSize : function(contentSize){
7586 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7590 * Returns the width and height of the viewport.
7591 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7593 getViewSize : function(){
7594 var d = this.dom, doc = document, aw = 0, ah = 0;
7595 if(d == doc || d == doc.body){
7596 return {width : D.getViewWidth(), height: D.getViewHeight()};
7599 width : d.clientWidth,
7600 height: d.clientHeight
7606 * Returns the value of the "value" attribute
7607 * @param {Boolean} asNumber true to parse the value as a number
7608 * @return {String/Number}
7610 getValue : function(asNumber){
7611 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7615 adjustWidth : function(width){
7616 if(typeof width == "number"){
7617 if(this.autoBoxAdjust && !this.isBorderBox()){
7618 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7628 adjustHeight : function(height){
7629 if(typeof height == "number"){
7630 if(this.autoBoxAdjust && !this.isBorderBox()){
7631 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7641 * Set the width of the element
7642 * @param {Number} width The new width
7643 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7644 * @return {Roo.Element} this
7646 setWidth : function(width, animate){
7647 width = this.adjustWidth(width);
7649 this.dom.style.width = this.addUnits(width);
7651 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7657 * Set the height of the element
7658 * @param {Number} height The new height
7659 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7660 * @return {Roo.Element} this
7662 setHeight : function(height, animate){
7663 height = this.adjustHeight(height);
7665 this.dom.style.height = this.addUnits(height);
7667 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7673 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7674 * @param {Number} width The new width
7675 * @param {Number} height The new height
7676 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7677 * @return {Roo.Element} this
7679 setSize : function(width, height, animate){
7680 if(typeof width == "object"){ // in case of object from getSize()
7681 height = width.height; width = width.width;
7683 width = this.adjustWidth(width); height = this.adjustHeight(height);
7685 this.dom.style.width = this.addUnits(width);
7686 this.dom.style.height = this.addUnits(height);
7688 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7694 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7695 * @param {Number} x X value for new position (coordinates are page-based)
7696 * @param {Number} y Y value for new position (coordinates are page-based)
7697 * @param {Number} width The new width
7698 * @param {Number} height The new height
7699 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7700 * @return {Roo.Element} this
7702 setBounds : function(x, y, width, height, animate){
7704 this.setSize(width, height);
7705 this.setLocation(x, y);
7707 width = this.adjustWidth(width); height = this.adjustHeight(height);
7708 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7709 this.preanim(arguments, 4), 'motion');
7715 * 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.
7716 * @param {Roo.lib.Region} region The region to fill
7717 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7718 * @return {Roo.Element} this
7720 setRegion : function(region, animate){
7721 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7726 * Appends an event handler
7728 * @param {String} eventName The type of event to append
7729 * @param {Function} fn The method the event invokes
7730 * @param {Object} scope (optional) The scope (this object) of the fn
7731 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7733 addListener : function(eventName, fn, scope, options){
7734 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7738 * Removes an event handler from this element
7739 * @param {String} eventName the type of event to remove
7740 * @param {Function} fn the method the event invokes
7741 * @return {Roo.Element} this
7743 removeListener : function(eventName, fn){
7744 Roo.EventManager.removeListener(this.dom, eventName, fn);
7749 * Removes all previous added listeners from this element
7750 * @return {Roo.Element} this
7752 removeAllListeners : function(){
7753 E.purgeElement(this.dom);
7757 relayEvent : function(eventName, observable){
7758 this.on(eventName, function(e){
7759 observable.fireEvent(eventName, e);
7764 * Set the opacity of the element
7765 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7766 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7767 * @return {Roo.Element} this
7769 setOpacity : function(opacity, animate){
7771 var s = this.dom.style;
7774 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7775 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7777 s.opacity = opacity;
7780 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7786 * Gets the left X coordinate
7787 * @param {Boolean} local True to get the local css position instead of page coordinate
7790 getLeft : function(local){
7794 return parseInt(this.getStyle("left"), 10) || 0;
7799 * Gets the right X coordinate of the element (element X position + element width)
7800 * @param {Boolean} local True to get the local css position instead of page coordinate
7803 getRight : function(local){
7805 return this.getX() + this.getWidth();
7807 return (this.getLeft(true) + this.getWidth()) || 0;
7812 * Gets the top Y coordinate
7813 * @param {Boolean} local True to get the local css position instead of page coordinate
7816 getTop : function(local) {
7820 return parseInt(this.getStyle("top"), 10) || 0;
7825 * Gets the bottom Y coordinate of the element (element Y position + element height)
7826 * @param {Boolean} local True to get the local css position instead of page coordinate
7829 getBottom : function(local){
7831 return this.getY() + this.getHeight();
7833 return (this.getTop(true) + this.getHeight()) || 0;
7838 * Initializes positioning on this element. If a desired position is not passed, it will make the
7839 * the element positioned relative IF it is not already positioned.
7840 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7841 * @param {Number} zIndex (optional) The zIndex to apply
7842 * @param {Number} x (optional) Set the page X position
7843 * @param {Number} y (optional) Set the page Y position
7845 position : function(pos, zIndex, x, y){
7847 if(this.getStyle('position') == 'static'){
7848 this.setStyle('position', 'relative');
7851 this.setStyle("position", pos);
7854 this.setStyle("z-index", zIndex);
7856 if(x !== undefined && y !== undefined){
7858 }else if(x !== undefined){
7860 }else if(y !== undefined){
7866 * Clear positioning back to the default when the document was loaded
7867 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7868 * @return {Roo.Element} this
7870 clearPositioning : function(value){
7878 "position" : "static"
7884 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7885 * snapshot before performing an update and then restoring the element.
7888 getPositioning : function(){
7889 var l = this.getStyle("left");
7890 var t = this.getStyle("top");
7892 "position" : this.getStyle("position"),
7894 "right" : l ? "" : this.getStyle("right"),
7896 "bottom" : t ? "" : this.getStyle("bottom"),
7897 "z-index" : this.getStyle("z-index")
7902 * Gets the width of the border(s) for the specified side(s)
7903 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7904 * passing lr would get the border (l)eft width + the border (r)ight width.
7905 * @return {Number} The width of the sides passed added together
7907 getBorderWidth : function(side){
7908 return this.addStyles(side, El.borders);
7912 * Gets the width of the padding(s) for the specified side(s)
7913 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7914 * passing lr would get the padding (l)eft + the padding (r)ight.
7915 * @return {Number} The padding of the sides passed added together
7917 getPadding : function(side){
7918 return this.addStyles(side, El.paddings);
7922 * Set positioning with an object returned by getPositioning().
7923 * @param {Object} posCfg
7924 * @return {Roo.Element} this
7926 setPositioning : function(pc){
7927 this.applyStyles(pc);
7928 if(pc.right == "auto"){
7929 this.dom.style.right = "";
7931 if(pc.bottom == "auto"){
7932 this.dom.style.bottom = "";
7938 fixDisplay : function(){
7939 if(this.getStyle("display") == "none"){
7940 this.setStyle("visibility", "hidden");
7941 this.setStyle("display", this.originalDisplay); // first try reverting to default
7942 if(this.getStyle("display") == "none"){ // if that fails, default to block
7943 this.setStyle("display", "block");
7949 * Quick set left and top adding default units
7950 * @param {String} left The left CSS property value
7951 * @param {String} top The top CSS property value
7952 * @return {Roo.Element} this
7954 setLeftTop : function(left, top){
7955 this.dom.style.left = this.addUnits(left);
7956 this.dom.style.top = this.addUnits(top);
7961 * Move this element relative to its current position.
7962 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
7963 * @param {Number} distance How far to move the element in pixels
7964 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7965 * @return {Roo.Element} this
7967 move : function(direction, distance, animate){
7968 var xy = this.getXY();
7969 direction = direction.toLowerCase();
7973 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
7977 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
7982 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
7987 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
7994 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
7995 * @return {Roo.Element} this
7998 if(!this.isClipped){
7999 this.isClipped = true;
8000 this.originalClip = {
8001 "o": this.getStyle("overflow"),
8002 "x": this.getStyle("overflow-x"),
8003 "y": this.getStyle("overflow-y")
8005 this.setStyle("overflow", "hidden");
8006 this.setStyle("overflow-x", "hidden");
8007 this.setStyle("overflow-y", "hidden");
8013 * Return clipping (overflow) to original clipping before clip() was called
8014 * @return {Roo.Element} this
8016 unclip : function(){
8018 this.isClipped = false;
8019 var o = this.originalClip;
8020 if(o.o){this.setStyle("overflow", o.o);}
8021 if(o.x){this.setStyle("overflow-x", o.x);}
8022 if(o.y){this.setStyle("overflow-y", o.y);}
8029 * Gets the x,y coordinates specified by the anchor position on the element.
8030 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8031 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8032 * {width: (target width), height: (target height)} (defaults to the element's current size)
8033 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8034 * @return {Array} [x, y] An array containing the element's x and y coordinates
8036 getAnchorXY : function(anchor, local, s){
8037 //Passing a different size is useful for pre-calculating anchors,
8038 //especially for anchored animations that change the el size.
8040 var w, h, vp = false;
8043 if(d == document.body || d == document){
8045 w = D.getViewWidth(); h = D.getViewHeight();
8047 w = this.getWidth(); h = this.getHeight();
8050 w = s.width; h = s.height;
8052 var x = 0, y = 0, r = Math.round;
8053 switch((anchor || "tl").toLowerCase()){
8095 var sc = this.getScroll();
8096 return [x + sc.left, y + sc.top];
8098 //Add the element's offset xy
8099 var o = this.getXY();
8100 return [x+o[0], y+o[1]];
8104 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8105 * supported position values.
8106 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8107 * @param {String} position The position to align to.
8108 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8109 * @return {Array} [x, y]
8111 getAlignToXY : function(el, p, o){
8115 throw "Element.alignTo with an element that doesn't exist";
8117 var c = false; //constrain to viewport
8118 var p1 = "", p2 = "";
8125 }else if(p.indexOf("-") == -1){
8128 p = p.toLowerCase();
8129 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8131 throw "Element.alignTo with an invalid alignment " + p;
8133 p1 = m[1]; p2 = m[2]; c = !!m[3];
8135 //Subtract the aligned el's internal xy from the target's offset xy
8136 //plus custom offset to get the aligned el's new offset xy
8137 var a1 = this.getAnchorXY(p1, true);
8138 var a2 = el.getAnchorXY(p2, false);
8139 var x = a2[0] - a1[0] + o[0];
8140 var y = a2[1] - a1[1] + o[1];
8142 //constrain the aligned el to viewport if necessary
8143 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8144 // 5px of margin for ie
8145 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8147 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8148 //perpendicular to the vp border, allow the aligned el to slide on that border,
8149 //otherwise swap the aligned el to the opposite border of the target.
8150 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8151 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8152 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8153 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8156 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8157 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8159 if((x+w) > dw + scrollX){
8160 x = swapX ? r.left-w : dw+scrollX-w;
8163 x = swapX ? r.right : scrollX;
8165 if((y+h) > dh + scrollY){
8166 y = swapY ? r.top-h : dh+scrollY-h;
8169 y = swapY ? r.bottom : scrollY;
8176 getConstrainToXY : function(){
8177 var os = {top:0, left:0, bottom:0, right: 0};
8179 return function(el, local, offsets, proposedXY){
8181 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8183 var vw, vh, vx = 0, vy = 0;
8184 if(el.dom == document.body || el.dom == document){
8185 vw = Roo.lib.Dom.getViewWidth();
8186 vh = Roo.lib.Dom.getViewHeight();
8188 vw = el.dom.clientWidth;
8189 vh = el.dom.clientHeight;
8191 var vxy = el.getXY();
8197 var s = el.getScroll();
8199 vx += offsets.left + s.left;
8200 vy += offsets.top + s.top;
8202 vw -= offsets.right;
8203 vh -= offsets.bottom;
8208 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8209 var x = xy[0], y = xy[1];
8210 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8212 // only move it if it needs it
8215 // first validate right/bottom
8224 // then make sure top/left isn't negative
8233 return moved ? [x, y] : false;
8238 adjustForConstraints : function(xy, parent, offsets){
8239 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8243 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8244 * document it aligns it to the viewport.
8245 * The position parameter is optional, and can be specified in any one of the following formats:
8247 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8248 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8249 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8250 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8251 * <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
8252 * element's anchor point, and the second value is used as the target's anchor point.</li>
8254 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8255 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8256 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8257 * that specified in order to enforce the viewport constraints.
8258 * Following are all of the supported anchor positions:
8261 ----- -----------------------------
8262 tl The top left corner (default)
8263 t The center of the top edge
8264 tr The top right corner
8265 l The center of the left edge
8266 c In the center of the element
8267 r The center of the right edge
8268 bl The bottom left corner
8269 b The center of the bottom edge
8270 br The bottom right corner
8274 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8275 el.alignTo("other-el");
8277 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8278 el.alignTo("other-el", "tr?");
8280 // align the bottom right corner of el with the center left edge of other-el
8281 el.alignTo("other-el", "br-l?");
8283 // align the center of el with the bottom left corner of other-el and
8284 // adjust the x position by -6 pixels (and the y position by 0)
8285 el.alignTo("other-el", "c-bl", [-6, 0]);
8287 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8288 * @param {String} position The position to align to.
8289 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8290 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8291 * @return {Roo.Element} this
8293 alignTo : function(element, position, offsets, animate){
8294 var xy = this.getAlignToXY(element, position, offsets);
8295 this.setXY(xy, this.preanim(arguments, 3));
8300 * Anchors an element to another element and realigns it when the window is resized.
8301 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8302 * @param {String} position The position to align to.
8303 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8304 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8305 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8306 * is a number, it is used as the buffer delay (defaults to 50ms).
8307 * @param {Function} callback The function to call after the animation finishes
8308 * @return {Roo.Element} this
8310 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8311 var action = function(){
8312 this.alignTo(el, alignment, offsets, animate);
8313 Roo.callback(callback, this);
8315 Roo.EventManager.onWindowResize(action, this);
8316 var tm = typeof monitorScroll;
8317 if(tm != 'undefined'){
8318 Roo.EventManager.on(window, 'scroll', action, this,
8319 {buffer: tm == 'number' ? monitorScroll : 50});
8321 action.call(this); // align immediately
8325 * Clears any opacity settings from this element. Required in some cases for IE.
8326 * @return {Roo.Element} this
8328 clearOpacity : function(){
8329 if (window.ActiveXObject) {
8330 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8331 this.dom.style.filter = "";
8334 this.dom.style.opacity = "";
8335 this.dom.style["-moz-opacity"] = "";
8336 this.dom.style["-khtml-opacity"] = "";
8342 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8343 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8344 * @return {Roo.Element} this
8346 hide : function(animate){
8347 this.setVisible(false, this.preanim(arguments, 0));
8352 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8353 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8354 * @return {Roo.Element} this
8356 show : function(animate){
8357 this.setVisible(true, this.preanim(arguments, 0));
8362 * @private Test if size has a unit, otherwise appends the default
8364 addUnits : function(size){
8365 return Roo.Element.addUnits(size, this.defaultUnit);
8369 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8370 * @return {Roo.Element} this
8372 beginMeasure : function(){
8374 if(el.offsetWidth || el.offsetHeight){
8375 return this; // offsets work already
8378 var p = this.dom, b = document.body; // start with this element
8379 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8380 var pe = Roo.get(p);
8381 if(pe.getStyle('display') == 'none'){
8382 changed.push({el: p, visibility: pe.getStyle("visibility")});
8383 p.style.visibility = "hidden";
8384 p.style.display = "block";
8388 this._measureChanged = changed;
8394 * Restores displays to before beginMeasure was called
8395 * @return {Roo.Element} this
8397 endMeasure : function(){
8398 var changed = this._measureChanged;
8400 for(var i = 0, len = changed.length; i < len; i++) {
8402 r.el.style.visibility = r.visibility;
8403 r.el.style.display = "none";
8405 this._measureChanged = null;
8411 * Update the innerHTML of this element, optionally searching for and processing scripts
8412 * @param {String} html The new HTML
8413 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8414 * @param {Function} callback For async script loading you can be noticed when the update completes
8415 * @return {Roo.Element} this
8417 update : function(html, loadScripts, callback){
8418 if(typeof html == "undefined"){
8421 if(loadScripts !== true){
8422 this.dom.innerHTML = html;
8423 if(typeof callback == "function"){
8431 html += '<span id="' + id + '"></span>';
8433 E.onAvailable(id, function(){
8434 var hd = document.getElementsByTagName("head")[0];
8435 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8436 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8437 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8440 while(match = re.exec(html)){
8441 var attrs = match[1];
8442 var srcMatch = attrs ? attrs.match(srcRe) : false;
8443 if(srcMatch && srcMatch[2]){
8444 var s = document.createElement("script");
8445 s.src = srcMatch[2];
8446 var typeMatch = attrs.match(typeRe);
8447 if(typeMatch && typeMatch[2]){
8448 s.type = typeMatch[2];
8451 }else if(match[2] && match[2].length > 0){
8452 if(window.execScript) {
8453 window.execScript(match[2]);
8461 window.eval(match[2]);
8465 var el = document.getElementById(id);
8466 if(el){el.parentNode.removeChild(el);}
8467 if(typeof callback == "function"){
8471 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8476 * Direct access to the UpdateManager update() method (takes the same parameters).
8477 * @param {String/Function} url The url for this request or a function to call to get the url
8478 * @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}
8479 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8480 * @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.
8481 * @return {Roo.Element} this
8484 var um = this.getUpdateManager();
8485 um.update.apply(um, arguments);
8490 * Gets this element's UpdateManager
8491 * @return {Roo.UpdateManager} The UpdateManager
8493 getUpdateManager : function(){
8494 if(!this.updateManager){
8495 this.updateManager = new Roo.UpdateManager(this);
8497 return this.updateManager;
8501 * Disables text selection for this element (normalized across browsers)
8502 * @return {Roo.Element} this
8504 unselectable : function(){
8505 this.dom.unselectable = "on";
8506 this.swallowEvent("selectstart", true);
8507 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8508 this.addClass("x-unselectable");
8513 * Calculates the x, y to center this element on the screen
8514 * @return {Array} The x, y values [x, y]
8516 getCenterXY : function(){
8517 return this.getAlignToXY(document, 'c-c');
8521 * Centers the Element in either the viewport, or another Element.
8522 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8524 center : function(centerIn){
8525 this.alignTo(centerIn || document, 'c-c');
8530 * Tests various css rules/browsers to determine if this element uses a border box
8533 isBorderBox : function(){
8534 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8538 * Return a box {x, y, width, height} that can be used to set another elements
8539 * size/location to match this element.
8540 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8541 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8542 * @return {Object} box An object in the format {x, y, width, height}
8544 getBox : function(contentBox, local){
8549 var left = parseInt(this.getStyle("left"), 10) || 0;
8550 var top = parseInt(this.getStyle("top"), 10) || 0;
8553 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8555 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8557 var l = this.getBorderWidth("l")+this.getPadding("l");
8558 var r = this.getBorderWidth("r")+this.getPadding("r");
8559 var t = this.getBorderWidth("t")+this.getPadding("t");
8560 var b = this.getBorderWidth("b")+this.getPadding("b");
8561 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)};
8563 bx.right = bx.x + bx.width;
8564 bx.bottom = bx.y + bx.height;
8569 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8570 for more information about the sides.
8571 * @param {String} sides
8574 getFrameWidth : function(sides, onlyContentBox){
8575 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8579 * 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.
8580 * @param {Object} box The box to fill {x, y, width, height}
8581 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8582 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8583 * @return {Roo.Element} this
8585 setBox : function(box, adjust, animate){
8586 var w = box.width, h = box.height;
8587 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8588 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8589 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8591 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8596 * Forces the browser to repaint this element
8597 * @return {Roo.Element} this
8599 repaint : function(){
8601 this.addClass("x-repaint");
8602 setTimeout(function(){
8603 Roo.get(dom).removeClass("x-repaint");
8609 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8610 * then it returns the calculated width of the sides (see getPadding)
8611 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8612 * @return {Object/Number}
8614 getMargins : function(side){
8617 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8618 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8619 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8620 right: parseInt(this.getStyle("margin-right"), 10) || 0
8623 return this.addStyles(side, El.margins);
8628 addStyles : function(sides, styles){
8630 for(var i = 0, len = sides.length; i < len; i++){
8631 v = this.getStyle(styles[sides.charAt(i)]);
8633 w = parseInt(v, 10);
8641 * Creates a proxy element of this element
8642 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8643 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8644 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8645 * @return {Roo.Element} The new proxy element
8647 createProxy : function(config, renderTo, matchBox){
8649 renderTo = Roo.getDom(renderTo);
8651 renderTo = document.body;
8653 config = typeof config == "object" ?
8654 config : {tag : "div", cls: config};
8655 var proxy = Roo.DomHelper.append(renderTo, config, true);
8657 proxy.setBox(this.getBox());
8663 * Puts a mask over this element to disable user interaction. Requires core.css.
8664 * This method can only be applied to elements which accept child nodes.
8665 * @param {String} msg (optional) A message to display in the mask
8666 * @param {String} msgCls (optional) A css class to apply to the msg element
8667 * @return {Element} The mask element
8669 mask : function(msg, msgCls){
8670 if(this.getStyle("position") == "static"){
8671 this.setStyle("position", "relative");
8674 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8676 this.addClass("x-masked");
8677 this._mask.setDisplayed(true);
8678 if(typeof msg == 'string'){
8680 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8682 var mm = this._maskMsg;
8683 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8684 mm.dom.firstChild.innerHTML = msg;
8685 mm.setDisplayed(true);
8688 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8689 this._mask.setHeight(this.getHeight());
8695 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8696 * it is cached for reuse.
8698 unmask : function(removeEl){
8700 if(removeEl === true){
8701 this._mask.remove();
8704 this._maskMsg.remove();
8705 delete this._maskMsg;
8708 this._mask.setDisplayed(false);
8710 this._maskMsg.setDisplayed(false);
8714 this.removeClass("x-masked");
8718 * Returns true if this element is masked
8721 isMasked : function(){
8722 return this._mask && this._mask.isVisible();
8726 * Creates an iframe shim for this element to keep selects and other windowed objects from
8728 * @return {Roo.Element} The new shim element
8730 createShim : function(){
8731 var el = document.createElement('iframe');
8732 el.frameBorder = 'no';
8733 el.className = 'roo-shim';
8734 if(Roo.isIE && Roo.isSecure){
8735 el.src = Roo.SSL_SECURE_URL;
8737 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8738 shim.autoBoxAdjust = false;
8743 * Removes this element from the DOM and deletes it from the cache
8745 remove : function(){
8746 if(this.dom.parentNode){
8747 this.dom.parentNode.removeChild(this.dom);
8749 delete El.cache[this.dom.id];
8753 * Sets up event handlers to add and remove a css class when the mouse is over this element
8754 * @param {String} className
8755 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8756 * mouseout events for children elements
8757 * @return {Roo.Element} this
8759 addClassOnOver : function(className, preventFlicker){
8760 this.on("mouseover", function(){
8761 Roo.fly(this, '_internal').addClass(className);
8763 var removeFn = function(e){
8764 if(preventFlicker !== true || !e.within(this, true)){
8765 Roo.fly(this, '_internal').removeClass(className);
8768 this.on("mouseout", removeFn, this.dom);
8773 * Sets up event handlers to add and remove a css class when this element has the focus
8774 * @param {String} className
8775 * @return {Roo.Element} this
8777 addClassOnFocus : function(className){
8778 this.on("focus", function(){
8779 Roo.fly(this, '_internal').addClass(className);
8781 this.on("blur", function(){
8782 Roo.fly(this, '_internal').removeClass(className);
8787 * 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)
8788 * @param {String} className
8789 * @return {Roo.Element} this
8791 addClassOnClick : function(className){
8793 this.on("mousedown", function(){
8794 Roo.fly(dom, '_internal').addClass(className);
8795 var d = Roo.get(document);
8796 var fn = function(){
8797 Roo.fly(dom, '_internal').removeClass(className);
8798 d.removeListener("mouseup", fn);
8800 d.on("mouseup", fn);
8806 * Stops the specified event from bubbling and optionally prevents the default action
8807 * @param {String} eventName
8808 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8809 * @return {Roo.Element} this
8811 swallowEvent : function(eventName, preventDefault){
8812 var fn = function(e){
8813 e.stopPropagation();
8818 if(eventName instanceof Array){
8819 for(var i = 0, len = eventName.length; i < len; i++){
8820 this.on(eventName[i], fn);
8824 this.on(eventName, fn);
8831 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8834 * Sizes this element to its parent element's dimensions performing
8835 * neccessary box adjustments.
8836 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8837 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8838 * @return {Roo.Element} this
8840 fitToParent : function(monitorResize, targetParent) {
8841 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8842 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8843 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8846 var p = Roo.get(targetParent || this.dom.parentNode);
8847 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8848 if (monitorResize === true) {
8849 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8850 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8856 * Gets the next sibling, skipping text nodes
8857 * @return {HTMLElement} The next sibling or null
8859 getNextSibling : function(){
8860 var n = this.dom.nextSibling;
8861 while(n && n.nodeType != 1){
8868 * Gets the previous sibling, skipping text nodes
8869 * @return {HTMLElement} The previous sibling or null
8871 getPrevSibling : function(){
8872 var n = this.dom.previousSibling;
8873 while(n && n.nodeType != 1){
8874 n = n.previousSibling;
8881 * Appends the passed element(s) to this element
8882 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8883 * @return {Roo.Element} this
8885 appendChild: function(el){
8892 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8893 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8894 * automatically generated with the specified attributes.
8895 * @param {HTMLElement} insertBefore (optional) a child element of this element
8896 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8897 * @return {Roo.Element} The new child element
8899 createChild: function(config, insertBefore, returnDom){
8900 config = config || {tag:'div'};
8902 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8904 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8908 * Appends this element to the passed element
8909 * @param {String/HTMLElement/Element} el The new parent element
8910 * @return {Roo.Element} this
8912 appendTo: function(el){
8913 el = Roo.getDom(el);
8914 el.appendChild(this.dom);
8919 * Inserts this element before the passed element in the DOM
8920 * @param {String/HTMLElement/Element} el The element to insert before
8921 * @return {Roo.Element} this
8923 insertBefore: function(el){
8924 el = Roo.getDom(el);
8925 el.parentNode.insertBefore(this.dom, el);
8930 * Inserts this element after the passed element in the DOM
8931 * @param {String/HTMLElement/Element} el The element to insert after
8932 * @return {Roo.Element} this
8934 insertAfter: function(el){
8935 el = Roo.getDom(el);
8936 el.parentNode.insertBefore(this.dom, el.nextSibling);
8941 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
8942 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8943 * @return {Roo.Element} The new child
8945 insertFirst: function(el, returnDom){
8947 if(typeof el == 'object' && !el.nodeType){ // dh config
8948 return this.createChild(el, this.dom.firstChild, returnDom);
8950 el = Roo.getDom(el);
8951 this.dom.insertBefore(el, this.dom.firstChild);
8952 return !returnDom ? Roo.get(el) : el;
8957 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
8958 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8959 * @param {String} where (optional) 'before' or 'after' defaults to before
8960 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8961 * @return {Roo.Element} the inserted Element
8963 insertSibling: function(el, where, returnDom){
8964 where = where ? where.toLowerCase() : 'before';
8966 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
8968 if(typeof el == 'object' && !el.nodeType){ // dh config
8969 if(where == 'after' && !this.dom.nextSibling){
8970 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
8972 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
8976 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
8977 where == 'before' ? this.dom : this.dom.nextSibling);
8986 * Creates and wraps this element with another element
8987 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
8988 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8989 * @return {HTMLElement/Element} The newly created wrapper element
8991 wrap: function(config, returnDom){
8993 config = {tag: "div"};
8995 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
8996 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9001 * Replaces the passed element with this element
9002 * @param {String/HTMLElement/Element} el The element to replace
9003 * @return {Roo.Element} this
9005 replace: function(el){
9007 this.insertBefore(el);
9013 * Inserts an html fragment into this element
9014 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9015 * @param {String} html The HTML fragment
9016 * @param {Boolean} returnEl True to return an Roo.Element
9017 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9019 insertHtml : function(where, html, returnEl){
9020 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9021 return returnEl ? Roo.get(el) : el;
9025 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9026 * @param {Object} o The object with the attributes
9027 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9028 * @return {Roo.Element} this
9030 set : function(o, useSet){
9032 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9034 if(attr == "style" || typeof o[attr] == "function") continue;
9036 el.className = o["cls"];
9038 if(useSet) el.setAttribute(attr, o[attr]);
9039 else el[attr] = o[attr];
9043 Roo.DomHelper.applyStyles(el, o.style);
9049 * Convenience method for constructing a KeyMap
9050 * @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:
9051 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9052 * @param {Function} fn The function to call
9053 * @param {Object} scope (optional) The scope of the function
9054 * @return {Roo.KeyMap} The KeyMap created
9056 addKeyListener : function(key, fn, scope){
9058 if(typeof key != "object" || key instanceof Array){
9074 return new Roo.KeyMap(this, config);
9078 * Creates a KeyMap for this element
9079 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9080 * @return {Roo.KeyMap} The KeyMap created
9082 addKeyMap : function(config){
9083 return new Roo.KeyMap(this, config);
9087 * Returns true if this element is scrollable.
9090 isScrollable : function(){
9092 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9096 * 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().
9097 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9098 * @param {Number} value The new scroll value
9099 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9100 * @return {Element} this
9103 scrollTo : function(side, value, animate){
9104 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9106 this.dom[prop] = value;
9108 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9109 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9115 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9116 * within this element's scrollable range.
9117 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9118 * @param {Number} distance How far to scroll the element in pixels
9119 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9120 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9121 * was scrolled as far as it could go.
9123 scroll : function(direction, distance, animate){
9124 if(!this.isScrollable()){
9128 var l = el.scrollLeft, t = el.scrollTop;
9129 var w = el.scrollWidth, h = el.scrollHeight;
9130 var cw = el.clientWidth, ch = el.clientHeight;
9131 direction = direction.toLowerCase();
9132 var scrolled = false;
9133 var a = this.preanim(arguments, 2);
9138 var v = Math.min(l + distance, w-cw);
9139 this.scrollTo("left", v, a);
9146 var v = Math.max(l - distance, 0);
9147 this.scrollTo("left", v, a);
9155 var v = Math.max(t - distance, 0);
9156 this.scrollTo("top", v, a);
9164 var v = Math.min(t + distance, h-ch);
9165 this.scrollTo("top", v, a);
9174 * Translates the passed page coordinates into left/top css values for this element
9175 * @param {Number/Array} x The page x or an array containing [x, y]
9176 * @param {Number} y The page y
9177 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9179 translatePoints : function(x, y){
9180 if(typeof x == 'object' || x instanceof Array){
9183 var p = this.getStyle('position');
9184 var o = this.getXY();
9186 var l = parseInt(this.getStyle('left'), 10);
9187 var t = parseInt(this.getStyle('top'), 10);
9190 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9193 t = (p == "relative") ? 0 : this.dom.offsetTop;
9196 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9200 * Returns the current scroll position of the element.
9201 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9203 getScroll : function(){
9204 var d = this.dom, doc = document;
9205 if(d == doc || d == doc.body){
9206 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9207 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9208 return {left: l, top: t};
9210 return {left: d.scrollLeft, top: d.scrollTop};
9215 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9216 * are convert to standard 6 digit hex color.
9217 * @param {String} attr The css attribute
9218 * @param {String} defaultValue The default value to use when a valid color isn't found
9219 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9222 getColor : function(attr, defaultValue, prefix){
9223 var v = this.getStyle(attr);
9224 if(!v || v == "transparent" || v == "inherit") {
9225 return defaultValue;
9227 var color = typeof prefix == "undefined" ? "#" : prefix;
9228 if(v.substr(0, 4) == "rgb("){
9229 var rvs = v.slice(4, v.length -1).split(",");
9230 for(var i = 0; i < 3; i++){
9231 var h = parseInt(rvs[i]).toString(16);
9238 if(v.substr(0, 1) == "#"){
9240 for(var i = 1; i < 4; i++){
9241 var c = v.charAt(i);
9244 }else if(v.length == 7){
9245 color += v.substr(1);
9249 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9253 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9254 * gradient background, rounded corners and a 4-way shadow.
9255 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9256 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9257 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9258 * @return {Roo.Element} this
9260 boxWrap : function(cls){
9261 cls = cls || 'x-box';
9262 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9263 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9268 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9269 * @param {String} namespace The namespace in which to look for the attribute
9270 * @param {String} name The attribute name
9271 * @return {String} The attribute value
9273 getAttributeNS : Roo.isIE ? function(ns, name){
9275 var type = typeof d[ns+":"+name];
9276 if(type != 'undefined' && type != 'unknown'){
9277 return d[ns+":"+name];
9280 } : function(ns, name){
9282 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9286 var ep = El.prototype;
9289 * Appends an event handler (Shorthand for addListener)
9290 * @param {String} eventName The type of event to append
9291 * @param {Function} fn The method the event invokes
9292 * @param {Object} scope (optional) The scope (this object) of the fn
9293 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9296 ep.on = ep.addListener;
9298 ep.mon = ep.addListener;
9301 * Removes an event handler from this element (shorthand for removeListener)
9302 * @param {String} eventName the type of event to remove
9303 * @param {Function} fn the method the event invokes
9304 * @return {Roo.Element} this
9307 ep.un = ep.removeListener;
9310 * true to automatically adjust width and height settings for box-model issues (default to true)
9312 ep.autoBoxAdjust = true;
9315 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9318 El.addUnits = function(v, defaultUnit){
9319 if(v === "" || v == "auto"){
9322 if(v === undefined){
9325 if(typeof v == "number" || !El.unitPattern.test(v)){
9326 return v + (defaultUnit || 'px');
9331 // special markup used throughout Roo when box wrapping elements
9332 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>';
9334 * Visibility mode constant - Use visibility to hide element
9340 * Visibility mode constant - Use display to hide element
9346 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9347 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9348 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9360 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9361 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9362 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9363 * @return {Element} The Element object
9366 El.get = function(el){
9368 if(!el){ return null; }
9369 if(typeof el == "string"){ // element id
9370 if(!(elm = document.getElementById(el))){
9373 if(ex = El.cache[el]){
9376 ex = El.cache[el] = new El(elm);
9379 }else if(el.tagName){ // dom element
9383 if(ex = El.cache[id]){
9386 ex = El.cache[id] = new El(el);
9389 }else if(el instanceof El){
9391 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9392 // catch case where it hasn't been appended
9393 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9396 }else if(el.isComposite){
9398 }else if(el instanceof Array){
9399 return El.select(el);
9400 }else if(el == document){
9401 // create a bogus element object representing the document object
9403 var f = function(){};
9404 f.prototype = El.prototype;
9406 docEl.dom = document;
9414 El.uncache = function(el){
9415 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9417 delete El.cache[a[i].id || a[i]];
9423 // Garbage collection - uncache elements/purge listeners on orphaned elements
9424 // so we don't hold a reference and cause the browser to retain them
9425 El.garbageCollect = function(){
9426 if(!Roo.enableGarbageCollector){
9427 clearInterval(El.collectorThread);
9430 for(var eid in El.cache){
9431 var el = El.cache[eid], d = el.dom;
9432 // -------------------------------------------------------
9433 // Determining what is garbage:
9434 // -------------------------------------------------------
9436 // dom node is null, definitely garbage
9437 // -------------------------------------------------------
9439 // no parentNode == direct orphan, definitely garbage
9440 // -------------------------------------------------------
9441 // !d.offsetParent && !document.getElementById(eid)
9442 // display none elements have no offsetParent so we will
9443 // also try to look it up by it's id. However, check
9444 // offsetParent first so we don't do unneeded lookups.
9445 // This enables collection of elements that are not orphans
9446 // directly, but somewhere up the line they have an orphan
9448 // -------------------------------------------------------
9449 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9450 delete El.cache[eid];
9451 if(d && Roo.enableListenerCollection){
9457 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9461 El.Flyweight = function(dom){
9464 El.Flyweight.prototype = El.prototype;
9466 El._flyweights = {};
9468 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9469 * the dom node can be overwritten by other code.
9470 * @param {String/HTMLElement} el The dom node or id
9471 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9472 * prevent conflicts (e.g. internally Roo uses "_internal")
9474 * @return {Element} The shared Element object
9476 El.fly = function(el, named){
9477 named = named || '_global';
9478 el = Roo.getDom(el);
9482 if(!El._flyweights[named]){
9483 El._flyweights[named] = new El.Flyweight();
9485 El._flyweights[named].dom = el;
9486 return El._flyweights[named];
9490 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9491 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9492 * Shorthand of {@link Roo.Element#get}
9493 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9494 * @return {Element} The Element object
9500 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9501 * the dom node can be overwritten by other code.
9502 * Shorthand of {@link Roo.Element#fly}
9503 * @param {String/HTMLElement} el The dom node or id
9504 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9505 * prevent conflicts (e.g. internally Roo uses "_internal")
9507 * @return {Element} The shared Element object
9513 // speedy lookup for elements never to box adjust
9514 var noBoxAdjust = Roo.isStrict ? {
9517 input:1, select:1, textarea:1
9519 if(Roo.isIE || Roo.isGecko){
9520 noBoxAdjust['button'] = 1;
9524 Roo.EventManager.on(window, 'unload', function(){
9526 delete El._flyweights;
9534 Roo.Element.selectorFunction = Roo.DomQuery.select;
9537 Roo.Element.select = function(selector, unique, root){
9539 if(typeof selector == "string"){
9540 els = Roo.Element.selectorFunction(selector, root);
9541 }else if(selector.length !== undefined){
9544 throw "Invalid selector";
9546 if(unique === true){
9547 return new Roo.CompositeElement(els);
9549 return new Roo.CompositeElementLite(els);
9553 * Selects elements based on the passed CSS selector to enable working on them as 1.
9554 * @param {String/Array} selector The CSS selector or an array of elements
9555 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9556 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9557 * @return {CompositeElementLite/CompositeElement}
9561 Roo.select = Roo.Element.select;