4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
90 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
93 enableGarbageCollector : true,
96 * True to automatically purge event listeners after uncaching an element (defaults to false).
97 * Note: this only happens if enableGarbageCollector is true.
100 enableListenerCollection:false,
103 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
104 * the IE insecure content warning (defaults to javascript:false).
107 SSL_SECURE_URL : "javascript:false",
110 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
111 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
114 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
116 emptyFn : function(){},
119 * Copies all the properties of config to obj if they don't already exist.
120 * @param {Object} obj The receiver of the properties
121 * @param {Object} config The source of the properties
122 * @return {Object} returns obj
124 applyIf : function(o, c){
127 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
134 * Applies event listeners to elements by selectors when the document is ready.
135 * The event name is specified with an @ suffix.
138 // add a listener for click on all anchors in element with id foo
139 '#foo a@click' : function(e, t){
143 // add the same listener to multiple selectors (separated by comma BEFORE the @)
144 '#foo a, #bar span.some-class@mouseover' : function(){
149 * @param {Object} obj The list of behaviors to apply
151 addBehaviors : function(o){
153 Roo.onReady(function(){
158 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
160 var parts = b.split('@');
161 if(parts[1]){ // for Object prototype breakers
164 cache[s] = Roo.select(s);
166 cache[s].on(parts[1], o[b]);
173 * Generates unique ids. If the element already has an id, it is unchanged
174 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
175 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
176 * @return {String} The generated Id.
178 id : function(el, prefix){
179 prefix = prefix || "roo-gen";
181 var id = prefix + (++idSeed);
182 return el ? (el.id ? el.id : (el.id = id)) : id;
187 * Extends one class with another class and optionally overrides members with the passed literal. This class
188 * also adds the function "override()" to the class that can be used to override
189 * members on an instance.
190 * @param {Object} subclass The class inheriting the functionality
191 * @param {Object} superclass The class being extended
192 * @param {Object} overrides (optional) A literal with members
197 var io = function(o){
202 return function(sb, sp, overrides){
203 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
206 sb = function(){sp.apply(this, arguments);};
208 var F = function(){}, sbp, spp = sp.prototype;
210 sbp = sb.prototype = new F();
214 if(spp.constructor == Object.prototype.constructor){
219 sb.override = function(o){
223 Roo.override(sb, overrides);
229 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
231 Roo.override(MyClass, {
232 newMethod1: function(){
235 newMethod2: function(foo){
240 * @param {Object} origclass The class to override
241 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
242 * containing one or more methods.
245 override : function(origclass, overrides){
247 var p = origclass.prototype;
248 for(var method in overrides){
249 p[method] = overrides[method];
254 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
256 Roo.namespace('Company', 'Company.data');
257 Company.Widget = function() { ... }
258 Company.data.CustomStore = function(config) { ... }
260 * @param {String} namespace1
261 * @param {String} namespace2
262 * @param {String} etc
265 namespace : function(){
266 var a=arguments, o=null, i, j, d, rt;
267 for (i=0; i<a.length; ++i) {
271 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
272 for (j=1; j<d.length; ++j) {
273 o[d[j]]=o[d[j]] || {};
279 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
281 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
282 Roo.factory(conf, Roo.data);
284 * @param {String} classname
285 * @param {String} namespace (optional)
289 factory : function(c, ns)
291 // no xtype, no ns or c.xns - or forced off by c.xns
292 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
295 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
296 if (c.constructor == ns[c.xtype]) {// already created...
300 if (Roo.debug) console.log("Roo.Factory(" + c.xtype + ")");
301 var ret = new ns[c.xtype](c);
305 c.xns = false; // prevent recursion..
310 * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2". Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
314 urlEncode : function(o){
320 var ov = o[key], k = encodeURIComponent(key);
321 var type = typeof ov;
322 if(type == 'undefined'){
324 }else if(type != "function" && type != "object"){
325 buf.push(k, "=", encodeURIComponent(ov), "&");
326 }else if(ov instanceof Array){
328 for(var i = 0, len = ov.length; i < len; i++) {
329 buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
341 * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
342 * @param {String} string
343 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
344 * @return {Object} A literal with members
346 urlDecode : function(string, overwrite){
347 if(!string || !string.length){
351 var pairs = string.split('&');
352 var pair, name, value;
353 for(var i = 0, len = pairs.length; i < len; i++){
354 pair = pairs[i].split('=');
355 name = decodeURIComponent(pair[0]);
356 value = decodeURIComponent(pair[1]);
357 if(overwrite !== true){
358 if(typeof obj[name] == "undefined"){
360 }else if(typeof obj[name] == "string"){
361 obj[name] = [obj[name]];
362 obj[name].push(value);
364 obj[name].push(value);
374 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
375 * passed array is not really an array, your function is called once with it.
376 * The supplied function is called with (Object item, Number index, Array allItems).
377 * @param {Array/NodeList/Mixed} array
378 * @param {Function} fn
379 * @param {Object} scope
381 each : function(array, fn, scope){
382 if(typeof array.length == "undefined" || typeof array == "string"){
385 for(var i = 0, len = array.length; i < len; i++){
386 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
391 combine : function(){
392 var as = arguments, l = as.length, r = [];
393 for(var i = 0; i < l; i++){
395 if(a instanceof Array){
397 }else if(a.length !== undefined && !a.substr){
398 r = r.concat(Array.prototype.slice.call(a, 0));
407 * Escapes the passed string for use in a regular expression
408 * @param {String} str
411 escapeRe : function(s) {
412 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
416 callback : function(cb, scope, args, delay){
417 if(typeof cb == "function"){
419 cb.defer(delay, scope, args || []);
421 cb.apply(scope, args || []);
427 * Return the dom node for the passed string (id), dom node, or Roo.Element
428 * @param {String/HTMLElement/Roo.Element} el
429 * @return HTMLElement
431 getDom : function(el){
435 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
439 * Shorthand for {@link Roo.ComponentMgr#get}
441 * @return Roo.Component
443 getCmp : function(id){
444 return Roo.ComponentMgr.get(id);
447 num : function(v, defaultValue){
448 if(typeof v != 'number'){
454 destroy : function(){
455 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
459 as.removeAllListeners();
463 if(typeof as.purgeListeners == 'function'){
466 if(typeof as.destroy == 'function'){
473 // inpired by a similar function in mootools library
475 * Returns the type of object that is passed in. If the object passed in is null or undefined it
476 * return false otherwise it returns one of the following values:<ul>
477 * <li><b>string</b>: If the object passed is a string</li>
478 * <li><b>number</b>: If the object passed is a number</li>
479 * <li><b>boolean</b>: If the object passed is a boolean value</li>
480 * <li><b>function</b>: If the object passed is a function reference</li>
481 * <li><b>object</b>: If the object passed is an object</li>
482 * <li><b>array</b>: If the object passed is an array</li>
483 * <li><b>regexp</b>: If the object passed is a regular expression</li>
484 * <li><b>element</b>: If the object passed is a DOM Element</li>
485 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
486 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
487 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
488 * @param {Mixed} object
492 if(o === undefined || o === null){
499 if(t == 'object' && o.nodeName) {
501 case 1: return 'element';
502 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
505 if(t == 'object' || t == 'function') {
506 switch(o.constructor) {
507 case Array: return 'array';
508 case RegExp: return 'regexp';
510 if(typeof o.length == 'number' && typeof o.item == 'function') {
518 * Returns true if the passed value is null, undefined or an empty string (optional).
519 * @param {Mixed} value The value to test
520 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
523 isEmpty : function(v, allowBlank){
524 return v === null || v === undefined || (!allowBlank ? v === '' : false);
538 isBorderBox : isBorderBox,
540 isWindows : isWindows,
547 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
548 * you may want to set this to true.
551 useShims : ((isIE && !isIE7) || (isGecko && isMac))
557 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
558 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
561 * Ext JS Library 1.1.1
562 * Copyright(c) 2006-2007, Ext JS, LLC.
564 * Originally Released Under LGPL - original licence link has changed is not relivant.
567 * <script type="text/javascript">
571 // wrappedn so fnCleanup is not in global scope...
573 function fnCleanUp() {
574 var p = Function.prototype;
575 delete p.createSequence;
577 delete p.createDelegate;
578 delete p.createCallback;
579 delete p.createInterceptor;
581 window.detachEvent("onunload", fnCleanUp);
583 window.attachEvent("onunload", fnCleanUp);
590 * These functions are available on every Function object (any JavaScript function).
592 Roo.apply(Function.prototype, {
594 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
595 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
596 * Will create a function that is bound to those 2 args.
597 * @return {Function} The new function
599 createCallback : function(/*args...*/){
600 // make args available, in function below
601 var args = arguments;
604 return method.apply(window, args);
609 * Creates a delegate (callback) that sets the scope to obj.
610 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
611 * Will create a function that is automatically scoped to this.
612 * @param {Object} obj (optional) The object for which the scope is set
613 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
614 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
615 * if a number the args are inserted at the specified position
616 * @return {Function} The new function
618 createDelegate : function(obj, args, appendArgs){
621 var callArgs = args || arguments;
622 if(appendArgs === true){
623 callArgs = Array.prototype.slice.call(arguments, 0);
624 callArgs = callArgs.concat(args);
625 }else if(typeof appendArgs == "number"){
626 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
627 var applyArgs = [appendArgs, 0].concat(args); // create method call params
628 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
630 return method.apply(obj || window, callArgs);
635 * Calls this function after the number of millseconds specified.
636 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
637 * @param {Object} obj (optional) The object for which the scope is set
638 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
639 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
640 * if a number the args are inserted at the specified position
641 * @return {Number} The timeout id that can be used with clearTimeout
643 defer : function(millis, obj, args, appendArgs){
644 var fn = this.createDelegate(obj, args, appendArgs);
646 return setTimeout(fn, millis);
652 * Create a combined function call sequence of the original function + the passed function.
653 * The resulting function returns the results of the original function.
654 * The passed fcn is called with the parameters of the original function
655 * @param {Function} fcn The function to sequence
656 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
657 * @return {Function} The new function
659 createSequence : function(fcn, scope){
660 if(typeof fcn != "function"){
665 var retval = method.apply(this || window, arguments);
666 fcn.apply(scope || this || window, arguments);
672 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
673 * The resulting function returns the results of the original function.
674 * The passed fcn is called with the parameters of the original function.
676 * @param {Function} fcn The function to call before the original
677 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
678 * @return {Function} The new function
680 createInterceptor : function(fcn, scope){
681 if(typeof fcn != "function"){
688 if(fcn.apply(scope || this || window, arguments) === false){
691 return method.apply(this || window, arguments);
697 * Ext JS Library 1.1.1
698 * Copyright(c) 2006-2007, Ext JS, LLC.
700 * Originally Released Under LGPL - original licence link has changed is not relivant.
703 * <script type="text/javascript">
706 Roo.applyIf(String, {
711 * Escapes the passed string for ' and \
712 * @param {String} string The string to escape
713 * @return {String} The escaped string
716 escape : function(string) {
717 return string.replace(/('|\\)/g, "\\$1");
721 * Pads the left side of a string with a specified character. This is especially useful
722 * for normalizing number and date strings. Example usage:
724 var s = String.leftPad('123', 5, '0');
725 // s now contains the string: '00123'
727 * @param {String} string The original string
728 * @param {Number} size The total length of the output string
729 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
730 * @return {String} The padded string
733 leftPad : function (val, size, ch) {
734 var result = new String(val);
735 if(ch === null || ch === undefined || ch === '') {
738 while (result.length < size) {
739 result = ch + result;
745 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
746 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
748 var cls = 'my-class', text = 'Some text';
749 var s = String.format('<div class="{0}">{1}</div>', cls, text);
750 // s now contains the string: '<div class="my-class">Some text</div>'
752 * @param {String} string The tokenized string to be formatted
753 * @param {String} value1 The value to replace token {0}
754 * @param {String} value2 Etc...
755 * @return {String} The formatted string
758 format : function(format){
759 var args = Array.prototype.slice.call(arguments, 1);
760 return format.replace(/\{(\d+)\}/g, function(m, i){
761 return Roo.util.Format.htmlEncode(args[i]);
767 * Utility function that allows you to easily switch a string between two alternating values. The passed value
768 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
769 * they are already different, the first value passed in is returned. Note that this method returns the new value
770 * but does not change the current string.
772 // alternate sort directions
773 sort = sort.toggle('ASC', 'DESC');
775 // instead of conditional logic:
776 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
778 * @param {String} value The value to compare to the current string
779 * @param {String} other The new value to use if the string already equals the first value passed in
780 * @return {String} The new value
783 String.prototype.toggle = function(value, other){
784 return this == value ? other : value;
787 * Ext JS Library 1.1.1
788 * Copyright(c) 2006-2007, Ext JS, LLC.
790 * Originally Released Under LGPL - original licence link has changed is not relivant.
793 * <script type="text/javascript">
799 Roo.applyIf(Number.prototype, {
801 * Checks whether or not the current number is within a desired range. If the number is already within the
802 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
803 * exceeded. Note that this method returns the constrained value but does not change the current number.
804 * @param {Number} min The minimum number in the range
805 * @param {Number} max The maximum number in the range
806 * @return {Number} The constrained value if outside the range, otherwise the current value
808 constrain : function(min, max){
809 return Math.min(Math.max(this, min), max);
813 * Ext JS Library 1.1.1
814 * Copyright(c) 2006-2007, Ext JS, LLC.
816 * Originally Released Under LGPL - original licence link has changed is not relivant.
819 * <script type="text/javascript">
824 Roo.applyIf(Array.prototype, {
826 * Checks whether or not the specified object exists in the array.
827 * @param {Object} o The object to check for
828 * @return {Number} The index of o in the array (or -1 if it is not found)
830 indexOf : function(o){
831 for (var i = 0, len = this.length; i < len; i++){
832 if(this[i] == o) return i;
838 * Removes the specified object from the array. If the object is not found nothing happens.
839 * @param {Object} o The object to remove
841 remove : function(o){
842 var index = this.indexOf(o);
844 this.splice(index, 1);
848 * Map (JS 1.6 compatibility)
849 * @param {Function} function to call
851 map : function(fun /*, thisp*/)
853 var len = this.length >>> 0;
854 if (typeof fun != "function")
855 throw new TypeError();
857 var res = new Array(len);
858 var thisp = arguments[1];
859 for (var i = 0; i < len; i++)
862 res[i] = fun.call(thisp, this[i], i, this);
872 if (!Array.prototype.map)
877 * Ext JS Library 1.1.1
878 * Copyright(c) 2006-2007, Ext JS, LLC.
880 * Originally Released Under LGPL - original licence link has changed is not relivant.
883 * <script type="text/javascript">
889 * The date parsing and format syntax is a subset of
890 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
891 * supported will provide results equivalent to their PHP versions.
893 * Following is the list of all currently supported formats:
896 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
898 Format Output Description
899 ------ ---------- --------------------------------------------------------------
900 d 10 Day of the month, 2 digits with leading zeros
901 D Wed A textual representation of a day, three letters
902 j 10 Day of the month without leading zeros
903 l Wednesday A full textual representation of the day of the week
904 S th English ordinal day of month suffix, 2 chars (use with j)
905 w 3 Numeric representation of the day of the week
906 z 9 The julian date, or day of the year (0-365)
907 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
908 F January A full textual representation of the month
909 m 01 Numeric representation of a month, with leading zeros
910 M Jan Month name abbreviation, three letters
911 n 1 Numeric representation of a month, without leading zeros
912 t 31 Number of days in the given month
913 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
914 Y 2007 A full numeric representation of a year, 4 digits
915 y 07 A two digit representation of a year
916 a pm Lowercase Ante meridiem and Post meridiem
917 A PM Uppercase Ante meridiem and Post meridiem
918 g 3 12-hour format of an hour without leading zeros
919 G 15 24-hour format of an hour without leading zeros
920 h 03 12-hour format of an hour with leading zeros
921 H 15 24-hour format of an hour with leading zeros
922 i 05 Minutes with leading zeros
923 s 01 Seconds, with leading zeros
924 O -0600 Difference to Greenwich time (GMT) in hours
925 T CST Timezone setting of the machine running the code
926 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
929 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
931 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
932 document.write(dt.format('Y-m-d')); //2007-01-10
933 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
934 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
937 * Here are some standard date/time patterns that you might find helpful. They
938 * are not part of the source of Date.js, but to use them you can simply copy this
939 * block of code into any script that is included after Date.js and they will also become
940 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
943 ISO8601Long:"Y-m-d H:i:s",
944 ISO8601Short:"Y-m-d",
946 LongDate: "l, F d, Y",
947 FullDateTime: "l, F d, Y g:i:s A",
951 SortableDateTime: "Y-m-d\\TH:i:s",
952 UniversalSortableDateTime: "Y-m-d H:i:sO",
960 document.write(dt.format(Date.patterns.ShortDate));
965 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
966 * They generate precompiled functions from date formats instead of parsing and
967 * processing the pattern every time you format a date. These functions are available
968 * on every Date object (any javascript function).
970 * The original article and download are here:
971 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
978 Returns the number of milliseconds between this date and date
979 @param {Date} date (optional) Defaults to now
980 @return {Number} The diff in milliseconds
981 @member Date getElapsed
983 Date.prototype.getElapsed = function(date) {
984 return Math.abs((date || new Date()).getTime()-this.getTime());
986 // was in date file..
990 Date.parseFunctions = {count:0};
992 Date.parseRegexes = [];
994 Date.formatFunctions = {count:0};
997 Date.prototype.dateFormat = function(format) {
998 if (Date.formatFunctions[format] == null) {
999 Date.createNewFormat(format);
1001 var func = Date.formatFunctions[format];
1002 return this[func]();
1007 * Formats a date given the supplied format string
1008 * @param {String} format The format string
1009 * @return {String} The formatted date
1012 Date.prototype.format = Date.prototype.dateFormat;
1015 Date.createNewFormat = function(format) {
1016 var funcName = "format" + Date.formatFunctions.count++;
1017 Date.formatFunctions[format] = funcName;
1018 var code = "Date.prototype." + funcName + " = function(){return ";
1019 var special = false;
1021 for (var i = 0; i < format.length; ++i) {
1022 ch = format.charAt(i);
1023 if (!special && ch == "\\") {
1028 code += "'" + String.escape(ch) + "' + ";
1031 code += Date.getFormatCode(ch);
1034 /** eval:var:zzzzzzzzzzzzz */
1035 eval(code.substring(0, code.length - 3) + ";}");
1039 Date.getFormatCode = function(character) {
1040 switch (character) {
1042 return "String.leftPad(this.getDate(), 2, '0') + ";
1044 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1046 return "this.getDate() + ";
1048 return "Date.dayNames[this.getDay()] + ";
1050 return "this.getSuffix() + ";
1052 return "this.getDay() + ";
1054 return "this.getDayOfYear() + ";
1056 return "this.getWeekOfYear() + ";
1058 return "Date.monthNames[this.getMonth()] + ";
1060 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1062 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1064 return "(this.getMonth() + 1) + ";
1066 return "this.getDaysInMonth() + ";
1068 return "(this.isLeapYear() ? 1 : 0) + ";
1070 return "this.getFullYear() + ";
1072 return "('' + this.getFullYear()).substring(2, 4) + ";
1074 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1076 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1078 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1080 return "this.getHours() + ";
1082 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1084 return "String.leftPad(this.getHours(), 2, '0') + ";
1086 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1088 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1090 return "this.getGMTOffset() + ";
1092 return "this.getTimezone() + ";
1094 return "(this.getTimezoneOffset() * -60) + ";
1096 return "'" + String.escape(character) + "' + ";
1101 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1102 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1103 * the date format that is not specified will default to the current date value for that part. Time parts can also
1104 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1105 * string or the parse operation will fail.
1108 //dt = Fri May 25 2007 (current date)
1109 var dt = new Date();
1111 //dt = Thu May 25 2006 (today's month/day in 2006)
1112 dt = Date.parseDate("2006", "Y");
1114 //dt = Sun Jan 15 2006 (all date parts specified)
1115 dt = Date.parseDate("2006-1-15", "Y-m-d");
1117 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1118 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1120 * @param {String} input The unparsed date as a string
1121 * @param {String} format The format the date is in
1122 * @return {Date} The parsed date
1125 Date.parseDate = function(input, format) {
1126 if (Date.parseFunctions[format] == null) {
1127 Date.createParser(format);
1129 var func = Date.parseFunctions[format];
1130 return Date[func](input);
1135 Date.createParser = function(format) {
1136 var funcName = "parse" + Date.parseFunctions.count++;
1137 var regexNum = Date.parseRegexes.length;
1138 var currentGroup = 1;
1139 Date.parseFunctions[format] = funcName;
1141 var code = "Date." + funcName + " = function(input){\n"
1142 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1143 + "var d = new Date();\n"
1144 + "y = d.getFullYear();\n"
1145 + "m = d.getMonth();\n"
1146 + "d = d.getDate();\n"
1147 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1148 + "if (results && results.length > 0) {";
1151 var special = false;
1153 for (var i = 0; i < format.length; ++i) {
1154 ch = format.charAt(i);
1155 if (!special && ch == "\\") {
1160 regex += String.escape(ch);
1163 var obj = Date.formatCodeToRegex(ch, currentGroup);
1164 currentGroup += obj.g;
1166 if (obj.g && obj.c) {
1172 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1173 + "{v = new Date(y, m, d, h, i, s);}\n"
1174 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1175 + "{v = new Date(y, m, d, h, i);}\n"
1176 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1177 + "{v = new Date(y, m, d, h);}\n"
1178 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1179 + "{v = new Date(y, m, d);}\n"
1180 + "else if (y >= 0 && m >= 0)\n"
1181 + "{v = new Date(y, m);}\n"
1182 + "else if (y >= 0)\n"
1183 + "{v = new Date(y);}\n"
1184 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1185 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1186 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1189 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1190 /** eval:var:zzzzzzzzzzzzz */
1195 Date.formatCodeToRegex = function(character, currentGroup) {
1196 switch (character) {
1200 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1203 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1204 s:"(\\d{1,2})"}; // day of month without leading zeroes
1207 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1208 s:"(\\d{2})"}; // day of month with leading zeroes
1212 s:"(?:" + Date.dayNames.join("|") + ")"};
1216 s:"(?:st|nd|rd|th)"};
1231 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1232 s:"(" + Date.monthNames.join("|") + ")"};
1235 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1236 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1239 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1240 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1243 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1244 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1255 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1259 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1260 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1264 c:"if (results[" + currentGroup + "] == 'am') {\n"
1265 + "if (h == 12) { h = 0; }\n"
1266 + "} else { if (h < 12) { h += 12; }}",
1270 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1271 + "if (h == 12) { h = 0; }\n"
1272 + "} else { if (h < 12) { h += 12; }}",
1277 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1278 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1282 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1283 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1286 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1290 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1295 "o = results[", currentGroup, "];\n",
1296 "var sn = o.substring(0,1);\n", // get + / - sign
1297 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1298 "var mn = o.substring(3,5) % 60;\n", // get minutes
1299 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1300 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1306 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1309 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1310 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1311 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1315 s:String.escape(character)};
1320 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1321 * @return {String} The abbreviated timezone name (e.g. 'CST')
1323 Date.prototype.getTimezone = function() {
1324 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1328 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1329 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1331 Date.prototype.getGMTOffset = function() {
1332 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1333 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1334 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1338 * Get the numeric day number of the year, adjusted for leap year.
1339 * @return {Number} 0 through 364 (365 in leap years)
1341 Date.prototype.getDayOfYear = function() {
1343 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1344 for (var i = 0; i < this.getMonth(); ++i) {
1345 num += Date.daysInMonth[i];
1347 return num + this.getDate() - 1;
1351 * Get the string representation of the numeric week number of the year
1352 * (equivalent to the format specifier 'W').
1353 * @return {String} '00' through '52'
1355 Date.prototype.getWeekOfYear = function() {
1356 // Skip to Thursday of this week
1357 var now = this.getDayOfYear() + (4 - this.getDay());
1358 // Find the first Thursday of the year
1359 var jan1 = new Date(this.getFullYear(), 0, 1);
1360 var then = (7 - jan1.getDay() + 4);
1361 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1365 * Whether or not the current date is in a leap year.
1366 * @return {Boolean} True if the current date is in a leap year, else false
1368 Date.prototype.isLeapYear = function() {
1369 var year = this.getFullYear();
1370 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1374 * Get the first day of the current month, adjusted for leap year. The returned value
1375 * is the numeric day index within the week (0-6) which can be used in conjunction with
1376 * the {@link #monthNames} array to retrieve the textual day name.
1379 var dt = new Date('1/10/2007');
1380 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1382 * @return {Number} The day number (0-6)
1384 Date.prototype.getFirstDayOfMonth = function() {
1385 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1386 return (day < 0) ? (day + 7) : day;
1390 * Get the last day of the current month, adjusted for leap year. The returned value
1391 * is the numeric day index within the week (0-6) which can be used in conjunction with
1392 * the {@link #monthNames} array to retrieve the textual day name.
1395 var dt = new Date('1/10/2007');
1396 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1398 * @return {Number} The day number (0-6)
1400 Date.prototype.getLastDayOfMonth = function() {
1401 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1402 return (day < 0) ? (day + 7) : day;
1407 * Get the first date of this date's month
1410 Date.prototype.getFirstDateOfMonth = function() {
1411 return new Date(this.getFullYear(), this.getMonth(), 1);
1415 * Get the last date of this date's month
1418 Date.prototype.getLastDateOfMonth = function() {
1419 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1422 * Get the number of days in the current month, adjusted for leap year.
1423 * @return {Number} The number of days in the month
1425 Date.prototype.getDaysInMonth = function() {
1426 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1427 return Date.daysInMonth[this.getMonth()];
1431 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1432 * @return {String} 'st, 'nd', 'rd' or 'th'
1434 Date.prototype.getSuffix = function() {
1435 switch (this.getDate()) {
1452 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1455 * An array of textual month names.
1456 * Override these values for international dates, for example...
1457 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1476 * An array of textual day names.
1477 * Override these values for international dates, for example...
1478 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1494 Date.monthNumbers = {
1509 * Creates and returns a new Date instance with the exact same date value as the called instance.
1510 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1511 * variable will also be changed. When the intention is to create a new variable that will not
1512 * modify the original instance, you should create a clone.
1514 * Example of correctly cloning a date:
1517 var orig = new Date('10/1/2006');
1520 document.write(orig); //returns 'Thu Oct 05 2006'!
1523 var orig = new Date('10/1/2006');
1524 var copy = orig.clone();
1526 document.write(orig); //returns 'Thu Oct 01 2006'
1528 * @return {Date} The new Date instance
1530 Date.prototype.clone = function() {
1531 return new Date(this.getTime());
1535 * Clears any time information from this date
1536 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1537 @return {Date} this or the clone
1539 Date.prototype.clearTime = function(clone){
1541 return this.clone().clearTime();
1546 this.setMilliseconds(0);
1551 // safari setMonth is broken
1553 Date.brokenSetMonth = Date.prototype.setMonth;
1554 Date.prototype.setMonth = function(num){
1556 var n = Math.ceil(-num);
1557 var back_year = Math.ceil(n/12);
1558 var month = (n % 12) ? 12 - n % 12 : 0 ;
1559 this.setFullYear(this.getFullYear() - back_year);
1560 return Date.brokenSetMonth.call(this, month);
1562 return Date.brokenSetMonth.apply(this, arguments);
1567 /** Date interval constant
1571 /** Date interval constant
1575 /** Date interval constant
1579 /** Date interval constant
1583 /** Date interval constant
1587 /** Date interval constant
1591 /** Date interval constant
1597 * Provides a convenient method of performing basic date arithmetic. This method
1598 * does not modify the Date instance being called - it creates and returns
1599 * a new Date instance containing the resulting date value.
1604 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1605 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1607 //Negative values will subtract correctly:
1608 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1609 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1611 //You can even chain several calls together in one line!
1612 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1613 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1616 * @param {String} interval A valid date interval enum value
1617 * @param {Number} value The amount to add to the current date
1618 * @return {Date} The new Date instance
1620 Date.prototype.add = function(interval, value){
1621 var d = this.clone();
1622 if (!interval || value === 0) return d;
1623 switch(interval.toLowerCase()){
1625 d.setMilliseconds(this.getMilliseconds() + value);
1628 d.setSeconds(this.getSeconds() + value);
1631 d.setMinutes(this.getMinutes() + value);
1634 d.setHours(this.getHours() + value);
1637 d.setDate(this.getDate() + value);
1640 var day = this.getDate();
1642 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1645 d.setMonth(this.getMonth() + value);
1648 d.setFullYear(this.getFullYear() + value);
1654 * Ext JS Library 1.1.1
1655 * Copyright(c) 2006-2007, Ext JS, LLC.
1657 * Originally Released Under LGPL - original licence link has changed is not relivant.
1660 * <script type="text/javascript">
1664 getViewWidth : function(full) {
1665 return full ? this.getDocumentWidth() : this.getViewportWidth();
1668 getViewHeight : function(full) {
1669 return full ? this.getDocumentHeight() : this.getViewportHeight();
1672 getDocumentHeight: function() {
1673 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1674 return Math.max(scrollHeight, this.getViewportHeight());
1677 getDocumentWidth: function() {
1678 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1679 return Math.max(scrollWidth, this.getViewportWidth());
1682 getViewportHeight: function() {
1683 var height = self.innerHeight;
1684 var mode = document.compatMode;
1686 if ((mode || Roo.isIE) && !Roo.isOpera) {
1687 height = (mode == "CSS1Compat") ?
1688 document.documentElement.clientHeight :
1689 document.body.clientHeight;
1695 getViewportWidth: function() {
1696 var width = self.innerWidth;
1697 var mode = document.compatMode;
1699 if (mode || Roo.isIE) {
1700 width = (mode == "CSS1Compat") ?
1701 document.documentElement.clientWidth :
1702 document.body.clientWidth;
1707 isAncestor : function(p, c) {
1714 if (p.contains && !Roo.isSafari) {
1715 return p.contains(c);
1716 } else if (p.compareDocumentPosition) {
1717 return !!(p.compareDocumentPosition(c) & 16);
1719 var parent = c.parentNode;
1724 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1727 parent = parent.parentNode;
1733 getRegion : function(el) {
1734 return Roo.lib.Region.getRegion(el);
1737 getY : function(el) {
1738 return this.getXY(el)[1];
1741 getX : function(el) {
1742 return this.getXY(el)[0];
1745 getXY : function(el) {
1746 var p, pe, b, scroll, bd = document.body;
1747 el = Roo.getDom(el);
1748 var fly = Roo.lib.AnimBase.fly;
1749 if (el.getBoundingClientRect) {
1750 b = el.getBoundingClientRect();
1751 scroll = fly(document).getScroll();
1752 return [b.left + scroll.left, b.top + scroll.top];
1758 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1765 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1772 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1773 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1780 if (p != el && pe.getStyle('overflow') != 'visible') {
1788 if (Roo.isSafari && hasAbsolute) {
1793 if (Roo.isGecko && !hasAbsolute) {
1795 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1796 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1800 while (p && p != bd) {
1801 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1813 setXY : function(el, xy) {
1814 el = Roo.fly(el, '_setXY');
1816 var pts = el.translatePoints(xy);
1817 if (xy[0] !== false) {
1818 el.dom.style.left = pts.left + "px";
1820 if (xy[1] !== false) {
1821 el.dom.style.top = pts.top + "px";
1825 setX : function(el, x) {
1826 this.setXY(el, [x, false]);
1829 setY : function(el, y) {
1830 this.setXY(el, [false, y]);
1834 * Portions of this file are based on pieces of Yahoo User Interface Library
1835 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1836 * YUI licensed under the BSD License:
1837 * http://developer.yahoo.net/yui/license.txt
1838 * <script type="text/javascript">
1842 Roo.lib.Event = function() {
1843 var loadComplete = false;
1845 var unloadListeners = [];
1847 var onAvailStack = [];
1849 var lastError = null;
1862 startInterval: function() {
1863 if (!this._interval) {
1865 var callback = function() {
1866 self._tryPreloadAttach();
1868 this._interval = setInterval(callback, this.POLL_INTERVAL);
1873 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1874 onAvailStack.push({ id: p_id,
1877 override: p_override,
1878 checkReady: false });
1880 retryCount = this.POLL_RETRYS;
1881 this.startInterval();
1885 addListener: function(el, eventName, fn) {
1886 el = Roo.getDom(el);
1891 if ("unload" == eventName) {
1892 unloadListeners[unloadListeners.length] =
1893 [el, eventName, fn];
1897 var wrappedFn = function(e) {
1898 return fn(Roo.lib.Event.getEvent(e));
1901 var li = [el, eventName, fn, wrappedFn];
1903 var index = listeners.length;
1904 listeners[index] = li;
1906 this.doAdd(el, eventName, wrappedFn, false);
1912 removeListener: function(el, eventName, fn) {
1915 el = Roo.getDom(el);
1918 return this.purgeElement(el, false, eventName);
1922 if ("unload" == eventName) {
1924 for (i = 0,len = unloadListeners.length; i < len; i++) {
1925 var li = unloadListeners[i];
1928 li[1] == eventName &&
1930 unloadListeners.splice(i, 1);
1938 var cacheItem = null;
1941 var index = arguments[3];
1943 if ("undefined" == typeof index) {
1944 index = this._getCacheIndex(el, eventName, fn);
1948 cacheItem = listeners[index];
1951 if (!el || !cacheItem) {
1955 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1957 delete listeners[index][this.WFN];
1958 delete listeners[index][this.FN];
1959 listeners.splice(index, 1);
1966 getTarget: function(ev, resolveTextNode) {
1967 ev = ev.browserEvent || ev;
1968 var t = ev.target || ev.srcElement;
1969 return this.resolveTextNode(t);
1973 resolveTextNode: function(node) {
1974 if (Roo.isSafari && node && 3 == node.nodeType) {
1975 return node.parentNode;
1982 getPageX: function(ev) {
1983 ev = ev.browserEvent || ev;
1985 if (!x && 0 !== x) {
1986 x = ev.clientX || 0;
1989 x += this.getScroll()[1];
1997 getPageY: function(ev) {
1998 ev = ev.browserEvent || ev;
2000 if (!y && 0 !== y) {
2001 y = ev.clientY || 0;
2004 y += this.getScroll()[0];
2013 getXY: function(ev) {
2014 ev = ev.browserEvent || ev;
2015 return [this.getPageX(ev), this.getPageY(ev)];
2019 getRelatedTarget: function(ev) {
2020 ev = ev.browserEvent || ev;
2021 var t = ev.relatedTarget;
2023 if (ev.type == "mouseout") {
2025 } else if (ev.type == "mouseover") {
2030 return this.resolveTextNode(t);
2034 getTime: function(ev) {
2035 ev = ev.browserEvent || ev;
2037 var t = new Date().getTime();
2041 this.lastError = ex;
2050 stopEvent: function(ev) {
2051 this.stopPropagation(ev);
2052 this.preventDefault(ev);
2056 stopPropagation: function(ev) {
2057 ev = ev.browserEvent || ev;
2058 if (ev.stopPropagation) {
2059 ev.stopPropagation();
2061 ev.cancelBubble = true;
2066 preventDefault: function(ev) {
2067 ev = ev.browserEvent || ev;
2068 if(ev.preventDefault) {
2069 ev.preventDefault();
2071 ev.returnValue = false;
2076 getEvent: function(e) {
2077 var ev = e || window.event;
2079 var c = this.getEvent.caller;
2081 ev = c.arguments[0];
2082 if (ev && Event == ev.constructor) {
2092 getCharCode: function(ev) {
2093 ev = ev.browserEvent || ev;
2094 return ev.charCode || ev.keyCode || 0;
2098 _getCacheIndex: function(el, eventName, fn) {
2099 for (var i = 0,len = listeners.length; i < len; ++i) {
2100 var li = listeners[i];
2102 li[this.FN] == fn &&
2103 li[this.EL] == el &&
2104 li[this.TYPE] == eventName) {
2116 getEl: function(id) {
2117 return document.getElementById(id);
2121 clearCache: function() {
2125 _load: function(e) {
2126 loadComplete = true;
2127 var EU = Roo.lib.Event;
2131 EU.doRemove(window, "load", EU._load);
2136 _tryPreloadAttach: function() {
2145 var tryAgain = !loadComplete;
2147 tryAgain = (retryCount > 0);
2152 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2153 var item = onAvailStack[i];
2155 var el = this.getEl(item.id);
2158 if (!item.checkReady ||
2161 (document && document.body)) {
2164 if (item.override) {
2165 if (item.override === true) {
2168 scope = item.override;
2171 item.fn.call(scope, item.obj);
2172 onAvailStack[i] = null;
2175 notAvail.push(item);
2180 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2184 this.startInterval();
2186 clearInterval(this._interval);
2187 this._interval = null;
2190 this.locked = false;
2197 purgeElement: function(el, recurse, eventName) {
2198 var elListeners = this.getListeners(el, eventName);
2200 for (var i = 0,len = elListeners.length; i < len; ++i) {
2201 var l = elListeners[i];
2202 this.removeListener(el, l.type, l.fn);
2206 if (recurse && el && el.childNodes) {
2207 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2208 this.purgeElement(el.childNodes[i], recurse, eventName);
2214 getListeners: function(el, eventName) {
2215 var results = [], searchLists;
2217 searchLists = [listeners, unloadListeners];
2218 } else if (eventName == "unload") {
2219 searchLists = [unloadListeners];
2221 searchLists = [listeners];
2224 for (var j = 0; j < searchLists.length; ++j) {
2225 var searchList = searchLists[j];
2226 if (searchList && searchList.length > 0) {
2227 for (var i = 0,len = searchList.length; i < len; ++i) {
2228 var l = searchList[i];
2229 if (l && l[this.EL] === el &&
2230 (!eventName || eventName === l[this.TYPE])) {
2235 adjust: l[this.ADJ_SCOPE],
2243 return (results.length) ? results : null;
2247 _unload: function(e) {
2249 var EU = Roo.lib.Event, i, j, l, len, index;
2251 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2252 l = unloadListeners[i];
2255 if (l[EU.ADJ_SCOPE]) {
2256 if (l[EU.ADJ_SCOPE] === true) {
2259 scope = l[EU.ADJ_SCOPE];
2262 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2263 unloadListeners[i] = null;
2269 unloadListeners = null;
2271 if (listeners && listeners.length > 0) {
2272 j = listeners.length;
2275 l = listeners[index];
2277 EU.removeListener(l[EU.EL], l[EU.TYPE],
2287 EU.doRemove(window, "unload", EU._unload);
2292 getScroll: function() {
2293 var dd = document.documentElement, db = document.body;
2294 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2295 return [dd.scrollTop, dd.scrollLeft];
2297 return [db.scrollTop, db.scrollLeft];
2304 doAdd: function () {
2305 if (window.addEventListener) {
2306 return function(el, eventName, fn, capture) {
2307 el.addEventListener(eventName, fn, (capture));
2309 } else if (window.attachEvent) {
2310 return function(el, eventName, fn, capture) {
2311 el.attachEvent("on" + eventName, fn);
2320 doRemove: function() {
2321 if (window.removeEventListener) {
2322 return function (el, eventName, fn, capture) {
2323 el.removeEventListener(eventName, fn, (capture));
2325 } else if (window.detachEvent) {
2326 return function (el, eventName, fn) {
2327 el.detachEvent("on" + eventName, fn);
2339 var E = Roo.lib.Event;
2340 E.on = E.addListener;
2341 E.un = E.removeListener;
2343 if (document && document.body) {
2346 E.doAdd(window, "load", E._load);
2348 E.doAdd(window, "unload", E._unload);
2349 E._tryPreloadAttach();
2353 * Portions of this file are based on pieces of Yahoo User Interface Library
2354 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2355 * YUI licensed under the BSD License:
2356 * http://developer.yahoo.net/yui/license.txt
2357 * <script type="text/javascript">
2364 request : function(method, uri, cb, data, options) {
2366 var hs = options.headers;
2369 if(hs.hasOwnProperty(h)){
2370 this.initHeader(h, hs[h], false);
2374 if(options.xmlData){
2375 this.initHeader('Content-Type', 'text/xml', false);
2377 data = options.xmlData;
2381 return this.asyncRequest(method, uri, cb, data);
2384 serializeForm : function(form) {
2385 if(typeof form == 'string') {
2386 form = (document.getElementById(form) || document.forms[form]);
2389 var el, name, val, disabled, data = '', hasSubmit = false;
2390 for (var i = 0; i < form.elements.length; i++) {
2391 el = form.elements[i];
2392 disabled = form.elements[i].disabled;
2393 name = form.elements[i].name;
2394 val = form.elements[i].value;
2396 if (!disabled && name){
2400 case 'select-multiple':
2401 for (var j = 0; j < el.options.length; j++) {
2402 if (el.options[j].selected) {
2404 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2407 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2415 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2428 if(hasSubmit == false) {
2429 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2434 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2439 data = data.substr(0, data.length - 1);
2447 useDefaultHeader:true,
2449 defaultPostHeader:'application/x-www-form-urlencoded',
2451 useDefaultXhrHeader:true,
2453 defaultXhrHeader:'XMLHttpRequest',
2455 hasDefaultHeaders:true,
2467 setProgId:function(id)
2469 this.activeX.unshift(id);
2472 setDefaultPostHeader:function(b)
2474 this.useDefaultHeader = b;
2477 setDefaultXhrHeader:function(b)
2479 this.useDefaultXhrHeader = b;
2482 setPollingInterval:function(i)
2484 if (typeof i == 'number' && isFinite(i)) {
2485 this.pollInterval = i;
2489 createXhrObject:function(transactionId)
2495 http = new XMLHttpRequest();
2497 obj = { conn:http, tId:transactionId };
2501 for (var i = 0; i < this.activeX.length; ++i) {
2505 http = new ActiveXObject(this.activeX[i]);
2507 obj = { conn:http, tId:transactionId };
2520 getConnectionObject:function()
2523 var tId = this.transactionId;
2527 o = this.createXhrObject(tId);
2529 this.transactionId++;
2540 asyncRequest:function(method, uri, callback, postData)
2542 var o = this.getConnectionObject();
2548 o.conn.open(method, uri, true);
2550 if (this.useDefaultXhrHeader) {
2551 if (!this.defaultHeaders['X-Requested-With']) {
2552 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2556 if(postData && this.useDefaultHeader){
2557 this.initHeader('Content-Type', this.defaultPostHeader);
2560 if (this.hasDefaultHeaders || this.hasHeaders) {
2564 this.handleReadyState(o, callback);
2565 o.conn.send(postData || null);
2571 handleReadyState:function(o, callback)
2575 if (callback && callback.timeout) {
2576 this.timeout[o.tId] = window.setTimeout(function() {
2577 oConn.abort(o, callback, true);
2578 }, callback.timeout);
2581 this.poll[o.tId] = window.setInterval(
2583 if (o.conn && o.conn.readyState == 4) {
2584 window.clearInterval(oConn.poll[o.tId]);
2585 delete oConn.poll[o.tId];
2587 if(callback && callback.timeout) {
2588 window.clearTimeout(oConn.timeout[o.tId]);
2589 delete oConn.timeout[o.tId];
2592 oConn.handleTransactionResponse(o, callback);
2595 , this.pollInterval);
2598 handleTransactionResponse:function(o, callback, isAbort)
2602 this.releaseObject(o);
2606 var httpStatus, responseObject;
2610 if (o.conn.status !== undefined && o.conn.status != 0) {
2611 httpStatus = o.conn.status;
2623 if (httpStatus >= 200 && httpStatus < 300) {
2624 responseObject = this.createResponseObject(o, callback.argument);
2625 if (callback.success) {
2626 if (!callback.scope) {
2627 callback.success(responseObject);
2632 callback.success.apply(callback.scope, [responseObject]);
2637 switch (httpStatus) {
2645 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2646 if (callback.failure) {
2647 if (!callback.scope) {
2648 callback.failure(responseObject);
2651 callback.failure.apply(callback.scope, [responseObject]);
2656 responseObject = this.createResponseObject(o, callback.argument);
2657 if (callback.failure) {
2658 if (!callback.scope) {
2659 callback.failure(responseObject);
2662 callback.failure.apply(callback.scope, [responseObject]);
2668 this.releaseObject(o);
2669 responseObject = null;
2672 createResponseObject:function(o, callbackArg)
2679 var headerStr = o.conn.getAllResponseHeaders();
2680 var header = headerStr.split('\n');
2681 for (var i = 0; i < header.length; i++) {
2682 var delimitPos = header[i].indexOf(':');
2683 if (delimitPos != -1) {
2684 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2692 obj.status = o.conn.status;
2693 obj.statusText = o.conn.statusText;
2694 obj.getResponseHeader = headerObj;
2695 obj.getAllResponseHeaders = headerStr;
2696 obj.responseText = o.conn.responseText;
2697 obj.responseXML = o.conn.responseXML;
2699 if (typeof callbackArg !== undefined) {
2700 obj.argument = callbackArg;
2706 createExceptionObject:function(tId, callbackArg, isAbort)
2709 var COMM_ERROR = 'communication failure';
2710 var ABORT_CODE = -1;
2711 var ABORT_ERROR = 'transaction aborted';
2717 obj.status = ABORT_CODE;
2718 obj.statusText = ABORT_ERROR;
2721 obj.status = COMM_CODE;
2722 obj.statusText = COMM_ERROR;
2726 obj.argument = callbackArg;
2732 initHeader:function(label, value, isDefault)
2734 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2736 if (headerObj[label] === undefined) {
2737 headerObj[label] = value;
2742 headerObj[label] = value + "," + headerObj[label];
2746 this.hasDefaultHeaders = true;
2749 this.hasHeaders = true;
2754 setHeader:function(o)
2756 if (this.hasDefaultHeaders) {
2757 for (var prop in this.defaultHeaders) {
2758 if (this.defaultHeaders.hasOwnProperty(prop)) {
2759 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2764 if (this.hasHeaders) {
2765 for (var prop in this.headers) {
2766 if (this.headers.hasOwnProperty(prop)) {
2767 o.conn.setRequestHeader(prop, this.headers[prop]);
2771 this.hasHeaders = false;
2775 resetDefaultHeaders:function() {
2776 delete this.defaultHeaders;
2777 this.defaultHeaders = {};
2778 this.hasDefaultHeaders = false;
2781 abort:function(o, callback, isTimeout)
2783 if(this.isCallInProgress(o)) {
2785 window.clearInterval(this.poll[o.tId]);
2786 delete this.poll[o.tId];
2788 delete this.timeout[o.tId];
2791 this.handleTransactionResponse(o, callback, true);
2801 isCallInProgress:function(o)
2804 return o.conn.readyState != 4 && o.conn.readyState != 0;
2813 releaseObject:function(o)
2822 'MSXML2.XMLHTTP.3.0',
2830 * Portions of this file are based on pieces of Yahoo User Interface Library
2831 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2832 * YUI licensed under the BSD License:
2833 * http://developer.yahoo.net/yui/license.txt
2834 * <script type="text/javascript">
2838 Roo.lib.Region = function(t, r, b, l) {
2848 Roo.lib.Region.prototype = {
2849 contains : function(region) {
2850 return ( region.left >= this.left &&
2851 region.right <= this.right &&
2852 region.top >= this.top &&
2853 region.bottom <= this.bottom );
2857 getArea : function() {
2858 return ( (this.bottom - this.top) * (this.right - this.left) );
2861 intersect : function(region) {
2862 var t = Math.max(this.top, region.top);
2863 var r = Math.min(this.right, region.right);
2864 var b = Math.min(this.bottom, region.bottom);
2865 var l = Math.max(this.left, region.left);
2867 if (b >= t && r >= l) {
2868 return new Roo.lib.Region(t, r, b, l);
2873 union : function(region) {
2874 var t = Math.min(this.top, region.top);
2875 var r = Math.max(this.right, region.right);
2876 var b = Math.max(this.bottom, region.bottom);
2877 var l = Math.min(this.left, region.left);
2879 return new Roo.lib.Region(t, r, b, l);
2882 adjust : function(t, l, b, r) {
2891 Roo.lib.Region.getRegion = function(el) {
2892 var p = Roo.lib.Dom.getXY(el);
2895 var r = p[0] + el.offsetWidth;
2896 var b = p[1] + el.offsetHeight;
2899 return new Roo.lib.Region(t, r, b, l);
2902 * Portions of this file are based on pieces of Yahoo User Interface Library
2903 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2904 * YUI licensed under the BSD License:
2905 * http://developer.yahoo.net/yui/license.txt
2906 * <script type="text/javascript">
2909 //@@dep Roo.lib.Region
2912 Roo.lib.Point = function(x, y) {
2913 if (x instanceof Array) {
2917 this.x = this.right = this.left = this[0] = x;
2918 this.y = this.top = this.bottom = this[1] = y;
2921 Roo.lib.Point.prototype = new Roo.lib.Region();
2923 * Portions of this file are based on pieces of Yahoo User Interface Library
2924 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2925 * YUI licensed under the BSD License:
2926 * http://developer.yahoo.net/yui/license.txt
2927 * <script type="text/javascript">
2934 scroll : function(el, args, duration, easing, cb, scope) {
2935 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2938 motion : function(el, args, duration, easing, cb, scope) {
2939 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2942 color : function(el, args, duration, easing, cb, scope) {
2943 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2946 run : function(el, args, duration, easing, cb, scope, type) {
2947 type = type || Roo.lib.AnimBase;
2948 if (typeof easing == "string") {
2949 easing = Roo.lib.Easing[easing];
2951 var anim = new type(el, args, duration, easing);
2952 anim.animateX(function() {
2953 Roo.callback(cb, scope);
2959 * Portions of this file are based on pieces of Yahoo User Interface Library
2960 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2961 * YUI licensed under the BSD License:
2962 * http://developer.yahoo.net/yui/license.txt
2963 * <script type="text/javascript">
2971 if (!libFlyweight) {
2972 libFlyweight = new Roo.Element.Flyweight();
2974 libFlyweight.dom = el;
2975 return libFlyweight;
2978 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2982 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2984 this.init(el, attributes, duration, method);
2988 Roo.lib.AnimBase.fly = fly;
2992 Roo.lib.AnimBase.prototype = {
2994 toString: function() {
2995 var el = this.getEl();
2996 var id = el.id || el.tagName;
2997 return ("Anim " + id);
3001 noNegatives: /width|height|opacity|padding/i,
3002 offsetAttribute: /^((width|height)|(top|left))$/,
3003 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3004 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3008 doMethod: function(attr, start, end) {
3009 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3013 setAttribute: function(attr, val, unit) {
3014 if (this.patterns.noNegatives.test(attr)) {
3015 val = (val > 0) ? val : 0;
3018 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3022 getAttribute: function(attr) {
3023 var el = this.getEl();
3024 var val = fly(el).getStyle(attr);
3026 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3027 return parseFloat(val);
3030 var a = this.patterns.offsetAttribute.exec(attr) || [];
3031 var pos = !!( a[3] );
3032 var box = !!( a[2] );
3035 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3036 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3045 getDefaultUnit: function(attr) {
3046 if (this.patterns.defaultUnit.test(attr)) {
3053 animateX : function(callback, scope) {
3054 var f = function() {
3055 this.onComplete.removeListener(f);
3056 if (typeof callback == "function") {
3057 callback.call(scope || this, this);
3060 this.onComplete.addListener(f, this);
3065 setRuntimeAttribute: function(attr) {
3068 var attributes = this.attributes;
3070 this.runtimeAttributes[attr] = {};
3072 var isset = function(prop) {
3073 return (typeof prop !== 'undefined');
3076 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3080 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3083 if (isset(attributes[attr]['to'])) {
3084 end = attributes[attr]['to'];
3085 } else if (isset(attributes[attr]['by'])) {
3086 if (start.constructor == Array) {
3088 for (var i = 0, len = start.length; i < len; ++i) {
3089 end[i] = start[i] + attributes[attr]['by'][i];
3092 end = start + attributes[attr]['by'];
3096 this.runtimeAttributes[attr].start = start;
3097 this.runtimeAttributes[attr].end = end;
3100 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3104 init: function(el, attributes, duration, method) {
3106 var isAnimated = false;
3109 var startTime = null;
3112 var actualFrames = 0;
3115 el = Roo.getDom(el);
3118 this.attributes = attributes || {};
3121 this.duration = duration || 1;
3124 this.method = method || Roo.lib.Easing.easeNone;
3127 this.useSeconds = true;
3130 this.currentFrame = 0;
3133 this.totalFrames = Roo.lib.AnimMgr.fps;
3136 this.getEl = function() {
3141 this.isAnimated = function() {
3146 this.getStartTime = function() {
3150 this.runtimeAttributes = {};
3153 this.animate = function() {
3154 if (this.isAnimated()) {
3158 this.currentFrame = 0;
3160 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3162 Roo.lib.AnimMgr.registerElement(this);
3166 this.stop = function(finish) {
3168 this.currentFrame = this.totalFrames;
3169 this._onTween.fire();
3171 Roo.lib.AnimMgr.stop(this);
3174 var onStart = function() {
3175 this.onStart.fire();
3177 this.runtimeAttributes = {};
3178 for (var attr in this.attributes) {
3179 this.setRuntimeAttribute(attr);
3184 startTime = new Date();
3188 var onTween = function() {
3190 duration: new Date() - this.getStartTime(),
3191 currentFrame: this.currentFrame
3194 data.toString = function() {
3196 'duration: ' + data.duration +
3197 ', currentFrame: ' + data.currentFrame
3201 this.onTween.fire(data);
3203 var runtimeAttributes = this.runtimeAttributes;
3205 for (var attr in runtimeAttributes) {
3206 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3212 var onComplete = function() {
3213 var actual_duration = (new Date() - startTime) / 1000 ;
3216 duration: actual_duration,
3217 frames: actualFrames,
3218 fps: actualFrames / actual_duration
3221 data.toString = function() {
3223 'duration: ' + data.duration +
3224 ', frames: ' + data.frames +
3225 ', fps: ' + data.fps
3231 this.onComplete.fire(data);
3235 this._onStart = new Roo.util.Event(this);
3236 this.onStart = new Roo.util.Event(this);
3237 this.onTween = new Roo.util.Event(this);
3238 this._onTween = new Roo.util.Event(this);
3239 this.onComplete = new Roo.util.Event(this);
3240 this._onComplete = new Roo.util.Event(this);
3241 this._onStart.addListener(onStart);
3242 this._onTween.addListener(onTween);
3243 this._onComplete.addListener(onComplete);
3248 * Portions of this file are based on pieces of Yahoo User Interface Library
3249 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3250 * YUI licensed under the BSD License:
3251 * http://developer.yahoo.net/yui/license.txt
3252 * <script type="text/javascript">
3256 Roo.lib.AnimMgr = new function() {
3273 this.registerElement = function(tween) {
3274 queue[queue.length] = tween;
3276 tween._onStart.fire();
3281 this.unRegister = function(tween, index) {
3282 tween._onComplete.fire();
3283 index = index || getIndex(tween);
3285 queue.splice(index, 1);
3289 if (tweenCount <= 0) {
3295 this.start = function() {
3296 if (thread === null) {
3297 thread = setInterval(this.run, this.delay);
3302 this.stop = function(tween) {
3304 clearInterval(thread);
3306 for (var i = 0, len = queue.length; i < len; ++i) {
3307 if (queue[0].isAnimated()) {
3308 this.unRegister(queue[0], 0);
3317 this.unRegister(tween);
3322 this.run = function() {
3323 for (var i = 0, len = queue.length; i < len; ++i) {
3324 var tween = queue[i];
3325 if (!tween || !tween.isAnimated()) {
3329 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3331 tween.currentFrame += 1;
3333 if (tween.useSeconds) {
3334 correctFrame(tween);
3336 tween._onTween.fire();
3339 Roo.lib.AnimMgr.stop(tween, i);
3344 var getIndex = function(anim) {
3345 for (var i = 0, len = queue.length; i < len; ++i) {
3346 if (queue[i] == anim) {
3354 var correctFrame = function(tween) {
3355 var frames = tween.totalFrames;
3356 var frame = tween.currentFrame;
3357 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3358 var elapsed = (new Date() - tween.getStartTime());
3361 if (elapsed < tween.duration * 1000) {
3362 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3364 tweak = frames - (frame + 1);
3366 if (tweak > 0 && isFinite(tweak)) {
3367 if (tween.currentFrame + tweak >= frames) {
3368 tweak = frames - (frame + 1);
3371 tween.currentFrame += tweak;
3375 * Portions of this file are based on pieces of Yahoo User Interface Library
3376 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3377 * YUI licensed under the BSD License:
3378 * http://developer.yahoo.net/yui/license.txt
3379 * <script type="text/javascript">
3382 Roo.lib.Bezier = new function() {
3384 this.getPosition = function(points, t) {
3385 var n = points.length;
3388 for (var i = 0; i < n; ++i) {
3389 tmp[i] = [points[i][0], points[i][1]];
3392 for (var j = 1; j < n; ++j) {
3393 for (i = 0; i < n - j; ++i) {
3394 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3395 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3399 return [ tmp[0][0], tmp[0][1] ];
3403 * Portions of this file are based on pieces of Yahoo User Interface Library
3404 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3405 * YUI licensed under the BSD License:
3406 * http://developer.yahoo.net/yui/license.txt
3407 * <script type="text/javascript">
3412 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3413 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3416 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3418 var fly = Roo.lib.AnimBase.fly;
3420 var superclass = Y.ColorAnim.superclass;
3421 var proto = Y.ColorAnim.prototype;
3423 proto.toString = function() {
3424 var el = this.getEl();
3425 var id = el.id || el.tagName;
3426 return ("ColorAnim " + id);
3429 proto.patterns.color = /color$/i;
3430 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3431 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3432 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3433 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3436 proto.parseColor = function(s) {
3437 if (s.length == 3) {
3441 var c = this.patterns.hex.exec(s);
3442 if (c && c.length == 4) {
3443 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3446 c = this.patterns.rgb.exec(s);
3447 if (c && c.length == 4) {
3448 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3451 c = this.patterns.hex3.exec(s);
3452 if (c && c.length == 4) {
3453 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3458 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3459 proto.getAttribute = function(attr) {
3460 var el = this.getEl();
3461 if (this.patterns.color.test(attr)) {
3462 var val = fly(el).getStyle(attr);
3464 if (this.patterns.transparent.test(val)) {
3465 var parent = el.parentNode;
3466 val = fly(parent).getStyle(attr);
3468 while (parent && this.patterns.transparent.test(val)) {
3469 parent = parent.parentNode;
3470 val = fly(parent).getStyle(attr);
3471 if (parent.tagName.toUpperCase() == 'HTML') {
3477 val = superclass.getAttribute.call(this, attr);
3482 proto.getAttribute = function(attr) {
3483 var el = this.getEl();
3484 if (this.patterns.color.test(attr)) {
3485 var val = fly(el).getStyle(attr);
3487 if (this.patterns.transparent.test(val)) {
3488 var parent = el.parentNode;
3489 val = fly(parent).getStyle(attr);
3491 while (parent && this.patterns.transparent.test(val)) {
3492 parent = parent.parentNode;
3493 val = fly(parent).getStyle(attr);
3494 if (parent.tagName.toUpperCase() == 'HTML') {
3500 val = superclass.getAttribute.call(this, attr);
3506 proto.doMethod = function(attr, start, end) {
3509 if (this.patterns.color.test(attr)) {
3511 for (var i = 0, len = start.length; i < len; ++i) {
3512 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3515 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3518 val = superclass.doMethod.call(this, attr, start, end);
3524 proto.setRuntimeAttribute = function(attr) {
3525 superclass.setRuntimeAttribute.call(this, attr);
3527 if (this.patterns.color.test(attr)) {
3528 var attributes = this.attributes;
3529 var start = this.parseColor(this.runtimeAttributes[attr].start);
3530 var end = this.parseColor(this.runtimeAttributes[attr].end);
3532 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3533 end = this.parseColor(attributes[attr].by);
3535 for (var i = 0, len = start.length; i < len; ++i) {
3536 end[i] = start[i] + end[i];
3540 this.runtimeAttributes[attr].start = start;
3541 this.runtimeAttributes[attr].end = end;
3547 * Portions of this file are based on pieces of Yahoo User Interface Library
3548 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3549 * YUI licensed under the BSD License:
3550 * http://developer.yahoo.net/yui/license.txt
3551 * <script type="text/javascript">
3557 easeNone: function (t, b, c, d) {
3558 return c * t / d + b;
3562 easeIn: function (t, b, c, d) {
3563 return c * (t /= d) * t + b;
3567 easeOut: function (t, b, c, d) {
3568 return -c * (t /= d) * (t - 2) + b;
3572 easeBoth: function (t, b, c, d) {
3573 if ((t /= d / 2) < 1) {
3574 return c / 2 * t * t + b;
3577 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3581 easeInStrong: function (t, b, c, d) {
3582 return c * (t /= d) * t * t * t + b;
3586 easeOutStrong: function (t, b, c, d) {
3587 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3591 easeBothStrong: function (t, b, c, d) {
3592 if ((t /= d / 2) < 1) {
3593 return c / 2 * t * t * t * t + b;
3596 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3601 elasticIn: function (t, b, c, d, a, p) {
3605 if ((t /= d) == 1) {
3612 if (!a || a < Math.abs(c)) {
3617 var s = p / (2 * Math.PI) * Math.asin(c / a);
3620 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3624 elasticOut: function (t, b, c, d, a, p) {
3628 if ((t /= d) == 1) {
3635 if (!a || a < Math.abs(c)) {
3640 var s = p / (2 * Math.PI) * Math.asin(c / a);
3643 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3647 elasticBoth: function (t, b, c, d, a, p) {
3652 if ((t /= d / 2) == 2) {
3660 if (!a || a < Math.abs(c)) {
3665 var s = p / (2 * Math.PI) * Math.asin(c / a);
3669 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3670 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3672 return a * Math.pow(2, -10 * (t -= 1)) *
3673 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3678 backIn: function (t, b, c, d, s) {
3679 if (typeof s == 'undefined') {
3682 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3686 backOut: function (t, b, c, d, s) {
3687 if (typeof s == 'undefined') {
3690 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3694 backBoth: function (t, b, c, d, s) {
3695 if (typeof s == 'undefined') {
3699 if ((t /= d / 2 ) < 1) {
3700 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3702 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3706 bounceIn: function (t, b, c, d) {
3707 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3711 bounceOut: function (t, b, c, d) {
3712 if ((t /= d) < (1 / 2.75)) {
3713 return c * (7.5625 * t * t) + b;
3714 } else if (t < (2 / 2.75)) {
3715 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3716 } else if (t < (2.5 / 2.75)) {
3717 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3719 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3723 bounceBoth: function (t, b, c, d) {
3725 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3727 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3730 * Portions of this file are based on pieces of Yahoo User Interface Library
3731 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3732 * YUI licensed under the BSD License:
3733 * http://developer.yahoo.net/yui/license.txt
3734 * <script type="text/javascript">
3738 Roo.lib.Motion = function(el, attributes, duration, method) {
3740 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3744 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3748 var superclass = Y.Motion.superclass;
3749 var proto = Y.Motion.prototype;
3751 proto.toString = function() {
3752 var el = this.getEl();
3753 var id = el.id || el.tagName;
3754 return ("Motion " + id);
3757 proto.patterns.points = /^points$/i;
3759 proto.setAttribute = function(attr, val, unit) {
3760 if (this.patterns.points.test(attr)) {
3761 unit = unit || 'px';
3762 superclass.setAttribute.call(this, 'left', val[0], unit);
3763 superclass.setAttribute.call(this, 'top', val[1], unit);
3765 superclass.setAttribute.call(this, attr, val, unit);
3769 proto.getAttribute = function(attr) {
3770 if (this.patterns.points.test(attr)) {
3772 superclass.getAttribute.call(this, 'left'),
3773 superclass.getAttribute.call(this, 'top')
3776 val = superclass.getAttribute.call(this, attr);
3782 proto.doMethod = function(attr, start, end) {
3785 if (this.patterns.points.test(attr)) {
3786 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3787 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3789 val = superclass.doMethod.call(this, attr, start, end);
3794 proto.setRuntimeAttribute = function(attr) {
3795 if (this.patterns.points.test(attr)) {
3796 var el = this.getEl();
3797 var attributes = this.attributes;
3799 var control = attributes['points']['control'] || [];
3803 if (control.length > 0 && !(control[0] instanceof Array)) {
3804 control = [control];
3807 for (i = 0,len = control.length; i < len; ++i) {
3808 tmp[i] = control[i];
3813 Roo.fly(el).position();
3815 if (isset(attributes['points']['from'])) {
3816 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3819 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3822 start = this.getAttribute('points');
3825 if (isset(attributes['points']['to'])) {
3826 end = translateValues.call(this, attributes['points']['to'], start);
3828 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3829 for (i = 0,len = control.length; i < len; ++i) {
3830 control[i] = translateValues.call(this, control[i], start);
3834 } else if (isset(attributes['points']['by'])) {
3835 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3837 for (i = 0,len = control.length; i < len; ++i) {
3838 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3842 this.runtimeAttributes[attr] = [start];
3844 if (control.length > 0) {
3845 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3848 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3851 superclass.setRuntimeAttribute.call(this, attr);
3855 var translateValues = function(val, start) {
3856 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3857 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3862 var isset = function(prop) {
3863 return (typeof prop !== 'undefined');
3867 * Portions of this file are based on pieces of Yahoo User Interface Library
3868 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3869 * YUI licensed under the BSD License:
3870 * http://developer.yahoo.net/yui/license.txt
3871 * <script type="text/javascript">
3875 Roo.lib.Scroll = function(el, attributes, duration, method) {
3877 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3881 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3885 var superclass = Y.Scroll.superclass;
3886 var proto = Y.Scroll.prototype;
3888 proto.toString = function() {
3889 var el = this.getEl();
3890 var id = el.id || el.tagName;
3891 return ("Scroll " + id);
3894 proto.doMethod = function(attr, start, end) {
3897 if (attr == 'scroll') {
3899 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3900 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3904 val = superclass.doMethod.call(this, attr, start, end);
3909 proto.getAttribute = function(attr) {
3911 var el = this.getEl();
3913 if (attr == 'scroll') {
3914 val = [ el.scrollLeft, el.scrollTop ];
3916 val = superclass.getAttribute.call(this, attr);
3922 proto.setAttribute = function(attr, val, unit) {
3923 var el = this.getEl();
3925 if (attr == 'scroll') {
3926 el.scrollLeft = val[0];
3927 el.scrollTop = val[1];
3929 superclass.setAttribute.call(this, attr, val, unit);
3935 * Ext JS Library 1.1.1
3936 * Copyright(c) 2006-2007, Ext JS, LLC.
3938 * Originally Released Under LGPL - original licence link has changed is not relivant.
3941 * <script type="text/javascript">
3946 * @class Roo.DomHelper
3947 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3948 * 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>.
3951 Roo.DomHelper = function(){
3952 var tempTableEl = null;
3953 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3954 var tableRe = /^table|tbody|tr|td$/i;
3956 // build as innerHTML where available
3958 var createHtml = function(o){
3959 if(typeof o == 'string'){
3968 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3969 if(attr == "style"){
3971 if(typeof s == "function"){
3974 if(typeof s == "string"){
3975 b += ' style="' + s + '"';
3976 }else if(typeof s == "object"){
3979 if(typeof s[key] != "function"){
3980 b += key + ":" + s[key] + ";";
3987 b += ' class="' + o["cls"] + '"';
3988 }else if(attr == "htmlFor"){
3989 b += ' for="' + o["htmlFor"] + '"';
3991 b += " " + attr + '="' + o[attr] + '"';
3995 if(emptyTags.test(o.tag)){
3999 var cn = o.children || o.cn;
4001 //http://bugs.kde.org/show_bug.cgi?id=71506
4002 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4003 for(var i = 0, len = cn.length; i < len; i++) {
4004 b += createHtml(cn[i], b);
4007 b += createHtml(cn, b);
4013 b += "</" + o.tag + ">";
4020 var createDom = function(o, parentNode){
4022 // defininition craeted..
4024 if (o.ns && o.ns != 'html') {
4026 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4027 xmlns[o.ns] = o.xmlns;
4030 if (typeof(xmlns[o.ns]) == 'undefined') {
4031 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4037 if (typeof(o) == 'string') {
4038 return parentNode.appendChild(document.createTextNode(o));
4040 o.tag = o.tag || div;
4041 if (o.ns && Roo.isIE) {
4043 o.tag = o.ns + ':' + o.tag;
4046 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4047 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4050 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4051 attr == "style" || typeof o[attr] == "function") continue;
4053 if(attr=="cls" && Roo.isIE){
4054 el.className = o["cls"];
4056 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4057 else el[attr] = o[attr];
4060 Roo.DomHelper.applyStyles(el, o.style);
4061 var cn = o.children || o.cn;
4063 //http://bugs.kde.org/show_bug.cgi?id=71506
4064 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4065 for(var i = 0, len = cn.length; i < len; i++) {
4066 createDom(cn[i], el);
4073 el.innerHTML = o.html;
4076 parentNode.appendChild(el);
4081 var ieTable = function(depth, s, h, e){
4082 tempTableEl.innerHTML = [s, h, e].join('');
4083 var i = -1, el = tempTableEl;
4090 // kill repeat to save bytes
4094 tbe = '</tbody>'+te,
4100 * Nasty code for IE's broken table implementation
4102 var insertIntoTable = function(tag, where, el, html){
4104 tempTableEl = document.createElement('div');
4109 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4112 if(where == 'beforebegin'){
4116 before = el.nextSibling;
4119 node = ieTable(4, trs, html, tre);
4121 else if(tag == 'tr'){
4122 if(where == 'beforebegin'){
4125 node = ieTable(3, tbs, html, tbe);
4126 } else if(where == 'afterend'){
4127 before = el.nextSibling;
4129 node = ieTable(3, tbs, html, tbe);
4130 } else{ // INTO a TR
4131 if(where == 'afterbegin'){
4132 before = el.firstChild;
4134 node = ieTable(4, trs, html, tre);
4136 } else if(tag == 'tbody'){
4137 if(where == 'beforebegin'){
4140 node = ieTable(2, ts, html, te);
4141 } else if(where == 'afterend'){
4142 before = el.nextSibling;
4144 node = ieTable(2, ts, html, te);
4146 if(where == 'afterbegin'){
4147 before = el.firstChild;
4149 node = ieTable(3, tbs, html, tbe);
4152 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4155 if(where == 'afterbegin'){
4156 before = el.firstChild;
4158 node = ieTable(2, ts, html, te);
4160 el.insertBefore(node, before);
4165 /** True to force the use of DOM instead of html fragments @type Boolean */
4169 * Returns the markup for the passed Element(s) config
4170 * @param {Object} o The Dom object spec (and children)
4173 markup : function(o){
4174 return createHtml(o);
4178 * Applies a style specification to an element
4179 * @param {String/HTMLElement} el The element to apply styles to
4180 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4181 * a function which returns such a specification.
4183 applyStyles : function(el, styles){
4186 if(typeof styles == "string"){
4187 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4189 while ((matches = re.exec(styles)) != null){
4190 el.setStyle(matches[1], matches[2]);
4192 }else if (typeof styles == "object"){
4193 for (var style in styles){
4194 el.setStyle(style, styles[style]);
4196 }else if (typeof styles == "function"){
4197 Roo.DomHelper.applyStyles(el, styles.call());
4203 * Inserts an HTML fragment into the Dom
4204 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4205 * @param {HTMLElement} el The context element
4206 * @param {String} html The HTML fragmenet
4207 * @return {HTMLElement} The new node
4209 insertHtml : function(where, el, html){
4210 where = where.toLowerCase();
4211 if(el.insertAdjacentHTML){
4212 if(tableRe.test(el.tagName)){
4214 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4220 el.insertAdjacentHTML('BeforeBegin', html);
4221 return el.previousSibling;
4223 el.insertAdjacentHTML('AfterBegin', html);
4224 return el.firstChild;
4226 el.insertAdjacentHTML('BeforeEnd', html);
4227 return el.lastChild;
4229 el.insertAdjacentHTML('AfterEnd', html);
4230 return el.nextSibling;
4232 throw 'Illegal insertion point -> "' + where + '"';
4234 var range = el.ownerDocument.createRange();
4238 range.setStartBefore(el);
4239 frag = range.createContextualFragment(html);
4240 el.parentNode.insertBefore(frag, el);
4241 return el.previousSibling;
4244 range.setStartBefore(el.firstChild);
4245 frag = range.createContextualFragment(html);
4246 el.insertBefore(frag, el.firstChild);
4247 return el.firstChild;
4249 el.innerHTML = html;
4250 return el.firstChild;
4254 range.setStartAfter(el.lastChild);
4255 frag = range.createContextualFragment(html);
4256 el.appendChild(frag);
4257 return el.lastChild;
4259 el.innerHTML = html;
4260 return el.lastChild;
4263 range.setStartAfter(el);
4264 frag = range.createContextualFragment(html);
4265 el.parentNode.insertBefore(frag, el.nextSibling);
4266 return el.nextSibling;
4268 throw 'Illegal insertion point -> "' + where + '"';
4272 * Creates new Dom element(s) and inserts them before el
4273 * @param {String/HTMLElement/Element} el The context element
4274 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4275 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4276 * @return {HTMLElement/Roo.Element} The new node
4278 insertBefore : function(el, o, returnElement){
4279 return this.doInsert(el, o, returnElement, "beforeBegin");
4283 * Creates new Dom element(s) and inserts them after el
4284 * @param {String/HTMLElement/Element} el The context element
4285 * @param {Object} o The Dom object spec (and children)
4286 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4287 * @return {HTMLElement/Roo.Element} The new node
4289 insertAfter : function(el, o, returnElement){
4290 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4294 * Creates new Dom element(s) and inserts them as the first child of el
4295 * @param {String/HTMLElement/Element} el The context element
4296 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4297 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4298 * @return {HTMLElement/Roo.Element} The new node
4300 insertFirst : function(el, o, returnElement){
4301 return this.doInsert(el, o, returnElement, "afterBegin");
4305 doInsert : function(el, o, returnElement, pos, sibling){
4306 el = Roo.getDom(el);
4308 if(this.useDom || o.ns){
4309 newNode = createDom(o, null);
4310 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4312 var html = createHtml(o);
4313 newNode = this.insertHtml(pos, el, html);
4315 return returnElement ? Roo.get(newNode, true) : newNode;
4319 * Creates new Dom element(s) and appends them to el
4320 * @param {String/HTMLElement/Element} el The context element
4321 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4322 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4323 * @return {HTMLElement/Roo.Element} The new node
4325 append : function(el, o, returnElement){
4326 el = Roo.getDom(el);
4328 if(this.useDom || o.ns){
4329 newNode = createDom(o, null);
4330 el.appendChild(newNode);
4332 var html = createHtml(o);
4333 newNode = this.insertHtml("beforeEnd", el, html);
4335 return returnElement ? Roo.get(newNode, true) : newNode;
4339 * Creates new Dom element(s) and overwrites the contents of el with them
4340 * @param {String/HTMLElement/Element} el The context element
4341 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4342 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4343 * @return {HTMLElement/Roo.Element} The new node
4345 overwrite : function(el, o, returnElement){
4346 el = Roo.getDom(el);
4349 while (el.childNodes.length) {
4350 el.removeChild(el.firstChild);
4354 el.innerHTML = createHtml(o);
4357 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4361 * Creates a new Roo.DomHelper.Template from the Dom object spec
4362 * @param {Object} o The Dom object spec (and children)
4363 * @return {Roo.DomHelper.Template} The new template
4365 createTemplate : function(o){
4366 var html = createHtml(o);
4367 return new Roo.Template(html);
4373 * Ext JS Library 1.1.1
4374 * Copyright(c) 2006-2007, Ext JS, LLC.
4376 * Originally Released Under LGPL - original licence link has changed is not relivant.
4379 * <script type="text/javascript">
4383 * @class Roo.Template
4384 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4385 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4388 var t = new Roo.Template(
4389 '<div name="{id}">',
4390 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4393 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4395 * 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>.
4397 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4399 Roo.Template = function(html){
4400 if(html instanceof Array){
4401 html = html.join("");
4402 }else if(arguments.length > 1){
4403 html = Array.prototype.join.call(arguments, "");
4409 Roo.Template.prototype = {
4411 * Returns an HTML fragment of this template with the specified values applied.
4412 * @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'})
4413 * @return {String} The HTML fragment
4415 applyTemplate : function(values){
4417 return this.compiled(values);
4419 var useF = this.disableFormats !== true;
4420 var fm = Roo.util.Format, tpl = this;
4421 var fn = function(m, name, format, args){
4423 if(format.substr(0, 5) == "this."){
4424 return tpl.call(format.substr(5), values[name], values);
4427 // quoted values are required for strings in compiled templates,
4428 // but for non compiled we need to strip them
4429 // quoted reversed for jsmin
4430 var re = /^\s*['"](.*)["']\s*$/;
4431 args = args.split(',');
4432 for(var i = 0, len = args.length; i < len; i++){
4433 args[i] = args[i].replace(re, "$1");
4435 args = [values[name]].concat(args);
4437 args = [values[name]];
4439 return fm[format].apply(fm, args);
4442 return values[name] !== undefined ? values[name] : "";
4445 return this.html.replace(this.re, fn);
4449 * Sets the HTML used as the template and optionally compiles it.
4450 * @param {String} html
4451 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4452 * @return {Roo.Template} this
4454 set : function(html, compile){
4456 this.compiled = null;
4464 * True to disable format functions (defaults to false)
4467 disableFormats : false,
4470 * The regular expression used to match template variables
4474 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4477 * Compiles the template into an internal function, eliminating the RegEx overhead.
4478 * @return {Roo.Template} this
4480 compile : function(){
4481 var fm = Roo.util.Format;
4482 var useF = this.disableFormats !== true;
4483 var sep = Roo.isGecko ? "+" : ",";
4484 var fn = function(m, name, format, args){
4486 args = args ? ',' + args : "";
4487 if(format.substr(0, 5) != "this."){
4488 format = "fm." + format + '(';
4490 format = 'this.call("'+ format.substr(5) + '", ';
4494 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4496 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4499 // branched to use + in gecko and [].join() in others
4501 body = "this.compiled = function(values){ return '" +
4502 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4505 body = ["this.compiled = function(values){ return ['"];
4506 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4507 body.push("'].join('');};");
4508 body = body.join('');
4518 // private function used to call members
4519 call : function(fnName, value, allValues){
4520 return this[fnName](value, allValues);
4524 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4525 * @param {String/HTMLElement/Roo.Element} el The context element
4526 * @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'})
4527 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4528 * @return {HTMLElement/Roo.Element} The new node or Element
4530 insertFirst: function(el, values, returnElement){
4531 return this.doInsert('afterBegin', el, values, returnElement);
4535 * Applies the supplied values to the template and inserts the new node(s) before el.
4536 * @param {String/HTMLElement/Roo.Element} el The context element
4537 * @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'})
4538 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4539 * @return {HTMLElement/Roo.Element} The new node or Element
4541 insertBefore: function(el, values, returnElement){
4542 return this.doInsert('beforeBegin', el, values, returnElement);
4546 * Applies the supplied values to the template and inserts the new node(s) after el.
4547 * @param {String/HTMLElement/Roo.Element} el The context element
4548 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4549 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4550 * @return {HTMLElement/Roo.Element} The new node or Element
4552 insertAfter : function(el, values, returnElement){
4553 return this.doInsert('afterEnd', el, values, returnElement);
4557 * Applies the supplied values to the template and appends the new node(s) to el.
4558 * @param {String/HTMLElement/Roo.Element} el The context element
4559 * @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'})
4560 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4561 * @return {HTMLElement/Roo.Element} The new node or Element
4563 append : function(el, values, returnElement){
4564 return this.doInsert('beforeEnd', el, values, returnElement);
4567 doInsert : function(where, el, values, returnEl){
4568 el = Roo.getDom(el);
4569 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4570 return returnEl ? Roo.get(newNode, true) : newNode;
4574 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4575 * @param {String/HTMLElement/Roo.Element} el The context element
4576 * @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'})
4577 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4578 * @return {HTMLElement/Roo.Element} The new node or Element
4580 overwrite : function(el, values, returnElement){
4581 el = Roo.getDom(el);
4582 el.innerHTML = this.applyTemplate(values);
4583 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4587 * Alias for {@link #applyTemplate}
4590 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4593 Roo.DomHelper.Template = Roo.Template;
4596 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4597 * @param {String/HTMLElement} el A DOM element or its id
4598 * @returns {Roo.Template} The created template
4601 Roo.Template.from = function(el){
4602 el = Roo.getDom(el);
4603 return new Roo.Template(el.value || el.innerHTML);
4606 * Ext JS Library 1.1.1
4607 * Copyright(c) 2006-2007, Ext JS, LLC.
4609 * Originally Released Under LGPL - original licence link has changed is not relivant.
4612 * <script type="text/javascript">
4617 * This is code is also distributed under MIT license for use
4618 * with jQuery and prototype JavaScript libraries.
4621 * @class Roo.DomQuery
4622 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).
4624 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>
4627 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.
4629 <h4>Element Selectors:</h4>
4631 <li> <b>*</b> any element</li>
4632 <li> <b>E</b> an element with the tag E</li>
4633 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4634 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4635 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4636 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4638 <h4>Attribute Selectors:</h4>
4639 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4641 <li> <b>E[foo]</b> has an attribute "foo"</li>
4642 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4643 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4644 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4645 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4646 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4647 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4649 <h4>Pseudo Classes:</h4>
4651 <li> <b>E:first-child</b> E is the first child of its parent</li>
4652 <li> <b>E:last-child</b> E is the last child of its parent</li>
4653 <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>
4654 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4655 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4656 <li> <b>E:only-child</b> E is the only child of its parent</li>
4657 <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>
4658 <li> <b>E:first</b> the first E in the resultset</li>
4659 <li> <b>E:last</b> the last E in the resultset</li>
4660 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4661 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4662 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4663 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4664 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4665 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4666 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4667 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4668 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4670 <h4>CSS Value Selectors:</h4>
4672 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4673 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4674 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4675 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4676 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4677 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4681 Roo.DomQuery = function(){
4682 var cache = {}, simpleCache = {}, valueCache = {};
4683 var nonSpace = /\S/;
4684 var trimRe = /^\s+|\s+$/g;
4685 var tplRe = /\{(\d+)\}/g;
4686 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4687 var tagTokenRe = /^(#)?([\w-\*]+)/;
4688 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4690 function child(p, index){
4692 var n = p.firstChild;
4694 if(n.nodeType == 1){
4705 while((n = n.nextSibling) && n.nodeType != 1);
4710 while((n = n.previousSibling) && n.nodeType != 1);
4714 function children(d){
4715 var n = d.firstChild, ni = -1;
4717 var nx = n.nextSibling;
4718 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4728 function byClassName(c, a, v){
4732 var r = [], ri = -1, cn;
4733 for(var i = 0, ci; ci = c[i]; i++){
4734 if((' '+ci.className+' ').indexOf(v) != -1){
4741 function attrValue(n, attr){
4742 if(!n.tagName && typeof n.length != "undefined"){
4751 if(attr == "class" || attr == "className"){
4754 return n.getAttribute(attr) || n[attr];
4758 function getNodes(ns, mode, tagName){
4759 var result = [], ri = -1, cs;
4763 tagName = tagName || "*";
4764 if(typeof ns.getElementsByTagName != "undefined"){
4768 for(var i = 0, ni; ni = ns[i]; i++){
4769 cs = ni.getElementsByTagName(tagName);
4770 for(var j = 0, ci; ci = cs[j]; j++){
4774 }else if(mode == "/" || mode == ">"){
4775 var utag = tagName.toUpperCase();
4776 for(var i = 0, ni, cn; ni = ns[i]; i++){
4777 cn = ni.children || ni.childNodes;
4778 for(var j = 0, cj; cj = cn[j]; j++){
4779 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4784 }else if(mode == "+"){
4785 var utag = tagName.toUpperCase();
4786 for(var i = 0, n; n = ns[i]; i++){
4787 while((n = n.nextSibling) && n.nodeType != 1);
4788 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4792 }else if(mode == "~"){
4793 for(var i = 0, n; n = ns[i]; i++){
4794 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4803 function concat(a, b){
4807 for(var i = 0, l = b.length; i < l; i++){
4813 function byTag(cs, tagName){
4814 if(cs.tagName || cs == document){
4820 var r = [], ri = -1;
4821 tagName = tagName.toLowerCase();
4822 for(var i = 0, ci; ci = cs[i]; i++){
4823 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4830 function byId(cs, attr, id){
4831 if(cs.tagName || cs == document){
4837 var r = [], ri = -1;
4838 for(var i = 0,ci; ci = cs[i]; i++){
4839 if(ci && ci.id == id){
4847 function byAttribute(cs, attr, value, op, custom){
4848 var r = [], ri = -1, st = custom=="{";
4849 var f = Roo.DomQuery.operators[op];
4850 for(var i = 0, ci; ci = cs[i]; i++){
4853 a = Roo.DomQuery.getStyle(ci, attr);
4855 else if(attr == "class" || attr == "className"){
4857 }else if(attr == "for"){
4859 }else if(attr == "href"){
4860 a = ci.getAttribute("href", 2);
4862 a = ci.getAttribute(attr);
4864 if((f && f(a, value)) || (!f && a)){
4871 function byPseudo(cs, name, value){
4872 return Roo.DomQuery.pseudos[name](cs, value);
4875 // This is for IE MSXML which does not support expandos.
4876 // IE runs the same speed using setAttribute, however FF slows way down
4877 // and Safari completely fails so they need to continue to use expandos.
4878 var isIE = window.ActiveXObject ? true : false;
4880 // this eval is stop the compressor from
4881 // renaming the variable to something shorter
4883 /** eval:var:batch */
4888 function nodupIEXml(cs){
4890 cs[0].setAttribute("_nodup", d);
4892 for(var i = 1, len = cs.length; i < len; i++){
4894 if(!c.getAttribute("_nodup") != d){
4895 c.setAttribute("_nodup", d);
4899 for(var i = 0, len = cs.length; i < len; i++){
4900 cs[i].removeAttribute("_nodup");
4909 var len = cs.length, c, i, r = cs, cj, ri = -1;
4910 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4913 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4914 return nodupIEXml(cs);
4918 for(i = 1; c = cs[i]; i++){
4923 for(var j = 0; j < i; j++){
4926 for(j = i+1; cj = cs[j]; j++){
4938 function quickDiffIEXml(c1, c2){
4940 for(var i = 0, len = c1.length; i < len; i++){
4941 c1[i].setAttribute("_qdiff", d);
4944 for(var i = 0, len = c2.length; i < len; i++){
4945 if(c2[i].getAttribute("_qdiff") != d){
4946 r[r.length] = c2[i];
4949 for(var i = 0, len = c1.length; i < len; i++){
4950 c1[i].removeAttribute("_qdiff");
4955 function quickDiff(c1, c2){
4956 var len1 = c1.length;
4960 if(isIE && c1[0].selectSingleNode){
4961 return quickDiffIEXml(c1, c2);
4964 for(var i = 0; i < len1; i++){
4968 for(var i = 0, len = c2.length; i < len; i++){
4969 if(c2[i]._qdiff != d){
4970 r[r.length] = c2[i];
4976 function quickId(ns, mode, root, id){
4978 var d = root.ownerDocument || root;
4979 return d.getElementById(id);
4981 ns = getNodes(ns, mode, "*");
4982 return byId(ns, null, id);
4986 getStyle : function(el, name){
4987 return Roo.fly(el).getStyle(name);
4990 * Compiles a selector/xpath query into a reusable function. The returned function
4991 * takes one parameter "root" (optional), which is the context node from where the query should start.
4992 * @param {String} selector The selector/xpath query
4993 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4994 * @return {Function}
4996 compile : function(path, type){
4997 type = type || "select";
4999 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5000 var q = path, mode, lq;
5001 var tk = Roo.DomQuery.matchers;
5002 var tklen = tk.length;
5005 // accept leading mode switch
5006 var lmode = q.match(modeRe);
5007 if(lmode && lmode[1]){
5008 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5009 q = q.replace(lmode[1], "");
5011 // strip leading slashes
5012 while(path.substr(0, 1)=="/"){
5013 path = path.substr(1);
5016 while(q && lq != q){
5018 var tm = q.match(tagTokenRe);
5019 if(type == "select"){
5022 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5024 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5026 q = q.replace(tm[0], "");
5027 }else if(q.substr(0, 1) != '@'){
5028 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5033 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5035 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5037 q = q.replace(tm[0], "");
5040 while(!(mm = q.match(modeRe))){
5041 var matched = false;
5042 for(var j = 0; j < tklen; j++){
5044 var m = q.match(t.re);
5046 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5049 q = q.replace(m[0], "");
5054 // prevent infinite loop on bad selector
5056 throw 'Error parsing selector, parsing failed at "' + q + '"';
5060 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5061 q = q.replace(mm[1], "");
5064 fn[fn.length] = "return nodup(n);\n}";
5067 * list of variables that need from compression as they are used by eval.
5077 * eval:var:byClassName
5079 * eval:var:byAttribute
5080 * eval:var:attrValue
5088 * Selects a group of elements.
5089 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5090 * @param {Node} root (optional) The start of the query (defaults to document).
5093 select : function(path, root, type){
5094 if(!root || root == document){
5097 if(typeof root == "string"){
5098 root = document.getElementById(root);
5100 var paths = path.split(",");
5102 for(var i = 0, len = paths.length; i < len; i++){
5103 var p = paths[i].replace(trimRe, "");
5105 cache[p] = Roo.DomQuery.compile(p);
5107 throw p + " is not a valid selector";
5110 var result = cache[p](root);
5111 if(result && result != document){
5112 results = results.concat(result);
5115 if(paths.length > 1){
5116 return nodup(results);
5122 * Selects a single element.
5123 * @param {String} selector The selector/xpath query
5124 * @param {Node} root (optional) The start of the query (defaults to document).
5127 selectNode : function(path, root){
5128 return Roo.DomQuery.select(path, root)[0];
5132 * Selects the value of a node, optionally replacing null with the defaultValue.
5133 * @param {String} selector The selector/xpath query
5134 * @param {Node} root (optional) The start of the query (defaults to document).
5135 * @param {String} defaultValue
5137 selectValue : function(path, root, defaultValue){
5138 path = path.replace(trimRe, "");
5139 if(!valueCache[path]){
5140 valueCache[path] = Roo.DomQuery.compile(path, "select");
5142 var n = valueCache[path](root);
5143 n = n[0] ? n[0] : n;
5144 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5145 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5149 * Selects the value of a node, parsing integers and floats.
5150 * @param {String} selector The selector/xpath query
5151 * @param {Node} root (optional) The start of the query (defaults to document).
5152 * @param {Number} defaultValue
5155 selectNumber : function(path, root, defaultValue){
5156 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5157 return parseFloat(v);
5161 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5162 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5163 * @param {String} selector The simple selector to test
5166 is : function(el, ss){
5167 if(typeof el == "string"){
5168 el = document.getElementById(el);
5170 var isArray = (el instanceof Array);
5171 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5172 return isArray ? (result.length == el.length) : (result.length > 0);
5176 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5177 * @param {Array} el An array of elements to filter
5178 * @param {String} selector The simple selector to test
5179 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5180 * the selector instead of the ones that match
5183 filter : function(els, ss, nonMatches){
5184 ss = ss.replace(trimRe, "");
5185 if(!simpleCache[ss]){
5186 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5188 var result = simpleCache[ss](els);
5189 return nonMatches ? quickDiff(result, els) : result;
5193 * Collection of matching regular expressions and code snippets.
5197 select: 'n = byClassName(n, null, " {1} ");'
5199 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5200 select: 'n = byPseudo(n, "{1}", "{2}");'
5202 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5203 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5206 select: 'n = byId(n, null, "{1}");'
5209 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5214 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5215 * 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, > <.
5218 "=" : function(a, v){
5221 "!=" : function(a, v){
5224 "^=" : function(a, v){
5225 return a && a.substr(0, v.length) == v;
5227 "$=" : function(a, v){
5228 return a && a.substr(a.length-v.length) == v;
5230 "*=" : function(a, v){
5231 return a && a.indexOf(v) !== -1;
5233 "%=" : function(a, v){
5234 return (a % v) == 0;
5236 "|=" : function(a, v){
5237 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5239 "~=" : function(a, v){
5240 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5245 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5246 * and the argument (if any) supplied in the selector.
5249 "first-child" : function(c){
5250 var r = [], ri = -1, n;
5251 for(var i = 0, ci; ci = n = c[i]; i++){
5252 while((n = n.previousSibling) && n.nodeType != 1);
5260 "last-child" : function(c){
5261 var r = [], ri = -1, n;
5262 for(var i = 0, ci; ci = n = c[i]; i++){
5263 while((n = n.nextSibling) && n.nodeType != 1);
5271 "nth-child" : function(c, a) {
5272 var r = [], ri = -1;
5273 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5274 var f = (m[1] || 1) - 0, l = m[2] - 0;
5275 for(var i = 0, n; n = c[i]; i++){
5276 var pn = n.parentNode;
5277 if (batch != pn._batch) {
5279 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5280 if(cn.nodeType == 1){
5287 if (l == 0 || n.nodeIndex == l){
5290 } else if ((n.nodeIndex + l) % f == 0){
5298 "only-child" : function(c){
5299 var r = [], ri = -1;;
5300 for(var i = 0, ci; ci = c[i]; i++){
5301 if(!prev(ci) && !next(ci)){
5308 "empty" : function(c){
5309 var r = [], ri = -1;
5310 for(var i = 0, ci; ci = c[i]; i++){
5311 var cns = ci.childNodes, j = 0, cn, empty = true;
5314 if(cn.nodeType == 1 || cn.nodeType == 3){
5326 "contains" : function(c, v){
5327 var r = [], ri = -1;
5328 for(var i = 0, ci; ci = c[i]; i++){
5329 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5336 "nodeValue" : function(c, v){
5337 var r = [], ri = -1;
5338 for(var i = 0, ci; ci = c[i]; i++){
5339 if(ci.firstChild && ci.firstChild.nodeValue == v){
5346 "checked" : function(c){
5347 var r = [], ri = -1;
5348 for(var i = 0, ci; ci = c[i]; i++){
5349 if(ci.checked == true){
5356 "not" : function(c, ss){
5357 return Roo.DomQuery.filter(c, ss, true);
5360 "odd" : function(c){
5361 return this["nth-child"](c, "odd");
5364 "even" : function(c){
5365 return this["nth-child"](c, "even");
5368 "nth" : function(c, a){
5369 return c[a-1] || [];
5372 "first" : function(c){
5376 "last" : function(c){
5377 return c[c.length-1] || [];
5380 "has" : function(c, ss){
5381 var s = Roo.DomQuery.select;
5382 var r = [], ri = -1;
5383 for(var i = 0, ci; ci = c[i]; i++){
5384 if(s(ss, ci).length > 0){
5391 "next" : function(c, ss){
5392 var is = Roo.DomQuery.is;
5393 var r = [], ri = -1;
5394 for(var i = 0, ci; ci = c[i]; i++){
5403 "prev" : function(c, ss){
5404 var is = Roo.DomQuery.is;
5405 var r = [], ri = -1;
5406 for(var i = 0, ci; ci = c[i]; i++){
5419 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5420 * @param {String} path The selector/xpath query
5421 * @param {Node} root (optional) The start of the query (defaults to document).
5426 Roo.query = Roo.DomQuery.select;