4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
90 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
93 enableGarbageCollector : true,
96 * True to automatically purge event listeners after uncaching an element (defaults to false).
97 * Note: this only happens if enableGarbageCollector is true.
100 enableListenerCollection:false,
103 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
104 * the IE insecure content warning (defaults to javascript:false).
107 SSL_SECURE_URL : "javascript:false",
110 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
111 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
114 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
116 emptyFn : function(){},
119 * Copies all the properties of config to obj if they don't already exist.
120 * @param {Object} obj The receiver of the properties
121 * @param {Object} config The source of the properties
122 * @return {Object} returns obj
124 applyIf : function(o, c){
127 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
134 * Applies event listeners to elements by selectors when the document is ready.
135 * The event name is specified with an @ suffix.
138 // add a listener for click on all anchors in element with id foo
139 '#foo a@click' : function(e, t){
143 // add the same listener to multiple selectors (separated by comma BEFORE the @)
144 '#foo a, #bar span.some-class@mouseover' : function(){
149 * @param {Object} obj The list of behaviors to apply
151 addBehaviors : function(o){
153 Roo.onReady(function(){
158 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
160 var parts = b.split('@');
161 if(parts[1]){ // for Object prototype breakers
164 cache[s] = Roo.select(s);
166 cache[s].on(parts[1], o[b]);
173 * Generates unique ids. If the element already has an id, it is unchanged
174 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
175 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
176 * @return {String} The generated Id.
178 id : function(el, prefix){
179 prefix = prefix || "roo-gen";
181 var id = prefix + (++idSeed);
182 return el ? (el.id ? el.id : (el.id = id)) : id;
187 * Extends one class with another class and optionally overrides members with the passed literal. This class
188 * also adds the function "override()" to the class that can be used to override
189 * members on an instance.
190 * @param {Object} subclass The class inheriting the functionality
191 * @param {Object} superclass The class being extended
192 * @param {Object} overrides (optional) A literal with members
197 var io = function(o){
202 return function(sb, sp, overrides){
203 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
206 sb = function(){sp.apply(this, arguments);};
208 var F = function(){}, sbp, spp = sp.prototype;
210 sbp = sb.prototype = new F();
214 if(spp.constructor == Object.prototype.constructor){
219 sb.override = function(o){
223 Roo.override(sb, overrides);
229 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
231 Roo.override(MyClass, {
232 newMethod1: function(){
235 newMethod2: function(foo){
240 * @param {Object} origclass The class to override
241 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
242 * containing one or more methods.
245 override : function(origclass, overrides){
247 var p = origclass.prototype;
248 for(var method in overrides){
249 p[method] = overrides[method];
254 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
256 Roo.namespace('Company', 'Company.data');
257 Company.Widget = function() { ... }
258 Company.data.CustomStore = function(config) { ... }
260 * @param {String} namespace1
261 * @param {String} namespace2
262 * @param {String} etc
265 namespace : function(){
266 var a=arguments, o=null, i, j, d, rt;
267 for (i=0; i<a.length; ++i) {
271 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
272 for (j=1; j<d.length; ++j) {
273 o[d[j]]=o[d[j]] || {};
279 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
281 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
282 Roo.factory(conf, Roo.data);
284 * @param {String} classname
285 * @param {String} namespace (optional)
289 factory : function(c, ns)
291 // no xtype, no ns or c.xns - or forced off by c.xns
292 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
295 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
296 if (c.constructor == ns[c.xtype]) {// already created...
300 console.log("Roo.Factory(" + c.xtype + ")");
301 var ret = new ns[c.xtype](c);
305 c.xns = false; // prevent recursion..
310 * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2". Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
314 urlEncode : function(o){
320 var ov = o[key], k = encodeURIComponent(key);
321 var type = typeof ov;
322 if(type == 'undefined'){
324 }else if(type != "function" && type != "object"){
325 buf.push(k, "=", encodeURIComponent(ov), "&");
326 }else if(ov instanceof Array){
328 for(var i = 0, len = ov.length; i < len; i++) {
329 buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
341 * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
342 * @param {String} string
343 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
344 * @return {Object} A literal with members
346 urlDecode : function(string, overwrite){
347 if(!string || !string.length){
351 var pairs = string.split('&');
352 var pair, name, value;
353 for(var i = 0, len = pairs.length; i < len; i++){
354 pair = pairs[i].split('=');
355 name = decodeURIComponent(pair[0]);
356 value = decodeURIComponent(pair[1]);
357 if(overwrite !== true){
358 if(typeof obj[name] == "undefined"){
360 }else if(typeof obj[name] == "string"){
361 obj[name] = [obj[name]];
362 obj[name].push(value);
364 obj[name].push(value);
374 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
375 * passed array is not really an array, your function is called once with it.
376 * The supplied function is called with (Object item, Number index, Array allItems).
377 * @param {Array/NodeList/Mixed} array
378 * @param {Function} fn
379 * @param {Object} scope
381 each : function(array, fn, scope){
382 if(typeof array.length == "undefined" || typeof array == "string"){
385 for(var i = 0, len = array.length; i < len; i++){
386 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
391 combine : function(){
392 var as = arguments, l = as.length, r = [];
393 for(var i = 0; i < l; i++){
395 if(a instanceof Array){
397 }else if(a.length !== undefined && !a.substr){
398 r = r.concat(Array.prototype.slice.call(a, 0));
407 * Escapes the passed string for use in a regular expression
408 * @param {String} str
411 escapeRe : function(s) {
412 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
416 callback : function(cb, scope, args, delay){
417 if(typeof cb == "function"){
419 cb.defer(delay, scope, args || []);
421 cb.apply(scope, args || []);
427 * Return the dom node for the passed string (id), dom node, or Roo.Element
428 * @param {String/HTMLElement/Roo.Element} el
429 * @return HTMLElement
431 getDom : function(el){
435 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
439 * Shorthand for {@link Roo.ComponentMgr#get}
441 * @return Roo.Component
443 getCmp : function(id){
444 return Roo.ComponentMgr.get(id);
447 num : function(v, defaultValue){
448 if(typeof v != 'number'){
454 destroy : function(){
455 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
459 as.removeAllListeners();
463 if(typeof as.purgeListeners == 'function'){
466 if(typeof as.destroy == 'function'){
473 // inpired by a similar function in mootools library
475 * Returns the type of object that is passed in. If the object passed in is null or undefined it
476 * return false otherwise it returns one of the following values:<ul>
477 * <li><b>string</b>: If the object passed is a string</li>
478 * <li><b>number</b>: If the object passed is a number</li>
479 * <li><b>boolean</b>: If the object passed is a boolean value</li>
480 * <li><b>function</b>: If the object passed is a function reference</li>
481 * <li><b>object</b>: If the object passed is an object</li>
482 * <li><b>array</b>: If the object passed is an array</li>
483 * <li><b>regexp</b>: If the object passed is a regular expression</li>
484 * <li><b>element</b>: If the object passed is a DOM Element</li>
485 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
486 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
487 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
488 * @param {Mixed} object
492 if(o === undefined || o === null){
499 if(t == 'object' && o.nodeName) {
501 case 1: return 'element';
502 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
505 if(t == 'object' || t == 'function') {
506 switch(o.constructor) {
507 case Array: return 'array';
508 case RegExp: return 'regexp';
510 if(typeof o.length == 'number' && typeof o.item == 'function') {
518 * Returns true if the passed value is null, undefined or an empty string (optional).
519 * @param {Mixed} value The value to test
520 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
523 isEmpty : function(v, allowBlank){
524 return v === null || v === undefined || (!allowBlank ? v === '' : false);
538 isBorderBox : isBorderBox,
540 isWindows : isWindows,
547 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
548 * you may want to set this to true.
551 useShims : ((isIE && !isIE7) || (isGecko && isMac))
557 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
558 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
561 * Ext JS Library 1.1.1
562 * Copyright(c) 2006-2007, Ext JS, LLC.
564 * Originally Released Under LGPL - original licence link has changed is not relivant.
567 * <script type="text/javascript">
571 // wrappedn so fnCleanup is not in global scope...
573 function fnCleanUp() {
574 var p = Function.prototype;
575 delete p.createSequence;
577 delete p.createDelegate;
578 delete p.createCallback;
579 delete p.createInterceptor;
581 window.detachEvent("onunload", fnCleanUp);
583 window.attachEvent("onunload", fnCleanUp);
590 * These functions are available on every Function object (any JavaScript function).
592 Roo.apply(Function.prototype, {
594 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
595 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
596 * Will create a function that is bound to those 2 args.
597 * @return {Function} The new function
599 createCallback : function(/*args...*/){
600 // make args available, in function below
601 var args = arguments;
604 return method.apply(window, args);
609 * Creates a delegate (callback) that sets the scope to obj.
610 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
611 * Will create a function that is automatically scoped to this.
612 * @param {Object} obj (optional) The object for which the scope is set
613 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
614 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
615 * if a number the args are inserted at the specified position
616 * @return {Function} The new function
618 createDelegate : function(obj, args, appendArgs){
621 var callArgs = args || arguments;
622 if(appendArgs === true){
623 callArgs = Array.prototype.slice.call(arguments, 0);
624 callArgs = callArgs.concat(args);
625 }else if(typeof appendArgs == "number"){
626 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
627 var applyArgs = [appendArgs, 0].concat(args); // create method call params
628 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
630 return method.apply(obj || window, callArgs);
635 * Calls this function after the number of millseconds specified.
636 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
637 * @param {Object} obj (optional) The object for which the scope is set
638 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
639 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
640 * if a number the args are inserted at the specified position
641 * @return {Number} The timeout id that can be used with clearTimeout
643 defer : function(millis, obj, args, appendArgs){
644 var fn = this.createDelegate(obj, args, appendArgs);
646 return setTimeout(fn, millis);
652 * Create a combined function call sequence of the original function + the passed function.
653 * The resulting function returns the results of the original function.
654 * The passed fcn is called with the parameters of the original function
655 * @param {Function} fcn The function to sequence
656 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
657 * @return {Function} The new function
659 createSequence : function(fcn, scope){
660 if(typeof fcn != "function"){
665 var retval = method.apply(this || window, arguments);
666 fcn.apply(scope || this || window, arguments);
672 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
673 * The resulting function returns the results of the original function.
674 * The passed fcn is called with the parameters of the original function.
676 * @param {Function} fcn The function to call before the original
677 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
678 * @return {Function} The new function
680 createInterceptor : function(fcn, scope){
681 if(typeof fcn != "function"){
688 if(fcn.apply(scope || this || window, arguments) === false){
691 return method.apply(this || window, arguments);
697 * Ext JS Library 1.1.1
698 * Copyright(c) 2006-2007, Ext JS, LLC.
700 * Originally Released Under LGPL - original licence link has changed is not relivant.
703 * <script type="text/javascript">
706 Roo.applyIf(String, {
711 * Escapes the passed string for ' and \
712 * @param {String} string The string to escape
713 * @return {String} The escaped string
716 escape : function(string) {
717 return string.replace(/('|\\)/g, "\\$1");
721 * Pads the left side of a string with a specified character. This is especially useful
722 * for normalizing number and date strings. Example usage:
724 var s = String.leftPad('123', 5, '0');
725 // s now contains the string: '00123'
727 * @param {String} string The original string
728 * @param {Number} size The total length of the output string
729 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
730 * @return {String} The padded string
733 leftPad : function (val, size, ch) {
734 var result = new String(val);
735 if(ch === null || ch === undefined || ch === '') {
738 while (result.length < size) {
739 result = ch + result;
745 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
746 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
748 var cls = 'my-class', text = 'Some text';
749 var s = String.format('<div class="{0}">{1}</div>', cls, text);
750 // s now contains the string: '<div class="my-class">Some text</div>'
752 * @param {String} string The tokenized string to be formatted
753 * @param {String} value1 The value to replace token {0}
754 * @param {String} value2 Etc...
755 * @return {String} The formatted string
758 format : function(format){
759 var args = Array.prototype.slice.call(arguments, 1);
760 return format.replace(/\{(\d+)\}/g, function(m, i){
761 return Roo.util.Format.htmlEncode(args[i]);
767 * Utility function that allows you to easily switch a string between two alternating values. The passed value
768 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
769 * they are already different, the first value passed in is returned. Note that this method returns the new value
770 * but does not change the current string.
772 // alternate sort directions
773 sort = sort.toggle('ASC', 'DESC');
775 // instead of conditional logic:
776 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
778 * @param {String} value The value to compare to the current string
779 * @param {String} other The new value to use if the string already equals the first value passed in
780 * @return {String} The new value
783 String.prototype.toggle = function(value, other){
784 return this == value ? other : value;
787 * Ext JS Library 1.1.1
788 * Copyright(c) 2006-2007, Ext JS, LLC.
790 * Originally Released Under LGPL - original licence link has changed is not relivant.
793 * <script type="text/javascript">
799 Roo.applyIf(Number.prototype, {
801 * Checks whether or not the current number is within a desired range. If the number is already within the
802 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
803 * exceeded. Note that this method returns the constrained value but does not change the current number.
804 * @param {Number} min The minimum number in the range
805 * @param {Number} max The maximum number in the range
806 * @return {Number} The constrained value if outside the range, otherwise the current value
808 constrain : function(min, max){
809 return Math.min(Math.max(this, min), max);
813 * Ext JS Library 1.1.1
814 * Copyright(c) 2006-2007, Ext JS, LLC.
816 * Originally Released Under LGPL - original licence link has changed is not relivant.
819 * <script type="text/javascript">
824 Roo.applyIf(Array.prototype, {
826 * Checks whether or not the specified object exists in the array.
827 * @param {Object} o The object to check for
828 * @return {Number} The index of o in the array (or -1 if it is not found)
830 indexOf : function(o){
831 for (var i = 0, len = this.length; i < len; i++){
832 if(this[i] == o) return i;
838 * Removes the specified object from the array. If the object is not found nothing happens.
839 * @param {Object} o The object to remove
841 remove : function(o){
842 var index = this.indexOf(o);
844 this.splice(index, 1);
849 * Ext JS Library 1.1.1
850 * Copyright(c) 2006-2007, Ext JS, LLC.
852 * Originally Released Under LGPL - original licence link has changed is not relivant.
855 * <script type="text/javascript">
861 * The date parsing and format syntax is a subset of
862 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
863 * supported will provide results equivalent to their PHP versions.
865 * Following is the list of all currently supported formats:
868 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
870 Format Output Description
871 ------ ---------- --------------------------------------------------------------
872 d 10 Day of the month, 2 digits with leading zeros
873 D Wed A textual representation of a day, three letters
874 j 10 Day of the month without leading zeros
875 l Wednesday A full textual representation of the day of the week
876 S th English ordinal day of month suffix, 2 chars (use with j)
877 w 3 Numeric representation of the day of the week
878 z 9 The julian date, or day of the year (0-365)
879 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
880 F January A full textual representation of the month
881 m 01 Numeric representation of a month, with leading zeros
882 M Jan Month name abbreviation, three letters
883 n 1 Numeric representation of a month, without leading zeros
884 t 31 Number of days in the given month
885 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
886 Y 2007 A full numeric representation of a year, 4 digits
887 y 07 A two digit representation of a year
888 a pm Lowercase Ante meridiem and Post meridiem
889 A PM Uppercase Ante meridiem and Post meridiem
890 g 3 12-hour format of an hour without leading zeros
891 G 15 24-hour format of an hour without leading zeros
892 h 03 12-hour format of an hour with leading zeros
893 H 15 24-hour format of an hour with leading zeros
894 i 05 Minutes with leading zeros
895 s 01 Seconds, with leading zeros
896 O -0600 Difference to Greenwich time (GMT) in hours
897 T CST Timezone setting of the machine running the code
898 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
901 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
903 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
904 document.write(dt.format('Y-m-d')); //2007-01-10
905 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
906 document.write(dt.format('l, \\t\\he dS of F Y h:i:s A')); //Wednesday, the 10th of January 2007 03:05:01 PM
909 * Here are some standard date/time patterns that you might find helpful. They
910 * are not part of the source of Date.js, but to use them you can simply copy this
911 * block of code into any script that is included after Date.js and they will also become
912 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
915 ISO8601Long:"Y-m-d H:i:s",
916 ISO8601Short:"Y-m-d",
918 LongDate: "l, F d, Y",
919 FullDateTime: "l, F d, Y g:i:s A",
923 SortableDateTime: "Y-m-d\\TH:i:s",
924 UniversalSortableDateTime: "Y-m-d H:i:sO",
932 document.write(dt.format(Date.patterns.ShortDate));
937 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
938 * They generate precompiled functions from date formats instead of parsing and
939 * processing the pattern every time you format a date. These functions are available
940 * on every Date object (any javascript function).
942 * The original article and download are here:
943 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
950 Returns the number of milliseconds between this date and date
951 @param {Date} date (optional) Defaults to now
952 @return {Number} The diff in milliseconds
953 @member Date getElapsed
955 Date.prototype.getElapsed = function(date) {
956 return Math.abs((date || new Date()).getTime()-this.getTime());
958 // was in date file..
962 Date.parseFunctions = {count:0};
964 Date.parseRegexes = [];
966 Date.formatFunctions = {count:0};
969 Date.prototype.dateFormat = function(format) {
970 if (Date.formatFunctions[format] == null) {
971 Date.createNewFormat(format);
973 var func = Date.formatFunctions[format];
979 * Formats a date given the supplied format string
980 * @param {String} format The format string
981 * @return {String} The formatted date
984 Date.prototype.format = Date.prototype.dateFormat;
987 Date.createNewFormat = function(format) {
988 var funcName = "format" + Date.formatFunctions.count++;
989 Date.formatFunctions[format] = funcName;
990 var code = "Date.prototype." + funcName + " = function(){return ";
993 for (var i = 0; i < format.length; ++i) {
994 ch = format.charAt(i);
995 if (!special && ch == "\\") {
1000 code += "'" + String.escape(ch) + "' + ";
1003 code += Date.getFormatCode(ch);
1006 /** eval:var:zzzzzzzzzzzzz */
1007 eval(code.substring(0, code.length - 3) + ";}");
1011 Date.getFormatCode = function(character) {
1012 switch (character) {
1014 return "String.leftPad(this.getDate(), 2, '0') + ";
1016 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1018 return "this.getDate() + ";
1020 return "Date.dayNames[this.getDay()] + ";
1022 return "this.getSuffix() + ";
1024 return "this.getDay() + ";
1026 return "this.getDayOfYear() + ";
1028 return "this.getWeekOfYear() + ";
1030 return "Date.monthNames[this.getMonth()] + ";
1032 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1034 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1036 return "(this.getMonth() + 1) + ";
1038 return "this.getDaysInMonth() + ";
1040 return "(this.isLeapYear() ? 1 : 0) + ";
1042 return "this.getFullYear() + ";
1044 return "('' + this.getFullYear()).substring(2, 4) + ";
1046 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1048 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1050 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1052 return "this.getHours() + ";
1054 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1056 return "String.leftPad(this.getHours(), 2, '0') + ";
1058 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1060 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1062 return "this.getGMTOffset() + ";
1064 return "this.getTimezone() + ";
1066 return "(this.getTimezoneOffset() * -60) + ";
1068 return "'" + String.escape(character) + "' + ";
1073 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1074 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1075 * the date format that is not specified will default to the current date value for that part. Time parts can also
1076 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1077 * string or the parse operation will fail.
1080 //dt = Fri May 25 2007 (current date)
1081 var dt = new Date();
1083 //dt = Thu May 25 2006 (today's month/day in 2006)
1084 dt = Date.parseDate("2006", "Y");
1086 //dt = Sun Jan 15 2006 (all date parts specified)
1087 dt = Date.parseDate("2006-1-15", "Y-m-d");
1089 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1090 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1092 * @param {String} input The unparsed date as a string
1093 * @param {String} format The format the date is in
1094 * @return {Date} The parsed date
1097 Date.parseDate = function(input, format) {
1098 if (Date.parseFunctions[format] == null) {
1099 Date.createParser(format);
1101 var func = Date.parseFunctions[format];
1102 return Date[func](input);
1107 Date.createParser = function(format) {
1108 var funcName = "parse" + Date.parseFunctions.count++;
1109 var regexNum = Date.parseRegexes.length;
1110 var currentGroup = 1;
1111 Date.parseFunctions[format] = funcName;
1113 var code = "Date." + funcName + " = function(input){\n"
1114 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1115 + "var d = new Date();\n"
1116 + "y = d.getFullYear();\n"
1117 + "m = d.getMonth();\n"
1118 + "d = d.getDate();\n"
1119 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1120 + "if (results && results.length > 0) {";
1123 var special = false;
1125 for (var i = 0; i < format.length; ++i) {
1126 ch = format.charAt(i);
1127 if (!special && ch == "\\") {
1132 regex += String.escape(ch);
1135 var obj = Date.formatCodeToRegex(ch, currentGroup);
1136 currentGroup += obj.g;
1138 if (obj.g && obj.c) {
1144 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1145 + "{v = new Date(y, m, d, h, i, s);}\n"
1146 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1147 + "{v = new Date(y, m, d, h, i);}\n"
1148 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1149 + "{v = new Date(y, m, d, h);}\n"
1150 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1151 + "{v = new Date(y, m, d);}\n"
1152 + "else if (y >= 0 && m >= 0)\n"
1153 + "{v = new Date(y, m);}\n"
1154 + "else if (y >= 0)\n"
1155 + "{v = new Date(y);}\n"
1156 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1157 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1158 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1161 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1162 /** eval:var:zzzzzzzzzzzzz */
1167 Date.formatCodeToRegex = function(character, currentGroup) {
1168 switch (character) {
1172 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1175 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1176 s:"(\\d{1,2})"}; // day of month without leading zeroes
1179 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1180 s:"(\\d{2})"}; // day of month with leading zeroes
1184 s:"(?:" + Date.dayNames.join("|") + ")"};
1188 s:"(?:st|nd|rd|th)"};
1203 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1204 s:"(" + Date.monthNames.join("|") + ")"};
1207 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1208 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1211 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1212 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1215 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1216 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1227 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1231 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1232 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1236 c:"if (results[" + currentGroup + "] == 'am') {\n"
1237 + "if (h == 12) { h = 0; }\n"
1238 + "} else { if (h < 12) { h += 12; }}",
1242 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1243 + "if (h == 12) { h = 0; }\n"
1244 + "} else { if (h < 12) { h += 12; }}",
1249 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1250 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1254 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1255 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1258 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1262 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1267 "o = results[", currentGroup, "];\n",
1268 "var sn = o.substring(0,1);\n", // get + / - sign
1269 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1270 "var mn = o.substring(3,5) % 60;\n", // get minutes
1271 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1272 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1278 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1281 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1282 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1283 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1287 s:String.escape(character)};
1292 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1293 * @return {String} The abbreviated timezone name (e.g. 'CST')
1295 Date.prototype.getTimezone = function() {
1296 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1300 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1301 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1303 Date.prototype.getGMTOffset = function() {
1304 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1305 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1306 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1310 * Get the numeric day number of the year, adjusted for leap year.
1311 * @return {Number} 0 through 364 (365 in leap years)
1313 Date.prototype.getDayOfYear = function() {
1315 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1316 for (var i = 0; i < this.getMonth(); ++i) {
1317 num += Date.daysInMonth[i];
1319 return num + this.getDate() - 1;
1323 * Get the string representation of the numeric week number of the year
1324 * (equivalent to the format specifier 'W').
1325 * @return {String} '00' through '52'
1327 Date.prototype.getWeekOfYear = function() {
1328 // Skip to Thursday of this week
1329 var now = this.getDayOfYear() + (4 - this.getDay());
1330 // Find the first Thursday of the year
1331 var jan1 = new Date(this.getFullYear(), 0, 1);
1332 var then = (7 - jan1.getDay() + 4);
1333 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1337 * Whether or not the current date is in a leap year.
1338 * @return {Boolean} True if the current date is in a leap year, else false
1340 Date.prototype.isLeapYear = function() {
1341 var year = this.getFullYear();
1342 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1346 * Get the first day of the current month, adjusted for leap year. The returned value
1347 * is the numeric day index within the week (0-6) which can be used in conjunction with
1348 * the {@link #monthNames} array to retrieve the textual day name.
1351 var dt = new Date('1/10/2007');
1352 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1354 * @return {Number} The day number (0-6)
1356 Date.prototype.getFirstDayOfMonth = function() {
1357 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1358 return (day < 0) ? (day + 7) : day;
1362 * Get the last day of the current month, adjusted for leap year. The returned value
1363 * is the numeric day index within the week (0-6) which can be used in conjunction with
1364 * the {@link #monthNames} array to retrieve the textual day name.
1367 var dt = new Date('1/10/2007');
1368 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1370 * @return {Number} The day number (0-6)
1372 Date.prototype.getLastDayOfMonth = function() {
1373 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1374 return (day < 0) ? (day + 7) : day;
1379 * Get the first date of this date's month
1382 Date.prototype.getFirstDateOfMonth = function() {
1383 return new Date(this.getFullYear(), this.getMonth(), 1);
1387 * Get the last date of this date's month
1390 Date.prototype.getLastDateOfMonth = function() {
1391 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1394 * Get the number of days in the current month, adjusted for leap year.
1395 * @return {Number} The number of days in the month
1397 Date.prototype.getDaysInMonth = function() {
1398 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1399 return Date.daysInMonth[this.getMonth()];
1403 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1404 * @return {String} 'st, 'nd', 'rd' or 'th'
1406 Date.prototype.getSuffix = function() {
1407 switch (this.getDate()) {
1424 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1427 * An array of textual month names.
1428 * Override these values for international dates, for example...
1429 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1448 * An array of textual day names.
1449 * Override these values for international dates, for example...
1450 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1466 Date.monthNumbers = {
1481 * Creates and returns a new Date instance with the exact same date value as the called instance.
1482 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1483 * variable will also be changed. When the intention is to create a new variable that will not
1484 * modify the original instance, you should create a clone.
1486 * Example of correctly cloning a date:
1489 var orig = new Date('10/1/2006');
1492 document.write(orig); //returns 'Thu Oct 05 2006'!
1495 var orig = new Date('10/1/2006');
1496 var copy = orig.clone();
1498 document.write(orig); //returns 'Thu Oct 01 2006'
1500 * @return {Date} The new Date instance
1502 Date.prototype.clone = function() {
1503 return new Date(this.getTime());
1507 * Clears any time information from this date
1508 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1509 @return {Date} this or the clone
1511 Date.prototype.clearTime = function(clone){
1513 return this.clone().clearTime();
1518 this.setMilliseconds(0);
1523 // safari setMonth is broken
1525 Date.brokenSetMonth = Date.prototype.setMonth;
1526 Date.prototype.setMonth = function(num){
1528 var n = Math.ceil(-num);
1529 var back_year = Math.ceil(n/12);
1530 var month = (n % 12) ? 12 - n % 12 : 0 ;
1531 this.setFullYear(this.getFullYear() - back_year);
1532 return Date.brokenSetMonth.call(this, month);
1534 return Date.brokenSetMonth.apply(this, arguments);
1539 /** Date interval constant
1543 /** Date interval constant
1547 /** Date interval constant
1551 /** Date interval constant
1555 /** Date interval constant
1559 /** Date interval constant
1563 /** Date interval constant
1569 * Provides a convenient method of performing basic date arithmetic. This method
1570 * does not modify the Date instance being called - it creates and returns
1571 * a new Date instance containing the resulting date value.
1576 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1577 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1579 //Negative values will subtract correctly:
1580 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1581 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1583 //You can even chain several calls together in one line!
1584 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1585 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1588 * @param {String} interval A valid date interval enum value
1589 * @param {Number} value The amount to add to the current date
1590 * @return {Date} The new Date instance
1592 Date.prototype.add = function(interval, value){
1593 var d = this.clone();
1594 if (!interval || value === 0) return d;
1595 switch(interval.toLowerCase()){
1597 d.setMilliseconds(this.getMilliseconds() + value);
1600 d.setSeconds(this.getSeconds() + value);
1603 d.setMinutes(this.getMinutes() + value);
1606 d.setHours(this.getHours() + value);
1609 d.setDate(this.getDate() + value);
1612 var day = this.getDate();
1614 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1617 d.setMonth(this.getMonth() + value);
1620 d.setFullYear(this.getFullYear() + value);
1626 * Ext JS Library 1.1.1
1627 * Copyright(c) 2006-2007, Ext JS, LLC.
1629 * Originally Released Under LGPL - original licence link has changed is not relivant.
1632 * <script type="text/javascript">
1636 getViewWidth : function(full) {
1637 return full ? this.getDocumentWidth() : this.getViewportWidth();
1640 getViewHeight : function(full) {
1641 return full ? this.getDocumentHeight() : this.getViewportHeight();
1644 getDocumentHeight: function() {
1645 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1646 return Math.max(scrollHeight, this.getViewportHeight());
1649 getDocumentWidth: function() {
1650 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1651 return Math.max(scrollWidth, this.getViewportWidth());
1654 getViewportHeight: function() {
1655 var height = self.innerHeight;
1656 var mode = document.compatMode;
1658 if ((mode || Roo.isIE) && !Roo.isOpera) {
1659 height = (mode == "CSS1Compat") ?
1660 document.documentElement.clientHeight :
1661 document.body.clientHeight;
1667 getViewportWidth: function() {
1668 var width = self.innerWidth;
1669 var mode = document.compatMode;
1671 if (mode || Roo.isIE) {
1672 width = (mode == "CSS1Compat") ?
1673 document.documentElement.clientWidth :
1674 document.body.clientWidth;
1679 isAncestor : function(p, c) {
1686 if (p.contains && !Roo.isSafari) {
1687 return p.contains(c);
1688 } else if (p.compareDocumentPosition) {
1689 return !!(p.compareDocumentPosition(c) & 16);
1691 var parent = c.parentNode;
1696 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1699 parent = parent.parentNode;
1705 getRegion : function(el) {
1706 return Roo.lib.Region.getRegion(el);
1709 getY : function(el) {
1710 return this.getXY(el)[1];
1713 getX : function(el) {
1714 return this.getXY(el)[0];
1717 getXY : function(el) {
1718 var p, pe, b, scroll, bd = document.body;
1719 el = Roo.getDom(el);
1720 var fly = Roo.lib.AnimBase.fly;
1721 if (el.getBoundingClientRect) {
1722 b = el.getBoundingClientRect();
1723 scroll = fly(document).getScroll();
1724 return [b.left + scroll.left, b.top + scroll.top];
1730 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1737 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1744 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1745 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1752 if (p != el && pe.getStyle('overflow') != 'visible') {
1760 if (Roo.isSafari && hasAbsolute) {
1765 if (Roo.isGecko && !hasAbsolute) {
1767 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1768 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1772 while (p && p != bd) {
1773 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1785 setXY : function(el, xy) {
1786 el = Roo.fly(el, '_setXY');
1788 var pts = el.translatePoints(xy);
1789 if (xy[0] !== false) {
1790 el.dom.style.left = pts.left + "px";
1792 if (xy[1] !== false) {
1793 el.dom.style.top = pts.top + "px";
1797 setX : function(el, x) {
1798 this.setXY(el, [x, false]);
1801 setY : function(el, y) {
1802 this.setXY(el, [false, y]);
1806 * Portions of this file are based on pieces of Yahoo User Interface Library
1807 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1808 * YUI licensed under the BSD License:
1809 * http://developer.yahoo.net/yui/license.txt
1810 * <script type="text/javascript">
1814 Roo.lib.Event = function() {
1815 var loadComplete = false;
1817 var unloadListeners = [];
1819 var onAvailStack = [];
1821 var lastError = null;
1834 startInterval: function() {
1835 if (!this._interval) {
1837 var callback = function() {
1838 self._tryPreloadAttach();
1840 this._interval = setInterval(callback, this.POLL_INTERVAL);
1845 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1846 onAvailStack.push({ id: p_id,
1849 override: p_override,
1850 checkReady: false });
1852 retryCount = this.POLL_RETRYS;
1853 this.startInterval();
1857 addListener: function(el, eventName, fn) {
1858 el = Roo.getDom(el);
1863 if ("unload" == eventName) {
1864 unloadListeners[unloadListeners.length] =
1865 [el, eventName, fn];
1869 var wrappedFn = function(e) {
1870 return fn(Roo.lib.Event.getEvent(e));
1873 var li = [el, eventName, fn, wrappedFn];
1875 var index = listeners.length;
1876 listeners[index] = li;
1878 this.doAdd(el, eventName, wrappedFn, false);
1884 removeListener: function(el, eventName, fn) {
1887 el = Roo.getDom(el);
1890 return this.purgeElement(el, false, eventName);
1894 if ("unload" == eventName) {
1896 for (i = 0,len = unloadListeners.length; i < len; i++) {
1897 var li = unloadListeners[i];
1900 li[1] == eventName &&
1902 unloadListeners.splice(i, 1);
1910 var cacheItem = null;
1913 var index = arguments[3];
1915 if ("undefined" == typeof index) {
1916 index = this._getCacheIndex(el, eventName, fn);
1920 cacheItem = listeners[index];
1923 if (!el || !cacheItem) {
1927 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1929 delete listeners[index][this.WFN];
1930 delete listeners[index][this.FN];
1931 listeners.splice(index, 1);
1938 getTarget: function(ev, resolveTextNode) {
1939 ev = ev.browserEvent || ev;
1940 var t = ev.target || ev.srcElement;
1941 return this.resolveTextNode(t);
1945 resolveTextNode: function(node) {
1946 if (Roo.isSafari && node && 3 == node.nodeType) {
1947 return node.parentNode;
1954 getPageX: function(ev) {
1955 ev = ev.browserEvent || ev;
1957 if (!x && 0 !== x) {
1958 x = ev.clientX || 0;
1961 x += this.getScroll()[1];
1969 getPageY: function(ev) {
1970 ev = ev.browserEvent || ev;
1972 if (!y && 0 !== y) {
1973 y = ev.clientY || 0;
1976 y += this.getScroll()[0];
1985 getXY: function(ev) {
1986 ev = ev.browserEvent || ev;
1987 return [this.getPageX(ev), this.getPageY(ev)];
1991 getRelatedTarget: function(ev) {
1992 ev = ev.browserEvent || ev;
1993 var t = ev.relatedTarget;
1995 if (ev.type == "mouseout") {
1997 } else if (ev.type == "mouseover") {
2002 return this.resolveTextNode(t);
2006 getTime: function(ev) {
2007 ev = ev.browserEvent || ev;
2009 var t = new Date().getTime();
2013 this.lastError = ex;
2022 stopEvent: function(ev) {
2023 this.stopPropagation(ev);
2024 this.preventDefault(ev);
2028 stopPropagation: function(ev) {
2029 ev = ev.browserEvent || ev;
2030 if (ev.stopPropagation) {
2031 ev.stopPropagation();
2033 ev.cancelBubble = true;
2038 preventDefault: function(ev) {
2039 ev = ev.browserEvent || ev;
2040 if(ev.preventDefault) {
2041 ev.preventDefault();
2043 ev.returnValue = false;
2048 getEvent: function(e) {
2049 var ev = e || window.event;
2051 var c = this.getEvent.caller;
2053 ev = c.arguments[0];
2054 if (ev && Event == ev.constructor) {
2064 getCharCode: function(ev) {
2065 ev = ev.browserEvent || ev;
2066 return ev.charCode || ev.keyCode || 0;
2070 _getCacheIndex: function(el, eventName, fn) {
2071 for (var i = 0,len = listeners.length; i < len; ++i) {
2072 var li = listeners[i];
2074 li[this.FN] == fn &&
2075 li[this.EL] == el &&
2076 li[this.TYPE] == eventName) {
2088 getEl: function(id) {
2089 return document.getElementById(id);
2093 clearCache: function() {
2097 _load: function(e) {
2098 loadComplete = true;
2099 var EU = Roo.lib.Event;
2103 EU.doRemove(window, "load", EU._load);
2108 _tryPreloadAttach: function() {
2117 var tryAgain = !loadComplete;
2119 tryAgain = (retryCount > 0);
2124 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2125 var item = onAvailStack[i];
2127 var el = this.getEl(item.id);
2130 if (!item.checkReady ||
2133 (document && document.body)) {
2136 if (item.override) {
2137 if (item.override === true) {
2140 scope = item.override;
2143 item.fn.call(scope, item.obj);
2144 onAvailStack[i] = null;
2147 notAvail.push(item);
2152 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2156 this.startInterval();
2158 clearInterval(this._interval);
2159 this._interval = null;
2162 this.locked = false;
2169 purgeElement: function(el, recurse, eventName) {
2170 var elListeners = this.getListeners(el, eventName);
2172 for (var i = 0,len = elListeners.length; i < len; ++i) {
2173 var l = elListeners[i];
2174 this.removeListener(el, l.type, l.fn);
2178 if (recurse && el && el.childNodes) {
2179 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2180 this.purgeElement(el.childNodes[i], recurse, eventName);
2186 getListeners: function(el, eventName) {
2187 var results = [], searchLists;
2189 searchLists = [listeners, unloadListeners];
2190 } else if (eventName == "unload") {
2191 searchLists = [unloadListeners];
2193 searchLists = [listeners];
2196 for (var j = 0; j < searchLists.length; ++j) {
2197 var searchList = searchLists[j];
2198 if (searchList && searchList.length > 0) {
2199 for (var i = 0,len = searchList.length; i < len; ++i) {
2200 var l = searchList[i];
2201 if (l && l[this.EL] === el &&
2202 (!eventName || eventName === l[this.TYPE])) {
2207 adjust: l[this.ADJ_SCOPE],
2215 return (results.length) ? results : null;
2219 _unload: function(e) {
2221 var EU = Roo.lib.Event, i, j, l, len, index;
2223 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2224 l = unloadListeners[i];
2227 if (l[EU.ADJ_SCOPE]) {
2228 if (l[EU.ADJ_SCOPE] === true) {
2231 scope = l[EU.ADJ_SCOPE];
2234 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2235 unloadListeners[i] = null;
2241 unloadListeners = null;
2243 if (listeners && listeners.length > 0) {
2244 j = listeners.length;
2247 l = listeners[index];
2249 EU.removeListener(l[EU.EL], l[EU.TYPE],
2259 EU.doRemove(window, "unload", EU._unload);
2264 getScroll: function() {
2265 var dd = document.documentElement, db = document.body;
2266 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2267 return [dd.scrollTop, dd.scrollLeft];
2269 return [db.scrollTop, db.scrollLeft];
2276 doAdd: function () {
2277 if (window.addEventListener) {
2278 return function(el, eventName, fn, capture) {
2279 el.addEventListener(eventName, fn, (capture));
2281 } else if (window.attachEvent) {
2282 return function(el, eventName, fn, capture) {
2283 el.attachEvent("on" + eventName, fn);
2292 doRemove: function() {
2293 if (window.removeEventListener) {
2294 return function (el, eventName, fn, capture) {
2295 el.removeEventListener(eventName, fn, (capture));
2297 } else if (window.detachEvent) {
2298 return function (el, eventName, fn) {
2299 el.detachEvent("on" + eventName, fn);
2311 var E = Roo.lib.Event;
2312 E.on = E.addListener;
2313 E.un = E.removeListener;
2315 if (document && document.body) {
2318 E.doAdd(window, "load", E._load);
2320 E.doAdd(window, "unload", E._unload);
2321 E._tryPreloadAttach();
2325 * Portions of this file are based on pieces of Yahoo User Interface Library
2326 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2327 * YUI licensed under the BSD License:
2328 * http://developer.yahoo.net/yui/license.txt
2329 * <script type="text/javascript">
2336 request : function(method, uri, cb, data, options) {
2338 var hs = options.headers;
2341 if(hs.hasOwnProperty(h)){
2342 this.initHeader(h, hs[h], false);
2346 if(options.xmlData){
2347 this.initHeader('Content-Type', 'text/xml', false);
2349 data = options.xmlData;
2353 return this.asyncRequest(method, uri, cb, data);
2356 serializeForm : function(form) {
2357 if(typeof form == 'string') {
2358 form = (document.getElementById(form) || document.forms[form]);
2361 var el, name, val, disabled, data = '', hasSubmit = false;
2362 for (var i = 0; i < form.elements.length; i++) {
2363 el = form.elements[i];
2364 disabled = form.elements[i].disabled;
2365 name = form.elements[i].name;
2366 val = form.elements[i].value;
2368 if (!disabled && name){
2372 case 'select-multiple':
2373 for (var j = 0; j < el.options.length; j++) {
2374 if (el.options[j].selected) {
2376 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2379 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2387 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2400 if(hasSubmit == false) {
2401 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2406 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2411 data = data.substr(0, data.length - 1);
2419 useDefaultHeader:true,
2421 defaultPostHeader:'application/x-www-form-urlencoded',
2423 useDefaultXhrHeader:true,
2425 defaultXhrHeader:'XMLHttpRequest',
2427 hasDefaultHeaders:true,
2439 setProgId:function(id)
2441 this.activeX.unshift(id);
2444 setDefaultPostHeader:function(b)
2446 this.useDefaultHeader = b;
2449 setDefaultXhrHeader:function(b)
2451 this.useDefaultXhrHeader = b;
2454 setPollingInterval:function(i)
2456 if (typeof i == 'number' && isFinite(i)) {
2457 this.pollInterval = i;
2461 createXhrObject:function(transactionId)
2467 http = new XMLHttpRequest();
2469 obj = { conn:http, tId:transactionId };
2473 for (var i = 0; i < this.activeX.length; ++i) {
2477 http = new ActiveXObject(this.activeX[i]);
2479 obj = { conn:http, tId:transactionId };
2492 getConnectionObject:function()
2495 var tId = this.transactionId;
2499 o = this.createXhrObject(tId);
2501 this.transactionId++;
2512 asyncRequest:function(method, uri, callback, postData)
2514 var o = this.getConnectionObject();
2520 o.conn.open(method, uri, true);
2522 if (this.useDefaultXhrHeader) {
2523 if (!this.defaultHeaders['X-Requested-With']) {
2524 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2528 if(postData && this.useDefaultHeader){
2529 this.initHeader('Content-Type', this.defaultPostHeader);
2532 if (this.hasDefaultHeaders || this.hasHeaders) {
2536 this.handleReadyState(o, callback);
2537 o.conn.send(postData || null);
2543 handleReadyState:function(o, callback)
2547 if (callback && callback.timeout) {
2548 this.timeout[o.tId] = window.setTimeout(function() {
2549 oConn.abort(o, callback, true);
2550 }, callback.timeout);
2553 this.poll[o.tId] = window.setInterval(
2555 if (o.conn && o.conn.readyState == 4) {
2556 window.clearInterval(oConn.poll[o.tId]);
2557 delete oConn.poll[o.tId];
2559 if(callback && callback.timeout) {
2560 window.clearTimeout(oConn.timeout[o.tId]);
2561 delete oConn.timeout[o.tId];
2564 oConn.handleTransactionResponse(o, callback);
2567 , this.pollInterval);
2570 handleTransactionResponse:function(o, callback, isAbort)
2574 this.releaseObject(o);
2578 var httpStatus, responseObject;
2582 if (o.conn.status !== undefined && o.conn.status != 0) {
2583 httpStatus = o.conn.status;
2595 if (httpStatus >= 200 && httpStatus < 300) {
2596 responseObject = this.createResponseObject(o, callback.argument);
2597 if (callback.success) {
2598 if (!callback.scope) {
2599 callback.success(responseObject);
2604 callback.success.apply(callback.scope, [responseObject]);
2609 switch (httpStatus) {
2617 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2618 if (callback.failure) {
2619 if (!callback.scope) {
2620 callback.failure(responseObject);
2623 callback.failure.apply(callback.scope, [responseObject]);
2628 responseObject = this.createResponseObject(o, callback.argument);
2629 if (callback.failure) {
2630 if (!callback.scope) {
2631 callback.failure(responseObject);
2634 callback.failure.apply(callback.scope, [responseObject]);
2640 this.releaseObject(o);
2641 responseObject = null;
2644 createResponseObject:function(o, callbackArg)
2651 var headerStr = o.conn.getAllResponseHeaders();
2652 var header = headerStr.split('\n');
2653 for (var i = 0; i < header.length; i++) {
2654 var delimitPos = header[i].indexOf(':');
2655 if (delimitPos != -1) {
2656 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2664 obj.status = o.conn.status;
2665 obj.statusText = o.conn.statusText;
2666 obj.getResponseHeader = headerObj;
2667 obj.getAllResponseHeaders = headerStr;
2668 obj.responseText = o.conn.responseText;
2669 obj.responseXML = o.conn.responseXML;
2671 if (typeof callbackArg !== undefined) {
2672 obj.argument = callbackArg;
2678 createExceptionObject:function(tId, callbackArg, isAbort)
2681 var COMM_ERROR = 'communication failure';
2682 var ABORT_CODE = -1;
2683 var ABORT_ERROR = 'transaction aborted';
2689 obj.status = ABORT_CODE;
2690 obj.statusText = ABORT_ERROR;
2693 obj.status = COMM_CODE;
2694 obj.statusText = COMM_ERROR;
2698 obj.argument = callbackArg;
2704 initHeader:function(label, value, isDefault)
2706 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2708 if (headerObj[label] === undefined) {
2709 headerObj[label] = value;
2714 headerObj[label] = value + "," + headerObj[label];
2718 this.hasDefaultHeaders = true;
2721 this.hasHeaders = true;
2726 setHeader:function(o)
2728 if (this.hasDefaultHeaders) {
2729 for (var prop in this.defaultHeaders) {
2730 if (this.defaultHeaders.hasOwnProperty(prop)) {
2731 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2736 if (this.hasHeaders) {
2737 for (var prop in this.headers) {
2738 if (this.headers.hasOwnProperty(prop)) {
2739 o.conn.setRequestHeader(prop, this.headers[prop]);
2743 this.hasHeaders = false;
2747 resetDefaultHeaders:function() {
2748 delete this.defaultHeaders;
2749 this.defaultHeaders = {};
2750 this.hasDefaultHeaders = false;
2753 abort:function(o, callback, isTimeout)
2755 if(this.isCallInProgress(o)) {
2757 window.clearInterval(this.poll[o.tId]);
2758 delete this.poll[o.tId];
2760 delete this.timeout[o.tId];
2763 this.handleTransactionResponse(o, callback, true);
2773 isCallInProgress:function(o)
2776 return o.conn.readyState != 4 && o.conn.readyState != 0;
2785 releaseObject:function(o)
2794 'MSXML2.XMLHTTP.3.0',
2802 * Portions of this file are based on pieces of Yahoo User Interface Library
2803 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2804 * YUI licensed under the BSD License:
2805 * http://developer.yahoo.net/yui/license.txt
2806 * <script type="text/javascript">
2810 Roo.lib.Region = function(t, r, b, l) {
2820 Roo.lib.Region.prototype = {
2821 contains : function(region) {
2822 return ( region.left >= this.left &&
2823 region.right <= this.right &&
2824 region.top >= this.top &&
2825 region.bottom <= this.bottom );
2829 getArea : function() {
2830 return ( (this.bottom - this.top) * (this.right - this.left) );
2833 intersect : function(region) {
2834 var t = Math.max(this.top, region.top);
2835 var r = Math.min(this.right, region.right);
2836 var b = Math.min(this.bottom, region.bottom);
2837 var l = Math.max(this.left, region.left);
2839 if (b >= t && r >= l) {
2840 return new Roo.lib.Region(t, r, b, l);
2845 union : function(region) {
2846 var t = Math.min(this.top, region.top);
2847 var r = Math.max(this.right, region.right);
2848 var b = Math.max(this.bottom, region.bottom);
2849 var l = Math.min(this.left, region.left);
2851 return new Roo.lib.Region(t, r, b, l);
2854 adjust : function(t, l, b, r) {
2863 Roo.lib.Region.getRegion = function(el) {
2864 var p = Roo.lib.Dom.getXY(el);
2867 var r = p[0] + el.offsetWidth;
2868 var b = p[1] + el.offsetHeight;
2871 return new Roo.lib.Region(t, r, b, l);
2874 * Portions of this file are based on pieces of Yahoo User Interface Library
2875 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2876 * YUI licensed under the BSD License:
2877 * http://developer.yahoo.net/yui/license.txt
2878 * <script type="text/javascript">
2881 //@@dep Roo.lib.Region
2884 Roo.lib.Point = function(x, y) {
2885 if (x instanceof Array) {
2889 this.x = this.right = this.left = this[0] = x;
2890 this.y = this.top = this.bottom = this[1] = y;
2893 Roo.lib.Point.prototype = new Roo.lib.Region();
2895 * Portions of this file are based on pieces of Yahoo User Interface Library
2896 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2897 * YUI licensed under the BSD License:
2898 * http://developer.yahoo.net/yui/license.txt
2899 * <script type="text/javascript">
2906 scroll : function(el, args, duration, easing, cb, scope) {
2907 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2910 motion : function(el, args, duration, easing, cb, scope) {
2911 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2914 color : function(el, args, duration, easing, cb, scope) {
2915 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2918 run : function(el, args, duration, easing, cb, scope, type) {
2919 type = type || Roo.lib.AnimBase;
2920 if (typeof easing == "string") {
2921 easing = Roo.lib.Easing[easing];
2923 var anim = new type(el, args, duration, easing);
2924 anim.animateX(function() {
2925 Roo.callback(cb, scope);
2931 * Portions of this file are based on pieces of Yahoo User Interface Library
2932 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2933 * YUI licensed under the BSD License:
2934 * http://developer.yahoo.net/yui/license.txt
2935 * <script type="text/javascript">
2943 if (!libFlyweight) {
2944 libFlyweight = new Roo.Element.Flyweight();
2946 libFlyweight.dom = el;
2947 return libFlyweight;
2950 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2954 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2956 this.init(el, attributes, duration, method);
2960 Roo.lib.AnimBase.fly = fly;
2964 Roo.lib.AnimBase.prototype = {
2966 toString: function() {
2967 var el = this.getEl();
2968 var id = el.id || el.tagName;
2969 return ("Anim " + id);
2973 noNegatives: /width|height|opacity|padding/i,
2974 offsetAttribute: /^((width|height)|(top|left))$/,
2975 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
2976 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
2980 doMethod: function(attr, start, end) {
2981 return this.method(this.currentFrame, start, end - start, this.totalFrames);
2985 setAttribute: function(attr, val, unit) {
2986 if (this.patterns.noNegatives.test(attr)) {
2987 val = (val > 0) ? val : 0;
2990 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
2994 getAttribute: function(attr) {
2995 var el = this.getEl();
2996 var val = fly(el).getStyle(attr);
2998 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
2999 return parseFloat(val);
3002 var a = this.patterns.offsetAttribute.exec(attr) || [];
3003 var pos = !!( a[3] );
3004 var box = !!( a[2] );
3007 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3008 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3017 getDefaultUnit: function(attr) {
3018 if (this.patterns.defaultUnit.test(attr)) {
3025 animateX : function(callback, scope) {
3026 var f = function() {
3027 this.onComplete.removeListener(f);
3028 if (typeof callback == "function") {
3029 callback.call(scope || this, this);
3032 this.onComplete.addListener(f, this);
3037 setRuntimeAttribute: function(attr) {
3040 var attributes = this.attributes;
3042 this.runtimeAttributes[attr] = {};
3044 var isset = function(prop) {
3045 return (typeof prop !== 'undefined');
3048 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3052 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3055 if (isset(attributes[attr]['to'])) {
3056 end = attributes[attr]['to'];
3057 } else if (isset(attributes[attr]['by'])) {
3058 if (start.constructor == Array) {
3060 for (var i = 0, len = start.length; i < len; ++i) {
3061 end[i] = start[i] + attributes[attr]['by'][i];
3064 end = start + attributes[attr]['by'];
3068 this.runtimeAttributes[attr].start = start;
3069 this.runtimeAttributes[attr].end = end;
3072 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3076 init: function(el, attributes, duration, method) {
3078 var isAnimated = false;
3081 var startTime = null;
3084 var actualFrames = 0;
3087 el = Roo.getDom(el);
3090 this.attributes = attributes || {};
3093 this.duration = duration || 1;
3096 this.method = method || Roo.lib.Easing.easeNone;
3099 this.useSeconds = true;
3102 this.currentFrame = 0;
3105 this.totalFrames = Roo.lib.AnimMgr.fps;
3108 this.getEl = function() {
3113 this.isAnimated = function() {
3118 this.getStartTime = function() {
3122 this.runtimeAttributes = {};
3125 this.animate = function() {
3126 if (this.isAnimated()) {
3130 this.currentFrame = 0;
3132 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3134 Roo.lib.AnimMgr.registerElement(this);
3138 this.stop = function(finish) {
3140 this.currentFrame = this.totalFrames;
3141 this._onTween.fire();
3143 Roo.lib.AnimMgr.stop(this);
3146 var onStart = function() {
3147 this.onStart.fire();
3149 this.runtimeAttributes = {};
3150 for (var attr in this.attributes) {
3151 this.setRuntimeAttribute(attr);
3156 startTime = new Date();
3160 var onTween = function() {
3162 duration: new Date() - this.getStartTime(),
3163 currentFrame: this.currentFrame
3166 data.toString = function() {
3168 'duration: ' + data.duration +
3169 ', currentFrame: ' + data.currentFrame
3173 this.onTween.fire(data);
3175 var runtimeAttributes = this.runtimeAttributes;
3177 for (var attr in runtimeAttributes) {
3178 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3184 var onComplete = function() {
3185 var actual_duration = (new Date() - startTime) / 1000 ;
3188 duration: actual_duration,
3189 frames: actualFrames,
3190 fps: actualFrames / actual_duration
3193 data.toString = function() {
3195 'duration: ' + data.duration +
3196 ', frames: ' + data.frames +
3197 ', fps: ' + data.fps
3203 this.onComplete.fire(data);
3207 this._onStart = new Roo.util.Event(this);
3208 this.onStart = new Roo.util.Event(this);
3209 this.onTween = new Roo.util.Event(this);
3210 this._onTween = new Roo.util.Event(this);
3211 this.onComplete = new Roo.util.Event(this);
3212 this._onComplete = new Roo.util.Event(this);
3213 this._onStart.addListener(onStart);
3214 this._onTween.addListener(onTween);
3215 this._onComplete.addListener(onComplete);
3220 * Portions of this file are based on pieces of Yahoo User Interface Library
3221 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3222 * YUI licensed under the BSD License:
3223 * http://developer.yahoo.net/yui/license.txt
3224 * <script type="text/javascript">
3228 Roo.lib.AnimMgr = new function() {
3245 this.registerElement = function(tween) {
3246 queue[queue.length] = tween;
3248 tween._onStart.fire();
3253 this.unRegister = function(tween, index) {
3254 tween._onComplete.fire();
3255 index = index || getIndex(tween);
3257 queue.splice(index, 1);
3261 if (tweenCount <= 0) {
3267 this.start = function() {
3268 if (thread === null) {
3269 thread = setInterval(this.run, this.delay);
3274 this.stop = function(tween) {
3276 clearInterval(thread);
3278 for (var i = 0, len = queue.length; i < len; ++i) {
3279 if (queue[0].isAnimated()) {
3280 this.unRegister(queue[0], 0);
3289 this.unRegister(tween);
3294 this.run = function() {
3295 for (var i = 0, len = queue.length; i < len; ++i) {
3296 var tween = queue[i];
3297 if (!tween || !tween.isAnimated()) {
3301 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3303 tween.currentFrame += 1;
3305 if (tween.useSeconds) {
3306 correctFrame(tween);
3308 tween._onTween.fire();
3311 Roo.lib.AnimMgr.stop(tween, i);
3316 var getIndex = function(anim) {
3317 for (var i = 0, len = queue.length; i < len; ++i) {
3318 if (queue[i] == anim) {
3326 var correctFrame = function(tween) {
3327 var frames = tween.totalFrames;
3328 var frame = tween.currentFrame;
3329 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3330 var elapsed = (new Date() - tween.getStartTime());
3333 if (elapsed < tween.duration * 1000) {
3334 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3336 tweak = frames - (frame + 1);
3338 if (tweak > 0 && isFinite(tweak)) {
3339 if (tween.currentFrame + tweak >= frames) {
3340 tweak = frames - (frame + 1);
3343 tween.currentFrame += tweak;
3347 * Portions of this file are based on pieces of Yahoo User Interface Library
3348 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3349 * YUI licensed under the BSD License:
3350 * http://developer.yahoo.net/yui/license.txt
3351 * <script type="text/javascript">
3354 Roo.lib.Bezier = new function() {
3356 this.getPosition = function(points, t) {
3357 var n = points.length;
3360 for (var i = 0; i < n; ++i) {
3361 tmp[i] = [points[i][0], points[i][1]];
3364 for (var j = 1; j < n; ++j) {
3365 for (i = 0; i < n - j; ++i) {
3366 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3367 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3371 return [ tmp[0][0], tmp[0][1] ];
3375 * Portions of this file are based on pieces of Yahoo User Interface Library
3376 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3377 * YUI licensed under the BSD License:
3378 * http://developer.yahoo.net/yui/license.txt
3379 * <script type="text/javascript">
3384 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3385 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3388 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3390 var fly = Roo.lib.AnimBase.fly;
3392 var superclass = Y.ColorAnim.superclass;
3393 var proto = Y.ColorAnim.prototype;
3395 proto.toString = function() {
3396 var el = this.getEl();
3397 var id = el.id || el.tagName;
3398 return ("ColorAnim " + id);
3401 proto.patterns.color = /color$/i;
3402 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3403 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3404 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3405 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3408 proto.parseColor = function(s) {
3409 if (s.length == 3) {
3413 var c = this.patterns.hex.exec(s);
3414 if (c && c.length == 4) {
3415 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3418 c = this.patterns.rgb.exec(s);
3419 if (c && c.length == 4) {
3420 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3423 c = this.patterns.hex3.exec(s);
3424 if (c && c.length == 4) {
3425 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3430 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3431 proto.getAttribute = function(attr) {
3432 var el = this.getEl();
3433 if (this.patterns.color.test(attr)) {
3434 var val = fly(el).getStyle(attr);
3436 if (this.patterns.transparent.test(val)) {
3437 var parent = el.parentNode;
3438 val = fly(parent).getStyle(attr);
3440 while (parent && this.patterns.transparent.test(val)) {
3441 parent = parent.parentNode;
3442 val = fly(parent).getStyle(attr);
3443 if (parent.tagName.toUpperCase() == 'HTML') {
3449 val = superclass.getAttribute.call(this, attr);
3454 proto.getAttribute = function(attr) {
3455 var el = this.getEl();
3456 if (this.patterns.color.test(attr)) {
3457 var val = fly(el).getStyle(attr);
3459 if (this.patterns.transparent.test(val)) {
3460 var parent = el.parentNode;
3461 val = fly(parent).getStyle(attr);
3463 while (parent && this.patterns.transparent.test(val)) {
3464 parent = parent.parentNode;
3465 val = fly(parent).getStyle(attr);
3466 if (parent.tagName.toUpperCase() == 'HTML') {
3472 val = superclass.getAttribute.call(this, attr);
3478 proto.doMethod = function(attr, start, end) {
3481 if (this.patterns.color.test(attr)) {
3483 for (var i = 0, len = start.length; i < len; ++i) {
3484 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3487 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3490 val = superclass.doMethod.call(this, attr, start, end);
3496 proto.setRuntimeAttribute = function(attr) {
3497 superclass.setRuntimeAttribute.call(this, attr);
3499 if (this.patterns.color.test(attr)) {
3500 var attributes = this.attributes;
3501 var start = this.parseColor(this.runtimeAttributes[attr].start);
3502 var end = this.parseColor(this.runtimeAttributes[attr].end);
3504 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3505 end = this.parseColor(attributes[attr].by);
3507 for (var i = 0, len = start.length; i < len; ++i) {
3508 end[i] = start[i] + end[i];
3512 this.runtimeAttributes[attr].start = start;
3513 this.runtimeAttributes[attr].end = end;
3519 * Portions of this file are based on pieces of Yahoo User Interface Library
3520 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3521 * YUI licensed under the BSD License:
3522 * http://developer.yahoo.net/yui/license.txt
3523 * <script type="text/javascript">
3529 easeNone: function (t, b, c, d) {
3530 return c * t / d + b;
3534 easeIn: function (t, b, c, d) {
3535 return c * (t /= d) * t + b;
3539 easeOut: function (t, b, c, d) {
3540 return -c * (t /= d) * (t - 2) + b;
3544 easeBoth: function (t, b, c, d) {
3545 if ((t /= d / 2) < 1) {
3546 return c / 2 * t * t + b;
3549 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3553 easeInStrong: function (t, b, c, d) {
3554 return c * (t /= d) * t * t * t + b;
3558 easeOutStrong: function (t, b, c, d) {
3559 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3563 easeBothStrong: function (t, b, c, d) {
3564 if ((t /= d / 2) < 1) {
3565 return c / 2 * t * t * t * t + b;
3568 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3573 elasticIn: function (t, b, c, d, a, p) {
3577 if ((t /= d) == 1) {
3584 if (!a || a < Math.abs(c)) {
3589 var s = p / (2 * Math.PI) * Math.asin(c / a);
3592 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3596 elasticOut: function (t, b, c, d, a, p) {
3600 if ((t /= d) == 1) {
3607 if (!a || a < Math.abs(c)) {
3612 var s = p / (2 * Math.PI) * Math.asin(c / a);
3615 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3619 elasticBoth: function (t, b, c, d, a, p) {
3624 if ((t /= d / 2) == 2) {
3632 if (!a || a < Math.abs(c)) {
3637 var s = p / (2 * Math.PI) * Math.asin(c / a);
3641 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3642 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3644 return a * Math.pow(2, -10 * (t -= 1)) *
3645 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3650 backIn: function (t, b, c, d, s) {
3651 if (typeof s == 'undefined') {
3654 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3658 backOut: function (t, b, c, d, s) {
3659 if (typeof s == 'undefined') {
3662 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3666 backBoth: function (t, b, c, d, s) {
3667 if (typeof s == 'undefined') {
3671 if ((t /= d / 2 ) < 1) {
3672 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3674 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3678 bounceIn: function (t, b, c, d) {
3679 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3683 bounceOut: function (t, b, c, d) {
3684 if ((t /= d) < (1 / 2.75)) {
3685 return c * (7.5625 * t * t) + b;
3686 } else if (t < (2 / 2.75)) {
3687 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3688 } else if (t < (2.5 / 2.75)) {
3689 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3691 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3695 bounceBoth: function (t, b, c, d) {
3697 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3699 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3702 * Portions of this file are based on pieces of Yahoo User Interface Library
3703 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3704 * YUI licensed under the BSD License:
3705 * http://developer.yahoo.net/yui/license.txt
3706 * <script type="text/javascript">
3710 Roo.lib.Motion = function(el, attributes, duration, method) {
3712 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3716 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3720 var superclass = Y.Motion.superclass;
3721 var proto = Y.Motion.prototype;
3723 proto.toString = function() {
3724 var el = this.getEl();
3725 var id = el.id || el.tagName;
3726 return ("Motion " + id);
3729 proto.patterns.points = /^points$/i;
3731 proto.setAttribute = function(attr, val, unit) {
3732 if (this.patterns.points.test(attr)) {
3733 unit = unit || 'px';
3734 superclass.setAttribute.call(this, 'left', val[0], unit);
3735 superclass.setAttribute.call(this, 'top', val[1], unit);
3737 superclass.setAttribute.call(this, attr, val, unit);
3741 proto.getAttribute = function(attr) {
3742 if (this.patterns.points.test(attr)) {
3744 superclass.getAttribute.call(this, 'left'),
3745 superclass.getAttribute.call(this, 'top')
3748 val = superclass.getAttribute.call(this, attr);
3754 proto.doMethod = function(attr, start, end) {
3757 if (this.patterns.points.test(attr)) {
3758 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3759 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3761 val = superclass.doMethod.call(this, attr, start, end);
3766 proto.setRuntimeAttribute = function(attr) {
3767 if (this.patterns.points.test(attr)) {
3768 var el = this.getEl();
3769 var attributes = this.attributes;
3771 var control = attributes['points']['control'] || [];
3775 if (control.length > 0 && !(control[0] instanceof Array)) {
3776 control = [control];
3779 for (i = 0,len = control.length; i < len; ++i) {
3780 tmp[i] = control[i];
3785 Roo.fly(el).position();
3787 if (isset(attributes['points']['from'])) {
3788 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3791 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3794 start = this.getAttribute('points');
3797 if (isset(attributes['points']['to'])) {
3798 end = translateValues.call(this, attributes['points']['to'], start);
3800 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3801 for (i = 0,len = control.length; i < len; ++i) {
3802 control[i] = translateValues.call(this, control[i], start);
3806 } else if (isset(attributes['points']['by'])) {
3807 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3809 for (i = 0,len = control.length; i < len; ++i) {
3810 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3814 this.runtimeAttributes[attr] = [start];
3816 if (control.length > 0) {
3817 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3820 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3823 superclass.setRuntimeAttribute.call(this, attr);
3827 var translateValues = function(val, start) {
3828 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3829 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3834 var isset = function(prop) {
3835 return (typeof prop !== 'undefined');
3839 * Portions of this file are based on pieces of Yahoo User Interface Library
3840 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3841 * YUI licensed under the BSD License:
3842 * http://developer.yahoo.net/yui/license.txt
3843 * <script type="text/javascript">
3847 Roo.lib.Scroll = function(el, attributes, duration, method) {
3849 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3853 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3857 var superclass = Y.Scroll.superclass;
3858 var proto = Y.Scroll.prototype;
3860 proto.toString = function() {
3861 var el = this.getEl();
3862 var id = el.id || el.tagName;
3863 return ("Scroll " + id);
3866 proto.doMethod = function(attr, start, end) {
3869 if (attr == 'scroll') {
3871 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3872 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3876 val = superclass.doMethod.call(this, attr, start, end);
3881 proto.getAttribute = function(attr) {
3883 var el = this.getEl();
3885 if (attr == 'scroll') {
3886 val = [ el.scrollLeft, el.scrollTop ];
3888 val = superclass.getAttribute.call(this, attr);
3894 proto.setAttribute = function(attr, val, unit) {
3895 var el = this.getEl();
3897 if (attr == 'scroll') {
3898 el.scrollLeft = val[0];
3899 el.scrollTop = val[1];
3901 superclass.setAttribute.call(this, attr, val, unit);
3907 * Ext JS Library 1.1.1
3908 * Copyright(c) 2006-2007, Ext JS, LLC.
3910 * Originally Released Under LGPL - original licence link has changed is not relivant.
3913 * <script type="text/javascript">
3918 * @class Roo.DomHelper
3919 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3920 * For more information see <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">this blog post with examples</a>.
3923 Roo.DomHelper = function(){
3924 var tempTableEl = null;
3925 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3926 var tableRe = /^table|tbody|tr|td$/i;
3928 // build as innerHTML where available
3930 var createHtml = function(o){
3931 if(typeof o == 'string'){
3940 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3941 if(attr == "style"){
3943 if(typeof s == "function"){
3946 if(typeof s == "string"){
3947 b += ' style="' + s + '"';
3948 }else if(typeof s == "object"){
3951 if(typeof s[key] != "function"){
3952 b += key + ":" + s[key] + ";";
3959 b += ' class="' + o["cls"] + '"';
3960 }else if(attr == "htmlFor"){
3961 b += ' for="' + o["htmlFor"] + '"';
3963 b += " " + attr + '="' + o[attr] + '"';
3967 if(emptyTags.test(o.tag)){
3971 var cn = o.children || o.cn;
3973 //http://bugs.kde.org/show_bug.cgi?id=71506
3974 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
3975 for(var i = 0, len = cn.length; i < len; i++) {
3976 b += createHtml(cn[i], b);
3979 b += createHtml(cn, b);
3985 b += "</" + o.tag + ">";
3992 var createDom = function(o, parentNode){
3994 // defininition craeted..
3996 if (o.ns && o.ns != 'html') {
3998 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
3999 xmlns[o.ns] = o.xmlns;
4002 if (typeof(xmlns[o.ns]) == 'undefined') {
4003 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4009 if (typeof(o) == 'string') {
4010 return parentNode.appendChild(document.createTextNode(o));
4012 o.tag = o.tag || div;
4013 if (o.ns && Roo.isIE) {
4015 o.tag = o.ns + ':' + o.tag;
4018 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4019 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4022 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4023 attr == "style" || typeof o[attr] == "function") continue;
4025 if(attr=="cls" && Roo.isIE){
4026 el.className = o["cls"];
4028 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4029 else el[attr] = o[attr];
4032 Roo.DomHelper.applyStyles(el, o.style);
4033 var cn = o.children || o.cn;
4035 //http://bugs.kde.org/show_bug.cgi?id=71506
4036 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4037 for(var i = 0, len = cn.length; i < len; i++) {
4038 createDom(cn[i], el);
4045 el.innerHTML = o.html;
4048 parentNode.appendChild(el);
4053 var ieTable = function(depth, s, h, e){
4054 tempTableEl.innerHTML = [s, h, e].join('');
4055 var i = -1, el = tempTableEl;
4062 // kill repeat to save bytes
4066 tbe = '</tbody>'+te,
4072 * Nasty code for IE's broken table implementation
4074 var insertIntoTable = function(tag, where, el, html){
4076 tempTableEl = document.createElement('div');
4081 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4084 if(where == 'beforebegin'){
4088 before = el.nextSibling;
4091 node = ieTable(4, trs, html, tre);
4093 else if(tag == 'tr'){
4094 if(where == 'beforebegin'){
4097 node = ieTable(3, tbs, html, tbe);
4098 } else if(where == 'afterend'){
4099 before = el.nextSibling;
4101 node = ieTable(3, tbs, html, tbe);
4102 } else{ // INTO a TR
4103 if(where == 'afterbegin'){
4104 before = el.firstChild;
4106 node = ieTable(4, trs, html, tre);
4108 } else if(tag == 'tbody'){
4109 if(where == 'beforebegin'){
4112 node = ieTable(2, ts, html, te);
4113 } else if(where == 'afterend'){
4114 before = el.nextSibling;
4116 node = ieTable(2, ts, html, te);
4118 if(where == 'afterbegin'){
4119 before = el.firstChild;
4121 node = ieTable(3, tbs, html, tbe);
4124 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4127 if(where == 'afterbegin'){
4128 before = el.firstChild;
4130 node = ieTable(2, ts, html, te);
4132 el.insertBefore(node, before);
4137 /** True to force the use of DOM instead of html fragments @type Boolean */
4141 * Returns the markup for the passed Element(s) config
4142 * @param {Object} o The Dom object spec (and children)
4145 markup : function(o){
4146 return createHtml(o);
4150 * Applies a style specification to an element
4151 * @param {String/HTMLElement} el The element to apply styles to
4152 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4153 * a function which returns such a specification.
4155 applyStyles : function(el, styles){
4158 if(typeof styles == "string"){
4159 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4161 while ((matches = re.exec(styles)) != null){
4162 el.setStyle(matches[1], matches[2]);
4164 }else if (typeof styles == "object"){
4165 for (var style in styles){
4166 el.setStyle(style, styles[style]);
4168 }else if (typeof styles == "function"){
4169 Roo.DomHelper.applyStyles(el, styles.call());
4175 * Inserts an HTML fragment into the Dom
4176 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4177 * @param {HTMLElement} el The context element
4178 * @param {String} html The HTML fragmenet
4179 * @return {HTMLElement} The new node
4181 insertHtml : function(where, el, html){
4182 where = where.toLowerCase();
4183 if(el.insertAdjacentHTML){
4184 if(tableRe.test(el.tagName)){
4186 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4192 el.insertAdjacentHTML('BeforeBegin', html);
4193 return el.previousSibling;
4195 el.insertAdjacentHTML('AfterBegin', html);
4196 return el.firstChild;
4198 el.insertAdjacentHTML('BeforeEnd', html);
4199 return el.lastChild;
4201 el.insertAdjacentHTML('AfterEnd', html);
4202 return el.nextSibling;
4204 throw 'Illegal insertion point -> "' + where + '"';
4206 var range = el.ownerDocument.createRange();
4210 range.setStartBefore(el);
4211 frag = range.createContextualFragment(html);
4212 el.parentNode.insertBefore(frag, el);
4213 return el.previousSibling;
4216 range.setStartBefore(el.firstChild);
4217 frag = range.createContextualFragment(html);
4218 el.insertBefore(frag, el.firstChild);
4219 return el.firstChild;
4221 el.innerHTML = html;
4222 return el.firstChild;
4226 range.setStartAfter(el.lastChild);
4227 frag = range.createContextualFragment(html);
4228 el.appendChild(frag);
4229 return el.lastChild;
4231 el.innerHTML = html;
4232 return el.lastChild;
4235 range.setStartAfter(el);
4236 frag = range.createContextualFragment(html);
4237 el.parentNode.insertBefore(frag, el.nextSibling);
4238 return el.nextSibling;
4240 throw 'Illegal insertion point -> "' + where + '"';
4244 * Creates new Dom element(s) and inserts them before el
4245 * @param {String/HTMLElement/Element} el The context element
4246 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4247 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4248 * @return {HTMLElement/Roo.Element} The new node
4250 insertBefore : function(el, o, returnElement){
4251 return this.doInsert(el, o, returnElement, "beforeBegin");
4255 * Creates new Dom element(s) and inserts them after el
4256 * @param {String/HTMLElement/Element} el The context element
4257 * @param {Object} o The Dom object spec (and children)
4258 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4259 * @return {HTMLElement/Roo.Element} The new node
4261 insertAfter : function(el, o, returnElement){
4262 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4266 * Creates new Dom element(s) and inserts them as the first child of el
4267 * @param {String/HTMLElement/Element} el The context element
4268 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4269 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4270 * @return {HTMLElement/Roo.Element} The new node
4272 insertFirst : function(el, o, returnElement){
4273 return this.doInsert(el, o, returnElement, "afterBegin");
4277 doInsert : function(el, o, returnElement, pos, sibling){
4278 el = Roo.getDom(el);
4280 if(this.useDom || o.ns){
4281 newNode = createDom(o, null);
4282 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4284 var html = createHtml(o);
4285 newNode = this.insertHtml(pos, el, html);
4287 return returnElement ? Roo.get(newNode, true) : newNode;
4291 * Creates new Dom element(s) and appends them to el
4292 * @param {String/HTMLElement/Element} el The context element
4293 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4294 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4295 * @return {HTMLElement/Roo.Element} The new node
4297 append : function(el, o, returnElement){
4298 el = Roo.getDom(el);
4300 if(this.useDom || o.ns){
4301 newNode = createDom(o, null);
4302 el.appendChild(newNode);
4304 var html = createHtml(o);
4305 newNode = this.insertHtml("beforeEnd", el, html);
4307 return returnElement ? Roo.get(newNode, true) : newNode;
4311 * Creates new Dom element(s) and overwrites the contents of el with them
4312 * @param {String/HTMLElement/Element} el The context element
4313 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4314 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4315 * @return {HTMLElement/Roo.Element} The new node
4317 overwrite : function(el, o, returnElement){
4318 el = Roo.getDom(el);
4321 while (el.childNodes.length) {
4322 el.removeChild(el.firstChild);
4326 el.innerHTML = createHtml(o);
4329 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4333 * Creates a new Roo.DomHelper.Template from the Dom object spec
4334 * @param {Object} o The Dom object spec (and children)
4335 * @return {Roo.DomHelper.Template} The new template
4337 createTemplate : function(o){
4338 var html = createHtml(o);
4339 return new Roo.Template(html);
4345 * Ext JS Library 1.1.1
4346 * Copyright(c) 2006-2007, Ext JS, LLC.
4348 * Originally Released Under LGPL - original licence link has changed is not relivant.
4351 * <script type="text/javascript">
4355 * @class Roo.Template
4356 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4357 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4360 var t = new Roo.Template(
4361 '<div name="{id}">',
4362 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4365 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4367 * For more information see this blog post with examples: <a href="http://www.jackslocum.com/yui/2006/10/06/domhelper-create-elements-using-dom-html-fragments-or-templates/">DomHelper - Create Elements using DOM, HTML fragments and Templates</a>.
4369 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4371 Roo.Template = function(html){
4372 if(html instanceof Array){
4373 html = html.join("");
4374 }else if(arguments.length > 1){
4375 html = Array.prototype.join.call(arguments, "");
4381 Roo.Template.prototype = {
4383 * Returns an HTML fragment of this template with the specified values applied.
4384 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4385 * @return {String} The HTML fragment
4387 applyTemplate : function(values){
4389 return this.compiled(values);
4391 var useF = this.disableFormats !== true;
4392 var fm = Roo.util.Format, tpl = this;
4393 var fn = function(m, name, format, args){
4395 if(format.substr(0, 5) == "this."){
4396 return tpl.call(format.substr(5), values[name], values);
4399 // quoted values are required for strings in compiled templates,
4400 // but for non compiled we need to strip them
4401 // quoted reversed for jsmin
4402 var re = /^\s*['"](.*)["']\s*$/;
4403 args = args.split(',');
4404 for(var i = 0, len = args.length; i < len; i++){
4405 args[i] = args[i].replace(re, "$1");
4407 args = [values[name]].concat(args);
4409 args = [values[name]];
4411 return fm[format].apply(fm, args);
4414 return values[name] !== undefined ? values[name] : "";
4417 return this.html.replace(this.re, fn);
4421 * Sets the HTML used as the template and optionally compiles it.
4422 * @param {String} html
4423 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4424 * @return {Roo.Template} this
4426 set : function(html, compile){
4428 this.compiled = null;
4436 * True to disable format functions (defaults to false)
4439 disableFormats : false,
4442 * The regular expression used to match template variables
4446 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4449 * Compiles the template into an internal function, eliminating the RegEx overhead.
4450 * @return {Roo.Template} this
4452 compile : function(){
4453 var fm = Roo.util.Format;
4454 var useF = this.disableFormats !== true;
4455 var sep = Roo.isGecko ? "+" : ",";
4456 var fn = function(m, name, format, args){
4458 args = args ? ',' + args : "";
4459 if(format.substr(0, 5) != "this."){
4460 format = "fm." + format + '(';
4462 format = 'this.call("'+ format.substr(5) + '", ';
4466 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4468 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4471 // branched to use + in gecko and [].join() in others
4473 body = "this.compiled = function(values){ return '" +
4474 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4477 body = ["this.compiled = function(values){ return ['"];
4478 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4479 body.push("'].join('');};");
4480 body = body.join('');
4490 // private function used to call members
4491 call : function(fnName, value, allValues){
4492 return this[fnName](value, allValues);
4496 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4497 * @param {String/HTMLElement/Roo.Element} el The context element
4498 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4499 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4500 * @return {HTMLElement/Roo.Element} The new node or Element
4502 insertFirst: function(el, values, returnElement){
4503 return this.doInsert('afterBegin', el, values, returnElement);
4507 * Applies the supplied values to the template and inserts the new node(s) before el.
4508 * @param {String/HTMLElement/Roo.Element} el The context element
4509 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4510 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4511 * @return {HTMLElement/Roo.Element} The new node or Element
4513 insertBefore: function(el, values, returnElement){
4514 return this.doInsert('beforeBegin', el, values, returnElement);
4518 * Applies the supplied values to the template and inserts the new node(s) after el.
4519 * @param {String/HTMLElement/Roo.Element} el The context element
4520 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4521 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4522 * @return {HTMLElement/Roo.Element} The new node or Element
4524 insertAfter : function(el, values, returnElement){
4525 return this.doInsert('afterEnd', el, values, returnElement);
4529 * Applies the supplied values to the template and appends the new node(s) to el.
4530 * @param {String/HTMLElement/Roo.Element} el The context element
4531 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4532 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4533 * @return {HTMLElement/Roo.Element} The new node or Element
4535 append : function(el, values, returnElement){
4536 return this.doInsert('beforeEnd', el, values, returnElement);
4539 doInsert : function(where, el, values, returnEl){
4540 el = Roo.getDom(el);
4541 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4542 return returnEl ? Roo.get(newNode, true) : newNode;
4546 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4547 * @param {String/HTMLElement/Roo.Element} el The context element
4548 * @param {Object} values The template values. Can be an array if your params are numeric (i.e. {0}) or an object (i.e. {foo: 'bar'})
4549 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4550 * @return {HTMLElement/Roo.Element} The new node or Element
4552 overwrite : function(el, values, returnElement){
4553 el = Roo.getDom(el);
4554 el.innerHTML = this.applyTemplate(values);
4555 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4559 * Alias for {@link #applyTemplate}
4562 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4565 Roo.DomHelper.Template = Roo.Template;
4568 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4569 * @param {String/HTMLElement} el A DOM element or its id
4570 * @returns {Roo.Template} The created template
4573 Roo.Template.from = function(el){
4574 el = Roo.getDom(el);
4575 return new Roo.Template(el.value || el.innerHTML);
4578 * Ext JS Library 1.1.1
4579 * Copyright(c) 2006-2007, Ext JS, LLC.
4581 * Originally Released Under LGPL - original licence link has changed is not relivant.
4584 * <script type="text/javascript">
4589 * This is code is also distributed under MIT license for use
4590 * with jQuery and prototype JavaScript libraries.
4593 * @class Roo.DomQuery
4594 Provides high performance selector/xpath processing by compiling queries into reusable functions. New pseudo classes and matchers can be plugged. It works on HTML and XML documents (if a content node is passed in).
4596 DomQuery supports most of the <a href="http://www.w3.org/TR/2005/WD-css3-selectors-20051215/">CSS3 selectors spec</a>, along with some custom selectors and basic XPath.</p>
4599 All selectors, attribute filters and pseudos below can be combined infinitely in any order. For example "div.foo:nth-child(odd)[@foo=bar].bar:first" would be a perfectly valid selector. Node filters are processed in the order in which they appear, which allows you to optimize your queries for your document structure.
4601 <h4>Element Selectors:</h4>
4603 <li> <b>*</b> any element</li>
4604 <li> <b>E</b> an element with the tag E</li>
4605 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4606 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4607 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4608 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4610 <h4>Attribute Selectors:</h4>
4611 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4613 <li> <b>E[foo]</b> has an attribute "foo"</li>
4614 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4615 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4616 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4617 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4618 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4619 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4621 <h4>Pseudo Classes:</h4>
4623 <li> <b>E:first-child</b> E is the first child of its parent</li>
4624 <li> <b>E:last-child</b> E is the last child of its parent</li>
4625 <li> <b>E:nth-child(<i>n</i>)</b> E is the <i>n</i>th child of its parent (1 based as per the spec)</li>
4626 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4627 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4628 <li> <b>E:only-child</b> E is the only child of its parent</li>
4629 <li> <b>E:checked</b> E is an element that is has a checked attribute that is true (e.g. a radio or checkbox) </li>
4630 <li> <b>E:first</b> the first E in the resultset</li>
4631 <li> <b>E:last</b> the last E in the resultset</li>
4632 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4633 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4634 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4635 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4636 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4637 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4638 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4639 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4640 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4642 <h4>CSS Value Selectors:</h4>
4644 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4645 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4646 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4647 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4648 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4649 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4653 Roo.DomQuery = function(){
4654 var cache = {}, simpleCache = {}, valueCache = {};
4655 var nonSpace = /\S/;
4656 var trimRe = /^\s+|\s+$/g;
4657 var tplRe = /\{(\d+)\}/g;
4658 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4659 var tagTokenRe = /^(#)?([\w-\*]+)/;
4660 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4662 function child(p, index){
4664 var n = p.firstChild;
4666 if(n.nodeType == 1){
4677 while((n = n.nextSibling) && n.nodeType != 1);
4682 while((n = n.previousSibling) && n.nodeType != 1);
4686 function children(d){
4687 var n = d.firstChild, ni = -1;
4689 var nx = n.nextSibling;
4690 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4700 function byClassName(c, a, v){
4704 var r = [], ri = -1, cn;
4705 for(var i = 0, ci; ci = c[i]; i++){
4706 if((' '+ci.className+' ').indexOf(v) != -1){
4713 function attrValue(n, attr){
4714 if(!n.tagName && typeof n.length != "undefined"){
4723 if(attr == "class" || attr == "className"){
4726 return n.getAttribute(attr) || n[attr];
4730 function getNodes(ns, mode, tagName){
4731 var result = [], ri = -1, cs;
4735 tagName = tagName || "*";
4736 if(typeof ns.getElementsByTagName != "undefined"){
4740 for(var i = 0, ni; ni = ns[i]; i++){
4741 cs = ni.getElementsByTagName(tagName);
4742 for(var j = 0, ci; ci = cs[j]; j++){
4746 }else if(mode == "/" || mode == ">"){
4747 var utag = tagName.toUpperCase();
4748 for(var i = 0, ni, cn; ni = ns[i]; i++){
4749 cn = ni.children || ni.childNodes;
4750 for(var j = 0, cj; cj = cn[j]; j++){
4751 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4756 }else if(mode == "+"){
4757 var utag = tagName.toUpperCase();
4758 for(var i = 0, n; n = ns[i]; i++){
4759 while((n = n.nextSibling) && n.nodeType != 1);
4760 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4764 }else if(mode == "~"){
4765 for(var i = 0, n; n = ns[i]; i++){
4766 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4775 function concat(a, b){
4779 for(var i = 0, l = b.length; i < l; i++){
4785 function byTag(cs, tagName){
4786 if(cs.tagName || cs == document){
4792 var r = [], ri = -1;
4793 tagName = tagName.toLowerCase();
4794 for(var i = 0, ci; ci = cs[i]; i++){
4795 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4802 function byId(cs, attr, id){
4803 if(cs.tagName || cs == document){
4809 var r = [], ri = -1;
4810 for(var i = 0,ci; ci = cs[i]; i++){
4811 if(ci && ci.id == id){
4819 function byAttribute(cs, attr, value, op, custom){
4820 var r = [], ri = -1, st = custom=="{";
4821 var f = Roo.DomQuery.operators[op];
4822 for(var i = 0, ci; ci = cs[i]; i++){
4825 a = Roo.DomQuery.getStyle(ci, attr);
4827 else if(attr == "class" || attr == "className"){
4829 }else if(attr == "for"){
4831 }else if(attr == "href"){
4832 a = ci.getAttribute("href", 2);
4834 a = ci.getAttribute(attr);
4836 if((f && f(a, value)) || (!f && a)){
4843 function byPseudo(cs, name, value){
4844 return Roo.DomQuery.pseudos[name](cs, value);
4847 // This is for IE MSXML which does not support expandos.
4848 // IE runs the same speed using setAttribute, however FF slows way down
4849 // and Safari completely fails so they need to continue to use expandos.
4850 var isIE = window.ActiveXObject ? true : false;
4852 // this eval is stop the compressor from
4853 // renaming the variable to something shorter
4855 /** eval:var:batch */
4860 function nodupIEXml(cs){
4862 cs[0].setAttribute("_nodup", d);
4864 for(var i = 1, len = cs.length; i < len; i++){
4866 if(!c.getAttribute("_nodup") != d){
4867 c.setAttribute("_nodup", d);
4871 for(var i = 0, len = cs.length; i < len; i++){
4872 cs[i].removeAttribute("_nodup");
4881 var len = cs.length, c, i, r = cs, cj, ri = -1;
4882 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4885 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4886 return nodupIEXml(cs);
4890 for(i = 1; c = cs[i]; i++){
4895 for(var j = 0; j < i; j++){
4898 for(j = i+1; cj = cs[j]; j++){
4910 function quickDiffIEXml(c1, c2){
4912 for(var i = 0, len = c1.length; i < len; i++){
4913 c1[i].setAttribute("_qdiff", d);
4916 for(var i = 0, len = c2.length; i < len; i++){
4917 if(c2[i].getAttribute("_qdiff") != d){
4918 r[r.length] = c2[i];
4921 for(var i = 0, len = c1.length; i < len; i++){
4922 c1[i].removeAttribute("_qdiff");
4927 function quickDiff(c1, c2){
4928 var len1 = c1.length;
4932 if(isIE && c1[0].selectSingleNode){
4933 return quickDiffIEXml(c1, c2);
4936 for(var i = 0; i < len1; i++){
4940 for(var i = 0, len = c2.length; i < len; i++){
4941 if(c2[i]._qdiff != d){
4942 r[r.length] = c2[i];
4948 function quickId(ns, mode, root, id){
4950 var d = root.ownerDocument || root;
4951 return d.getElementById(id);
4953 ns = getNodes(ns, mode, "*");
4954 return byId(ns, null, id);
4958 getStyle : function(el, name){
4959 return Roo.fly(el).getStyle(name);
4962 * Compiles a selector/xpath query into a reusable function. The returned function
4963 * takes one parameter "root" (optional), which is the context node from where the query should start.
4964 * @param {String} selector The selector/xpath query
4965 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4966 * @return {Function}
4968 compile : function(path, type){
4969 type = type || "select";
4971 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
4972 var q = path, mode, lq;
4973 var tk = Roo.DomQuery.matchers;
4974 var tklen = tk.length;
4977 // accept leading mode switch
4978 var lmode = q.match(modeRe);
4979 if(lmode && lmode[1]){
4980 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
4981 q = q.replace(lmode[1], "");
4983 // strip leading slashes
4984 while(path.substr(0, 1)=="/"){
4985 path = path.substr(1);
4988 while(q && lq != q){
4990 var tm = q.match(tagTokenRe);
4991 if(type == "select"){
4994 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
4996 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
4998 q = q.replace(tm[0], "");
4999 }else if(q.substr(0, 1) != '@'){
5000 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5005 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5007 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5009 q = q.replace(tm[0], "");
5012 while(!(mm = q.match(modeRe))){
5013 var matched = false;
5014 for(var j = 0; j < tklen; j++){
5016 var m = q.match(t.re);
5018 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5021 q = q.replace(m[0], "");
5026 // prevent infinite loop on bad selector
5028 throw 'Error parsing selector, parsing failed at "' + q + '"';
5032 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5033 q = q.replace(mm[1], "");
5036 fn[fn.length] = "return nodup(n);\n}";
5039 * list of variables that need from compression as they are used by eval.
5049 * eval:var:byClassName
5051 * eval:var:byAttribute
5052 * eval:var:attrValue
5060 * Selects a group of elements.
5061 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5062 * @param {Node} root (optional) The start of the query (defaults to document).
5065 select : function(path, root, type){
5066 if(!root || root == document){
5069 if(typeof root == "string"){
5070 root = document.getElementById(root);
5072 var paths = path.split(",");
5074 for(var i = 0, len = paths.length; i < len; i++){
5075 var p = paths[i].replace(trimRe, "");
5077 cache[p] = Roo.DomQuery.compile(p);
5079 throw p + " is not a valid selector";
5082 var result = cache[p](root);
5083 if(result && result != document){
5084 results = results.concat(result);
5087 if(paths.length > 1){
5088 return nodup(results);
5094 * Selects a single element.
5095 * @param {String} selector The selector/xpath query
5096 * @param {Node} root (optional) The start of the query (defaults to document).
5099 selectNode : function(path, root){
5100 return Roo.DomQuery.select(path, root)[0];
5104 * Selects the value of a node, optionally replacing null with the defaultValue.
5105 * @param {String} selector The selector/xpath query
5106 * @param {Node} root (optional) The start of the query (defaults to document).
5107 * @param {String} defaultValue
5109 selectValue : function(path, root, defaultValue){
5110 path = path.replace(trimRe, "");
5111 if(!valueCache[path]){
5112 valueCache[path] = Roo.DomQuery.compile(path, "select");
5114 var n = valueCache[path](root);
5115 n = n[0] ? n[0] : n;
5116 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5117 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5121 * Selects the value of a node, parsing integers and floats.
5122 * @param {String} selector The selector/xpath query
5123 * @param {Node} root (optional) The start of the query (defaults to document).
5124 * @param {Number} defaultValue
5127 selectNumber : function(path, root, defaultValue){
5128 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5129 return parseFloat(v);
5133 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5134 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5135 * @param {String} selector The simple selector to test
5138 is : function(el, ss){
5139 if(typeof el == "string"){
5140 el = document.getElementById(el);
5142 var isArray = (el instanceof Array);
5143 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5144 return isArray ? (result.length == el.length) : (result.length > 0);
5148 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5149 * @param {Array} el An array of elements to filter
5150 * @param {String} selector The simple selector to test
5151 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5152 * the selector instead of the ones that match
5155 filter : function(els, ss, nonMatches){
5156 ss = ss.replace(trimRe, "");
5157 if(!simpleCache[ss]){
5158 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5160 var result = simpleCache[ss](els);
5161 return nonMatches ? quickDiff(result, els) : result;
5165 * Collection of matching regular expressions and code snippets.
5169 select: 'n = byClassName(n, null, " {1} ");'
5171 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5172 select: 'n = byPseudo(n, "{1}", "{2}");'
5174 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5175 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5178 select: 'n = byId(n, null, "{1}");'
5181 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5186 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5187 * New operators can be added as long as the match the format <i>c</i>= where <i>c</i> is any character other than space, > <.
5190 "=" : function(a, v){
5193 "!=" : function(a, v){
5196 "^=" : function(a, v){
5197 return a && a.substr(0, v.length) == v;
5199 "$=" : function(a, v){
5200 return a && a.substr(a.length-v.length) == v;
5202 "*=" : function(a, v){
5203 return a && a.indexOf(v) !== -1;
5205 "%=" : function(a, v){
5206 return (a % v) == 0;
5208 "|=" : function(a, v){
5209 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5211 "~=" : function(a, v){
5212 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5217 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5218 * and the argument (if any) supplied in the selector.
5221 "first-child" : function(c){
5222 var r = [], ri = -1, n;
5223 for(var i = 0, ci; ci = n = c[i]; i++){
5224 while((n = n.previousSibling) && n.nodeType != 1);
5232 "last-child" : function(c){
5233 var r = [], ri = -1, n;
5234 for(var i = 0, ci; ci = n = c[i]; i++){
5235 while((n = n.nextSibling) && n.nodeType != 1);
5243 "nth-child" : function(c, a) {
5244 var r = [], ri = -1;
5245 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5246 var f = (m[1] || 1) - 0, l = m[2] - 0;
5247 for(var i = 0, n; n = c[i]; i++){
5248 var pn = n.parentNode;
5249 if (batch != pn._batch) {
5251 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5252 if(cn.nodeType == 1){
5259 if (l == 0 || n.nodeIndex == l){
5262 } else if ((n.nodeIndex + l) % f == 0){
5270 "only-child" : function(c){
5271 var r = [], ri = -1;;
5272 for(var i = 0, ci; ci = c[i]; i++){
5273 if(!prev(ci) && !next(ci)){
5280 "empty" : function(c){
5281 var r = [], ri = -1;
5282 for(var i = 0, ci; ci = c[i]; i++){
5283 var cns = ci.childNodes, j = 0, cn, empty = true;
5286 if(cn.nodeType == 1 || cn.nodeType == 3){
5298 "contains" : function(c, v){
5299 var r = [], ri = -1;
5300 for(var i = 0, ci; ci = c[i]; i++){
5301 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5308 "nodeValue" : function(c, v){
5309 var r = [], ri = -1;
5310 for(var i = 0, ci; ci = c[i]; i++){
5311 if(ci.firstChild && ci.firstChild.nodeValue == v){
5318 "checked" : function(c){
5319 var r = [], ri = -1;
5320 for(var i = 0, ci; ci = c[i]; i++){
5321 if(ci.checked == true){
5328 "not" : function(c, ss){
5329 return Roo.DomQuery.filter(c, ss, true);
5332 "odd" : function(c){
5333 return this["nth-child"](c, "odd");
5336 "even" : function(c){
5337 return this["nth-child"](c, "even");
5340 "nth" : function(c, a){
5341 return c[a-1] || [];
5344 "first" : function(c){
5348 "last" : function(c){
5349 return c[c.length-1] || [];
5352 "has" : function(c, ss){
5353 var s = Roo.DomQuery.select;
5354 var r = [], ri = -1;
5355 for(var i = 0, ci; ci = c[i]; i++){
5356 if(s(ss, ci).length > 0){
5363 "next" : function(c, ss){
5364 var is = Roo.DomQuery.is;
5365 var r = [], ri = -1;
5366 for(var i = 0, ci; ci = c[i]; i++){
5375 "prev" : function(c, ss){
5376 var is = Roo.DomQuery.is;
5377 var r = [], ri = -1;
5378 for(var i = 0, ci; ci = c[i]; i++){
5391 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5392 * @param {String} path The selector/xpath query
5393 * @param {Node} root (optional) The start of the query (defaults to document).
5398 Roo.query = Roo.DomQuery.select;