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
89 * Turn on debugging output (currently only the factory uses this)
96 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
99 enableGarbageCollector : true,
102 * True to automatically purge event listeners after uncaching an element (defaults to false).
103 * Note: this only happens if enableGarbageCollector is true.
106 enableListenerCollection:false,
109 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
110 * the IE insecure content warning (defaults to javascript:false).
113 SSL_SECURE_URL : "javascript:false",
116 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
117 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
120 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
122 emptyFn : function(){},
125 * Copies all the properties of config to obj if they don't already exist.
126 * @param {Object} obj The receiver of the properties
127 * @param {Object} config The source of the properties
128 * @return {Object} returns obj
130 applyIf : function(o, c){
133 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
140 * Applies event listeners to elements by selectors when the document is ready.
141 * The event name is specified with an @ suffix.
144 // add a listener for click on all anchors in element with id foo
145 '#foo a@click' : function(e, t){
149 // add the same listener to multiple selectors (separated by comma BEFORE the @)
150 '#foo a, #bar span.some-class@mouseover' : function(){
155 * @param {Object} obj The list of behaviors to apply
157 addBehaviors : function(o){
159 Roo.onReady(function(){
164 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
166 var parts = b.split('@');
167 if(parts[1]){ // for Object prototype breakers
170 cache[s] = Roo.select(s);
172 cache[s].on(parts[1], o[b]);
179 * Generates unique ids. If the element already has an id, it is unchanged
180 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
181 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
182 * @return {String} The generated Id.
184 id : function(el, prefix){
185 prefix = prefix || "roo-gen";
187 var id = prefix + (++idSeed);
188 return el ? (el.id ? el.id : (el.id = id)) : id;
193 * Extends one class with another class and optionally overrides members with the passed literal. This class
194 * also adds the function "override()" to the class that can be used to override
195 * members on an instance.
196 * @param {Object} subclass The class inheriting the functionality
197 * @param {Object} superclass The class being extended
198 * @param {Object} overrides (optional) A literal with members
203 var io = function(o){
208 return function(sb, sp, overrides){
209 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
212 sb = function(){sp.apply(this, arguments);};
214 var F = function(){}, sbp, spp = sp.prototype;
216 sbp = sb.prototype = new F();
220 if(spp.constructor == Object.prototype.constructor){
225 sb.override = function(o){
229 Roo.override(sb, overrides);
235 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
237 Roo.override(MyClass, {
238 newMethod1: function(){
241 newMethod2: function(foo){
246 * @param {Object} origclass The class to override
247 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
248 * containing one or more methods.
251 override : function(origclass, overrides){
253 var p = origclass.prototype;
254 for(var method in overrides){
255 p[method] = overrides[method];
260 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
262 Roo.namespace('Company', 'Company.data');
263 Company.Widget = function() { ... }
264 Company.data.CustomStore = function(config) { ... }
266 * @param {String} namespace1
267 * @param {String} namespace2
268 * @param {String} etc
271 namespace : function(){
272 var a=arguments, o=null, i, j, d, rt;
273 for (i=0; i<a.length; ++i) {
277 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
278 for (j=1; j<d.length; ++j) {
279 o[d[j]]=o[d[j]] || {};
285 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
287 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
288 Roo.factory(conf, Roo.data);
290 * @param {String} classname
291 * @param {String} namespace (optional)
295 factory : function(c, ns)
297 // no xtype, no ns or c.xns - or forced off by c.xns
298 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
301 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
302 if (c.constructor == ns[c.xtype]) {// already created...
306 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
307 var ret = new ns[c.xtype](c);
311 c.xns = false; // prevent recursion..
315 * Logs to console if it can.
317 * @param {String|Object} string
322 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
329 * 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.
333 urlEncode : function(o){
339 var ov = o[key], k = encodeURIComponent(key);
340 var type = typeof ov;
341 if(type == 'undefined'){
343 }else if(type != "function" && type != "object"){
344 buf.push(k, "=", encodeURIComponent(ov), "&");
345 }else if(ov instanceof Array){
347 for(var i = 0, len = ov.length; i < len; i++) {
348 buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
360 * 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]}.
361 * @param {String} string
362 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
363 * @return {Object} A literal with members
365 urlDecode : function(string, overwrite){
366 if(!string || !string.length){
370 var pairs = string.split('&');
371 var pair, name, value;
372 for(var i = 0, len = pairs.length; i < len; i++){
373 pair = pairs[i].split('=');
374 name = decodeURIComponent(pair[0]);
375 value = decodeURIComponent(pair[1]);
376 if(overwrite !== true){
377 if(typeof obj[name] == "undefined"){
379 }else if(typeof obj[name] == "string"){
380 obj[name] = [obj[name]];
381 obj[name].push(value);
383 obj[name].push(value);
393 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
394 * passed array is not really an array, your function is called once with it.
395 * The supplied function is called with (Object item, Number index, Array allItems).
396 * @param {Array/NodeList/Mixed} array
397 * @param {Function} fn
398 * @param {Object} scope
400 each : function(array, fn, scope){
401 if(typeof array.length == "undefined" || typeof array == "string"){
404 for(var i = 0, len = array.length; i < len; i++){
405 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
410 combine : function(){
411 var as = arguments, l = as.length, r = [];
412 for(var i = 0; i < l; i++){
414 if(a instanceof Array){
416 }else if(a.length !== undefined && !a.substr){
417 r = r.concat(Array.prototype.slice.call(a, 0));
426 * Escapes the passed string for use in a regular expression
427 * @param {String} str
430 escapeRe : function(s) {
431 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
435 callback : function(cb, scope, args, delay){
436 if(typeof cb == "function"){
438 cb.defer(delay, scope, args || []);
440 cb.apply(scope, args || []);
446 * Return the dom node for the passed string (id), dom node, or Roo.Element
447 * @param {String/HTMLElement/Roo.Element} el
448 * @return HTMLElement
450 getDom : function(el){
454 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
458 * Shorthand for {@link Roo.ComponentMgr#get}
460 * @return Roo.Component
462 getCmp : function(id){
463 return Roo.ComponentMgr.get(id);
466 num : function(v, defaultValue){
467 if(typeof v != 'number'){
473 destroy : function(){
474 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
478 as.removeAllListeners();
482 if(typeof as.purgeListeners == 'function'){
485 if(typeof as.destroy == 'function'){
492 // inpired by a similar function in mootools library
494 * Returns the type of object that is passed in. If the object passed in is null or undefined it
495 * return false otherwise it returns one of the following values:<ul>
496 * <li><b>string</b>: If the object passed is a string</li>
497 * <li><b>number</b>: If the object passed is a number</li>
498 * <li><b>boolean</b>: If the object passed is a boolean value</li>
499 * <li><b>function</b>: If the object passed is a function reference</li>
500 * <li><b>object</b>: If the object passed is an object</li>
501 * <li><b>array</b>: If the object passed is an array</li>
502 * <li><b>regexp</b>: If the object passed is a regular expression</li>
503 * <li><b>element</b>: If the object passed is a DOM Element</li>
504 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
505 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
506 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
507 * @param {Mixed} object
511 if(o === undefined || o === null){
518 if(t == 'object' && o.nodeName) {
520 case 1: return 'element';
521 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
524 if(t == 'object' || t == 'function') {
525 switch(o.constructor) {
526 case Array: return 'array';
527 case RegExp: return 'regexp';
529 if(typeof o.length == 'number' && typeof o.item == 'function') {
537 * Returns true if the passed value is null, undefined or an empty string (optional).
538 * @param {Mixed} value The value to test
539 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
542 isEmpty : function(v, allowBlank){
543 return v === null || v === undefined || (!allowBlank ? v === '' : false);
557 isBorderBox : isBorderBox,
559 isWindows : isWindows,
566 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
567 * you may want to set this to true.
570 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
575 * Selects a single element as a Roo Element
576 * This is about as close as you can get to jQuery's $('do crazy stuff')
577 * @param {String} selector The selector/xpath query
578 * @param {Node} root (optional) The start of the query (defaults to document).
579 * @return {Roo.Element}
581 selectNode : function(selector, root)
583 var node = Roo.DomQuery.selectNode(selector,root);
584 return node ? Roo.get(node) : false;
592 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
593 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
596 * Ext JS Library 1.1.1
597 * Copyright(c) 2006-2007, Ext JS, LLC.
599 * Originally Released Under LGPL - original licence link has changed is not relivant.
602 * <script type="text/javascript">
606 // wrappedn so fnCleanup is not in global scope...
608 function fnCleanUp() {
609 var p = Function.prototype;
610 delete p.createSequence;
612 delete p.createDelegate;
613 delete p.createCallback;
614 delete p.createInterceptor;
616 window.detachEvent("onunload", fnCleanUp);
618 window.attachEvent("onunload", fnCleanUp);
625 * These functions are available on every Function object (any JavaScript function).
627 Roo.apply(Function.prototype, {
629 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
630 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
631 * Will create a function that is bound to those 2 args.
632 * @return {Function} The new function
634 createCallback : function(/*args...*/){
635 // make args available, in function below
636 var args = arguments;
639 return method.apply(window, args);
644 * Creates a delegate (callback) that sets the scope to obj.
645 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
646 * Will create a function that is automatically scoped to this.
647 * @param {Object} obj (optional) The object for which the scope is set
648 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
649 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
650 * if a number the args are inserted at the specified position
651 * @return {Function} The new function
653 createDelegate : function(obj, args, appendArgs){
656 var callArgs = args || arguments;
657 if(appendArgs === true){
658 callArgs = Array.prototype.slice.call(arguments, 0);
659 callArgs = callArgs.concat(args);
660 }else if(typeof appendArgs == "number"){
661 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
662 var applyArgs = [appendArgs, 0].concat(args); // create method call params
663 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
665 return method.apply(obj || window, callArgs);
670 * Calls this function after the number of millseconds specified.
671 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
672 * @param {Object} obj (optional) The object for which the scope is set
673 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
674 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
675 * if a number the args are inserted at the specified position
676 * @return {Number} The timeout id that can be used with clearTimeout
678 defer : function(millis, obj, args, appendArgs){
679 var fn = this.createDelegate(obj, args, appendArgs);
681 return setTimeout(fn, millis);
687 * Create a combined function call sequence of the original function + the passed function.
688 * The resulting function returns the results of the original function.
689 * The passed fcn is called with the parameters of the original function
690 * @param {Function} fcn The function to sequence
691 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
692 * @return {Function} The new function
694 createSequence : function(fcn, scope){
695 if(typeof fcn != "function"){
700 var retval = method.apply(this || window, arguments);
701 fcn.apply(scope || this || window, arguments);
707 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
708 * The resulting function returns the results of the original function.
709 * The passed fcn is called with the parameters of the original function.
711 * @param {Function} fcn The function to call before the original
712 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
713 * @return {Function} The new function
715 createInterceptor : function(fcn, scope){
716 if(typeof fcn != "function"){
723 if(fcn.apply(scope || this || window, arguments) === false){
726 return method.apply(this || window, arguments);
732 * Ext JS Library 1.1.1
733 * Copyright(c) 2006-2007, Ext JS, LLC.
735 * Originally Released Under LGPL - original licence link has changed is not relivant.
738 * <script type="text/javascript">
741 Roo.applyIf(String, {
746 * Escapes the passed string for ' and \
747 * @param {String} string The string to escape
748 * @return {String} The escaped string
751 escape : function(string) {
752 return string.replace(/('|\\)/g, "\\$1");
756 * Pads the left side of a string with a specified character. This is especially useful
757 * for normalizing number and date strings. Example usage:
759 var s = String.leftPad('123', 5, '0');
760 // s now contains the string: '00123'
762 * @param {String} string The original string
763 * @param {Number} size The total length of the output string
764 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
765 * @return {String} The padded string
768 leftPad : function (val, size, ch) {
769 var result = new String(val);
770 if(ch === null || ch === undefined || ch === '') {
773 while (result.length < size) {
774 result = ch + result;
780 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
781 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
783 var cls = 'my-class', text = 'Some text';
784 var s = String.format('<div class="{0}">{1}</div>', cls, text);
785 // s now contains the string: '<div class="my-class">Some text</div>'
787 * @param {String} string The tokenized string to be formatted
788 * @param {String} value1 The value to replace token {0}
789 * @param {String} value2 Etc...
790 * @return {String} The formatted string
793 format : function(format){
794 var args = Array.prototype.slice.call(arguments, 1);
795 return format.replace(/\{(\d+)\}/g, function(m, i){
796 return Roo.util.Format.htmlEncode(args[i]);
802 * Utility function that allows you to easily switch a string between two alternating values. The passed value
803 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
804 * they are already different, the first value passed in is returned. Note that this method returns the new value
805 * but does not change the current string.
807 // alternate sort directions
808 sort = sort.toggle('ASC', 'DESC');
810 // instead of conditional logic:
811 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
813 * @param {String} value The value to compare to the current string
814 * @param {String} other The new value to use if the string already equals the first value passed in
815 * @return {String} The new value
818 String.prototype.toggle = function(value, other){
819 return this == value ? other : value;
822 * Ext JS Library 1.1.1
823 * Copyright(c) 2006-2007, Ext JS, LLC.
825 * Originally Released Under LGPL - original licence link has changed is not relivant.
828 * <script type="text/javascript">
834 Roo.applyIf(Number.prototype, {
836 * Checks whether or not the current number is within a desired range. If the number is already within the
837 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
838 * exceeded. Note that this method returns the constrained value but does not change the current number.
839 * @param {Number} min The minimum number in the range
840 * @param {Number} max The maximum number in the range
841 * @return {Number} The constrained value if outside the range, otherwise the current value
843 constrain : function(min, max){
844 return Math.min(Math.max(this, min), max);
848 * Ext JS Library 1.1.1
849 * Copyright(c) 2006-2007, Ext JS, LLC.
851 * Originally Released Under LGPL - original licence link has changed is not relivant.
854 * <script type="text/javascript">
859 Roo.applyIf(Array.prototype, {
861 * Checks whether or not the specified object exists in the array.
862 * @param {Object} o The object to check for
863 * @return {Number} The index of o in the array (or -1 if it is not found)
865 indexOf : function(o){
866 for (var i = 0, len = this.length; i < len; i++){
867 if(this[i] == o) return i;
873 * Removes the specified object from the array. If the object is not found nothing happens.
874 * @param {Object} o The object to remove
876 remove : function(o){
877 var index = this.indexOf(o);
879 this.splice(index, 1);
883 * Map (JS 1.6 compatibility)
884 * @param {Function} function to call
888 var len = this.length >>> 0;
889 if (typeof fun != "function")
890 throw new TypeError();
892 var res = new Array(len);
893 var thisp = arguments[1];
894 for (var i = 0; i < len; i++)
897 res[i] = fun.call(thisp, this[i], i, this);
908 * Ext JS Library 1.1.1
909 * Copyright(c) 2006-2007, Ext JS, LLC.
911 * Originally Released Under LGPL - original licence link has changed is not relivant.
914 * <script type="text/javascript">
920 * The date parsing and format syntax is a subset of
921 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
922 * supported will provide results equivalent to their PHP versions.
924 * Following is the list of all currently supported formats:
927 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
929 Format Output Description
930 ------ ---------- --------------------------------------------------------------
931 d 10 Day of the month, 2 digits with leading zeros
932 D Wed A textual representation of a day, three letters
933 j 10 Day of the month without leading zeros
934 l Wednesday A full textual representation of the day of the week
935 S th English ordinal day of month suffix, 2 chars (use with j)
936 w 3 Numeric representation of the day of the week
937 z 9 The julian date, or day of the year (0-365)
938 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
939 F January A full textual representation of the month
940 m 01 Numeric representation of a month, with leading zeros
941 M Jan Month name abbreviation, three letters
942 n 1 Numeric representation of a month, without leading zeros
943 t 31 Number of days in the given month
944 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
945 Y 2007 A full numeric representation of a year, 4 digits
946 y 07 A two digit representation of a year
947 a pm Lowercase Ante meridiem and Post meridiem
948 A PM Uppercase Ante meridiem and Post meridiem
949 g 3 12-hour format of an hour without leading zeros
950 G 15 24-hour format of an hour without leading zeros
951 h 03 12-hour format of an hour with leading zeros
952 H 15 24-hour format of an hour with leading zeros
953 i 05 Minutes with leading zeros
954 s 01 Seconds, with leading zeros
955 O -0600 Difference to Greenwich time (GMT) in hours
956 T CST Timezone setting of the machine running the code
957 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
960 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
962 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
963 document.write(dt.format('Y-m-d')); //2007-01-10
964 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
965 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
968 * Here are some standard date/time patterns that you might find helpful. They
969 * are not part of the source of Date.js, but to use them you can simply copy this
970 * block of code into any script that is included after Date.js and they will also become
971 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
974 ISO8601Long:"Y-m-d H:i:s",
975 ISO8601Short:"Y-m-d",
977 LongDate: "l, F d, Y",
978 FullDateTime: "l, F d, Y g:i:s A",
982 SortableDateTime: "Y-m-d\\TH:i:s",
983 UniversalSortableDateTime: "Y-m-d H:i:sO",
991 document.write(dt.format(Date.patterns.ShortDate));
996 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
997 * They generate precompiled functions from date formats instead of parsing and
998 * processing the pattern every time you format a date. These functions are available
999 * on every Date object (any javascript function).
1001 * The original article and download are here:
1002 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
1009 Returns the number of milliseconds between this date and date
1010 @param {Date} date (optional) Defaults to now
1011 @return {Number} The diff in milliseconds
1012 @member Date getElapsed
1014 Date.prototype.getElapsed = function(date) {
1015 return Math.abs((date || new Date()).getTime()-this.getTime());
1017 // was in date file..
1021 Date.parseFunctions = {count:0};
1023 Date.parseRegexes = [];
1025 Date.formatFunctions = {count:0};
1028 Date.prototype.dateFormat = function(format) {
1029 if (Date.formatFunctions[format] == null) {
1030 Date.createNewFormat(format);
1032 var func = Date.formatFunctions[format];
1033 return this[func]();
1038 * Formats a date given the supplied format string
1039 * @param {String} format The format string
1040 * @return {String} The formatted date
1043 Date.prototype.format = Date.prototype.dateFormat;
1046 Date.createNewFormat = function(format) {
1047 var funcName = "format" + Date.formatFunctions.count++;
1048 Date.formatFunctions[format] = funcName;
1049 var code = "Date.prototype." + funcName + " = function(){return ";
1050 var special = false;
1052 for (var i = 0; i < format.length; ++i) {
1053 ch = format.charAt(i);
1054 if (!special && ch == "\\") {
1059 code += "'" + String.escape(ch) + "' + ";
1062 code += Date.getFormatCode(ch);
1065 /** eval:var:zzzzzzzzzzzzz */
1066 eval(code.substring(0, code.length - 3) + ";}");
1070 Date.getFormatCode = function(character) {
1071 switch (character) {
1073 return "String.leftPad(this.getDate(), 2, '0') + ";
1075 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1077 return "this.getDate() + ";
1079 return "Date.dayNames[this.getDay()] + ";
1081 return "this.getSuffix() + ";
1083 return "this.getDay() + ";
1085 return "this.getDayOfYear() + ";
1087 return "this.getWeekOfYear() + ";
1089 return "Date.monthNames[this.getMonth()] + ";
1091 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1093 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1095 return "(this.getMonth() + 1) + ";
1097 return "this.getDaysInMonth() + ";
1099 return "(this.isLeapYear() ? 1 : 0) + ";
1101 return "this.getFullYear() + ";
1103 return "('' + this.getFullYear()).substring(2, 4) + ";
1105 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1107 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1109 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1111 return "this.getHours() + ";
1113 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1115 return "String.leftPad(this.getHours(), 2, '0') + ";
1117 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1119 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1121 return "this.getGMTOffset() + ";
1123 return "this.getTimezone() + ";
1125 return "(this.getTimezoneOffset() * -60) + ";
1127 return "'" + String.escape(character) + "' + ";
1132 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1133 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1134 * the date format that is not specified will default to the current date value for that part. Time parts can also
1135 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1136 * string or the parse operation will fail.
1139 //dt = Fri May 25 2007 (current date)
1140 var dt = new Date();
1142 //dt = Thu May 25 2006 (today's month/day in 2006)
1143 dt = Date.parseDate("2006", "Y");
1145 //dt = Sun Jan 15 2006 (all date parts specified)
1146 dt = Date.parseDate("2006-1-15", "Y-m-d");
1148 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1149 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1151 * @param {String} input The unparsed date as a string
1152 * @param {String} format The format the date is in
1153 * @return {Date} The parsed date
1156 Date.parseDate = function(input, format) {
1157 if (Date.parseFunctions[format] == null) {
1158 Date.createParser(format);
1160 var func = Date.parseFunctions[format];
1161 return Date[func](input);
1166 Date.createParser = function(format) {
1167 var funcName = "parse" + Date.parseFunctions.count++;
1168 var regexNum = Date.parseRegexes.length;
1169 var currentGroup = 1;
1170 Date.parseFunctions[format] = funcName;
1172 var code = "Date." + funcName + " = function(input){\n"
1173 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1174 + "var d = new Date();\n"
1175 + "y = d.getFullYear();\n"
1176 + "m = d.getMonth();\n"
1177 + "d = d.getDate();\n"
1178 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1179 + "if (results && results.length > 0) {";
1182 var special = false;
1184 for (var i = 0; i < format.length; ++i) {
1185 ch = format.charAt(i);
1186 if (!special && ch == "\\") {
1191 regex += String.escape(ch);
1194 var obj = Date.formatCodeToRegex(ch, currentGroup);
1195 currentGroup += obj.g;
1197 if (obj.g && obj.c) {
1203 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1204 + "{v = new Date(y, m, d, h, i, s);}\n"
1205 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1206 + "{v = new Date(y, m, d, h, i);}\n"
1207 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1208 + "{v = new Date(y, m, d, h);}\n"
1209 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1210 + "{v = new Date(y, m, d);}\n"
1211 + "else if (y >= 0 && m >= 0)\n"
1212 + "{v = new Date(y, m);}\n"
1213 + "else if (y >= 0)\n"
1214 + "{v = new Date(y);}\n"
1215 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1216 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1217 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1220 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1221 /** eval:var:zzzzzzzzzzzzz */
1226 Date.formatCodeToRegex = function(character, currentGroup) {
1227 switch (character) {
1231 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1234 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1235 s:"(\\d{1,2})"}; // day of month without leading zeroes
1238 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1239 s:"(\\d{2})"}; // day of month with leading zeroes
1243 s:"(?:" + Date.dayNames.join("|") + ")"};
1247 s:"(?:st|nd|rd|th)"};
1262 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1263 s:"(" + Date.monthNames.join("|") + ")"};
1266 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1267 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1270 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1271 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1274 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1275 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1286 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1290 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1291 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1295 c:"if (results[" + currentGroup + "] == 'am') {\n"
1296 + "if (h == 12) { h = 0; }\n"
1297 + "} else { if (h < 12) { h += 12; }}",
1301 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1302 + "if (h == 12) { h = 0; }\n"
1303 + "} else { if (h < 12) { h += 12; }}",
1308 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1309 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1313 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1314 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1317 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1321 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1326 "o = results[", currentGroup, "];\n",
1327 "var sn = o.substring(0,1);\n", // get + / - sign
1328 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1329 "var mn = o.substring(3,5) % 60;\n", // get minutes
1330 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1331 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1337 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1340 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1341 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1342 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1346 s:String.escape(character)};
1351 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1352 * @return {String} The abbreviated timezone name (e.g. 'CST')
1354 Date.prototype.getTimezone = function() {
1355 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1359 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1360 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1362 Date.prototype.getGMTOffset = function() {
1363 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1364 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1365 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1369 * Get the numeric day number of the year, adjusted for leap year.
1370 * @return {Number} 0 through 364 (365 in leap years)
1372 Date.prototype.getDayOfYear = function() {
1374 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1375 for (var i = 0; i < this.getMonth(); ++i) {
1376 num += Date.daysInMonth[i];
1378 return num + this.getDate() - 1;
1382 * Get the string representation of the numeric week number of the year
1383 * (equivalent to the format specifier 'W').
1384 * @return {String} '00' through '52'
1386 Date.prototype.getWeekOfYear = function() {
1387 // Skip to Thursday of this week
1388 var now = this.getDayOfYear() + (4 - this.getDay());
1389 // Find the first Thursday of the year
1390 var jan1 = new Date(this.getFullYear(), 0, 1);
1391 var then = (7 - jan1.getDay() + 4);
1392 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1396 * Whether or not the current date is in a leap year.
1397 * @return {Boolean} True if the current date is in a leap year, else false
1399 Date.prototype.isLeapYear = function() {
1400 var year = this.getFullYear();
1401 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1405 * Get the first day of the current month, adjusted for leap year. The returned value
1406 * is the numeric day index within the week (0-6) which can be used in conjunction with
1407 * the {@link #monthNames} array to retrieve the textual day name.
1410 var dt = new Date('1/10/2007');
1411 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1413 * @return {Number} The day number (0-6)
1415 Date.prototype.getFirstDayOfMonth = function() {
1416 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1417 return (day < 0) ? (day + 7) : day;
1421 * Get the last day of the current month, adjusted for leap year. The returned value
1422 * is the numeric day index within the week (0-6) which can be used in conjunction with
1423 * the {@link #monthNames} array to retrieve the textual day name.
1426 var dt = new Date('1/10/2007');
1427 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1429 * @return {Number} The day number (0-6)
1431 Date.prototype.getLastDayOfMonth = function() {
1432 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1433 return (day < 0) ? (day + 7) : day;
1438 * Get the first date of this date's month
1441 Date.prototype.getFirstDateOfMonth = function() {
1442 return new Date(this.getFullYear(), this.getMonth(), 1);
1446 * Get the last date of this date's month
1449 Date.prototype.getLastDateOfMonth = function() {
1450 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1453 * Get the number of days in the current month, adjusted for leap year.
1454 * @return {Number} The number of days in the month
1456 Date.prototype.getDaysInMonth = function() {
1457 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1458 return Date.daysInMonth[this.getMonth()];
1462 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1463 * @return {String} 'st, 'nd', 'rd' or 'th'
1465 Date.prototype.getSuffix = function() {
1466 switch (this.getDate()) {
1483 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1486 * An array of textual month names.
1487 * Override these values for international dates, for example...
1488 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1507 * An array of textual day names.
1508 * Override these values for international dates, for example...
1509 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1525 Date.monthNumbers = {
1540 * Creates and returns a new Date instance with the exact same date value as the called instance.
1541 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1542 * variable will also be changed. When the intention is to create a new variable that will not
1543 * modify the original instance, you should create a clone.
1545 * Example of correctly cloning a date:
1548 var orig = new Date('10/1/2006');
1551 document.write(orig); //returns 'Thu Oct 05 2006'!
1554 var orig = new Date('10/1/2006');
1555 var copy = orig.clone();
1557 document.write(orig); //returns 'Thu Oct 01 2006'
1559 * @return {Date} The new Date instance
1561 Date.prototype.clone = function() {
1562 return new Date(this.getTime());
1566 * Clears any time information from this date
1567 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1568 @return {Date} this or the clone
1570 Date.prototype.clearTime = function(clone){
1572 return this.clone().clearTime();
1577 this.setMilliseconds(0);
1582 // safari setMonth is broken
1584 Date.brokenSetMonth = Date.prototype.setMonth;
1585 Date.prototype.setMonth = function(num){
1587 var n = Math.ceil(-num);
1588 var back_year = Math.ceil(n/12);
1589 var month = (n % 12) ? 12 - n % 12 : 0 ;
1590 this.setFullYear(this.getFullYear() - back_year);
1591 return Date.brokenSetMonth.call(this, month);
1593 return Date.brokenSetMonth.apply(this, arguments);
1598 /** Date interval constant
1602 /** Date interval constant
1606 /** Date interval constant
1610 /** Date interval constant
1614 /** Date interval constant
1618 /** Date interval constant
1622 /** Date interval constant
1628 * Provides a convenient method of performing basic date arithmetic. This method
1629 * does not modify the Date instance being called - it creates and returns
1630 * a new Date instance containing the resulting date value.
1635 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1636 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1638 //Negative values will subtract correctly:
1639 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1640 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1642 //You can even chain several calls together in one line!
1643 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1644 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1647 * @param {String} interval A valid date interval enum value
1648 * @param {Number} value The amount to add to the current date
1649 * @return {Date} The new Date instance
1651 Date.prototype.add = function(interval, value){
1652 var d = this.clone();
1653 if (!interval || value === 0) return d;
1654 switch(interval.toLowerCase()){
1656 d.setMilliseconds(this.getMilliseconds() + value);
1659 d.setSeconds(this.getSeconds() + value);
1662 d.setMinutes(this.getMinutes() + value);
1665 d.setHours(this.getHours() + value);
1668 d.setDate(this.getDate() + value);
1671 var day = this.getDate();
1673 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1676 d.setMonth(this.getMonth() + value);
1679 d.setFullYear(this.getFullYear() + value);
1685 * Ext JS Library 1.1.1
1686 * Copyright(c) 2006-2007, Ext JS, LLC.
1688 * Originally Released Under LGPL - original licence link has changed is not relivant.
1691 * <script type="text/javascript">
1695 getViewWidth : function(full) {
1696 return full ? this.getDocumentWidth() : this.getViewportWidth();
1699 getViewHeight : function(full) {
1700 return full ? this.getDocumentHeight() : this.getViewportHeight();
1703 getDocumentHeight: function() {
1704 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1705 return Math.max(scrollHeight, this.getViewportHeight());
1708 getDocumentWidth: function() {
1709 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1710 return Math.max(scrollWidth, this.getViewportWidth());
1713 getViewportHeight: function() {
1714 var height = self.innerHeight;
1715 var mode = document.compatMode;
1717 if ((mode || Roo.isIE) && !Roo.isOpera) {
1718 height = (mode == "CSS1Compat") ?
1719 document.documentElement.clientHeight :
1720 document.body.clientHeight;
1726 getViewportWidth: function() {
1727 var width = self.innerWidth;
1728 var mode = document.compatMode;
1730 if (mode || Roo.isIE) {
1731 width = (mode == "CSS1Compat") ?
1732 document.documentElement.clientWidth :
1733 document.body.clientWidth;
1738 isAncestor : function(p, c) {
1745 if (p.contains && !Roo.isSafari) {
1746 return p.contains(c);
1747 } else if (p.compareDocumentPosition) {
1748 return !!(p.compareDocumentPosition(c) & 16);
1750 var parent = c.parentNode;
1755 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1758 parent = parent.parentNode;
1764 getRegion : function(el) {
1765 return Roo.lib.Region.getRegion(el);
1768 getY : function(el) {
1769 return this.getXY(el)[1];
1772 getX : function(el) {
1773 return this.getXY(el)[0];
1776 getXY : function(el) {
1777 var p, pe, b, scroll, bd = document.body;
1778 el = Roo.getDom(el);
1779 var fly = Roo.lib.AnimBase.fly;
1780 if (el.getBoundingClientRect) {
1781 b = el.getBoundingClientRect();
1782 scroll = fly(document).getScroll();
1783 return [b.left + scroll.left, b.top + scroll.top];
1789 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1796 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1803 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1804 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1811 if (p != el && pe.getStyle('overflow') != 'visible') {
1819 if (Roo.isSafari && hasAbsolute) {
1824 if (Roo.isGecko && !hasAbsolute) {
1826 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1827 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1831 while (p && p != bd) {
1832 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1844 setXY : function(el, xy) {
1845 el = Roo.fly(el, '_setXY');
1847 var pts = el.translatePoints(xy);
1848 if (xy[0] !== false) {
1849 el.dom.style.left = pts.left + "px";
1851 if (xy[1] !== false) {
1852 el.dom.style.top = pts.top + "px";
1856 setX : function(el, x) {
1857 this.setXY(el, [x, false]);
1860 setY : function(el, y) {
1861 this.setXY(el, [false, y]);
1865 * Portions of this file are based on pieces of Yahoo User Interface Library
1866 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1867 * YUI licensed under the BSD License:
1868 * http://developer.yahoo.net/yui/license.txt
1869 * <script type="text/javascript">
1873 Roo.lib.Event = function() {
1874 var loadComplete = false;
1876 var unloadListeners = [];
1878 var onAvailStack = [];
1880 var lastError = null;
1893 startInterval: function() {
1894 if (!this._interval) {
1896 var callback = function() {
1897 self._tryPreloadAttach();
1899 this._interval = setInterval(callback, this.POLL_INTERVAL);
1904 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1905 onAvailStack.push({ id: p_id,
1908 override: p_override,
1909 checkReady: false });
1911 retryCount = this.POLL_RETRYS;
1912 this.startInterval();
1916 addListener: function(el, eventName, fn) {
1917 el = Roo.getDom(el);
1922 if ("unload" == eventName) {
1923 unloadListeners[unloadListeners.length] =
1924 [el, eventName, fn];
1928 var wrappedFn = function(e) {
1929 return fn(Roo.lib.Event.getEvent(e));
1932 var li = [el, eventName, fn, wrappedFn];
1934 var index = listeners.length;
1935 listeners[index] = li;
1937 this.doAdd(el, eventName, wrappedFn, false);
1943 removeListener: function(el, eventName, fn) {
1946 el = Roo.getDom(el);
1949 return this.purgeElement(el, false, eventName);
1953 if ("unload" == eventName) {
1955 for (i = 0,len = unloadListeners.length; i < len; i++) {
1956 var li = unloadListeners[i];
1959 li[1] == eventName &&
1961 unloadListeners.splice(i, 1);
1969 var cacheItem = null;
1972 var index = arguments[3];
1974 if ("undefined" == typeof index) {
1975 index = this._getCacheIndex(el, eventName, fn);
1979 cacheItem = listeners[index];
1982 if (!el || !cacheItem) {
1986 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1988 delete listeners[index][this.WFN];
1989 delete listeners[index][this.FN];
1990 listeners.splice(index, 1);
1997 getTarget: function(ev, resolveTextNode) {
1998 ev = ev.browserEvent || ev;
1999 var t = ev.target || ev.srcElement;
2000 return this.resolveTextNode(t);
2004 resolveTextNode: function(node) {
2005 if (Roo.isSafari && node && 3 == node.nodeType) {
2006 return node.parentNode;
2013 getPageX: function(ev) {
2014 ev = ev.browserEvent || ev;
2016 if (!x && 0 !== x) {
2017 x = ev.clientX || 0;
2020 x += this.getScroll()[1];
2028 getPageY: function(ev) {
2029 ev = ev.browserEvent || ev;
2031 if (!y && 0 !== y) {
2032 y = ev.clientY || 0;
2035 y += this.getScroll()[0];
2044 getXY: function(ev) {
2045 ev = ev.browserEvent || ev;
2046 return [this.getPageX(ev), this.getPageY(ev)];
2050 getRelatedTarget: function(ev) {
2051 ev = ev.browserEvent || ev;
2052 var t = ev.relatedTarget;
2054 if (ev.type == "mouseout") {
2056 } else if (ev.type == "mouseover") {
2061 return this.resolveTextNode(t);
2065 getTime: function(ev) {
2066 ev = ev.browserEvent || ev;
2068 var t = new Date().getTime();
2072 this.lastError = ex;
2081 stopEvent: function(ev) {
2082 this.stopPropagation(ev);
2083 this.preventDefault(ev);
2087 stopPropagation: function(ev) {
2088 ev = ev.browserEvent || ev;
2089 if (ev.stopPropagation) {
2090 ev.stopPropagation();
2092 ev.cancelBubble = true;
2097 preventDefault: function(ev) {
2098 ev = ev.browserEvent || ev;
2099 if(ev.preventDefault) {
2100 ev.preventDefault();
2102 ev.returnValue = false;
2107 getEvent: function(e) {
2108 var ev = e || window.event;
2110 var c = this.getEvent.caller;
2112 ev = c.arguments[0];
2113 if (ev && Event == ev.constructor) {
2123 getCharCode: function(ev) {
2124 ev = ev.browserEvent || ev;
2125 return ev.charCode || ev.keyCode || 0;
2129 _getCacheIndex: function(el, eventName, fn) {
2130 for (var i = 0,len = listeners.length; i < len; ++i) {
2131 var li = listeners[i];
2133 li[this.FN] == fn &&
2134 li[this.EL] == el &&
2135 li[this.TYPE] == eventName) {
2147 getEl: function(id) {
2148 return document.getElementById(id);
2152 clearCache: function() {
2156 _load: function(e) {
2157 loadComplete = true;
2158 var EU = Roo.lib.Event;
2162 EU.doRemove(window, "load", EU._load);
2167 _tryPreloadAttach: function() {
2176 var tryAgain = !loadComplete;
2178 tryAgain = (retryCount > 0);
2183 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2184 var item = onAvailStack[i];
2186 var el = this.getEl(item.id);
2189 if (!item.checkReady ||
2192 (document && document.body)) {
2195 if (item.override) {
2196 if (item.override === true) {
2199 scope = item.override;
2202 item.fn.call(scope, item.obj);
2203 onAvailStack[i] = null;
2206 notAvail.push(item);
2211 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2215 this.startInterval();
2217 clearInterval(this._interval);
2218 this._interval = null;
2221 this.locked = false;
2228 purgeElement: function(el, recurse, eventName) {
2229 var elListeners = this.getListeners(el, eventName);
2231 for (var i = 0,len = elListeners.length; i < len; ++i) {
2232 var l = elListeners[i];
2233 this.removeListener(el, l.type, l.fn);
2237 if (recurse && el && el.childNodes) {
2238 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2239 this.purgeElement(el.childNodes[i], recurse, eventName);
2245 getListeners: function(el, eventName) {
2246 var results = [], searchLists;
2248 searchLists = [listeners, unloadListeners];
2249 } else if (eventName == "unload") {
2250 searchLists = [unloadListeners];
2252 searchLists = [listeners];
2255 for (var j = 0; j < searchLists.length; ++j) {
2256 var searchList = searchLists[j];
2257 if (searchList && searchList.length > 0) {
2258 for (var i = 0,len = searchList.length; i < len; ++i) {
2259 var l = searchList[i];
2260 if (l && l[this.EL] === el &&
2261 (!eventName || eventName === l[this.TYPE])) {
2266 adjust: l[this.ADJ_SCOPE],
2274 return (results.length) ? results : null;
2278 _unload: function(e) {
2280 var EU = Roo.lib.Event, i, j, l, len, index;
2282 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2283 l = unloadListeners[i];
2286 if (l[EU.ADJ_SCOPE]) {
2287 if (l[EU.ADJ_SCOPE] === true) {
2290 scope = l[EU.ADJ_SCOPE];
2293 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2294 unloadListeners[i] = null;
2300 unloadListeners = null;
2302 if (listeners && listeners.length > 0) {
2303 j = listeners.length;
2306 l = listeners[index];
2308 EU.removeListener(l[EU.EL], l[EU.TYPE],
2318 EU.doRemove(window, "unload", EU._unload);
2323 getScroll: function() {
2324 var dd = document.documentElement, db = document.body;
2325 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2326 return [dd.scrollTop, dd.scrollLeft];
2328 return [db.scrollTop, db.scrollLeft];
2335 doAdd: function () {
2336 if (window.addEventListener) {
2337 return function(el, eventName, fn, capture) {
2338 el.addEventListener(eventName, fn, (capture));
2340 } else if (window.attachEvent) {
2341 return function(el, eventName, fn, capture) {
2342 el.attachEvent("on" + eventName, fn);
2351 doRemove: function() {
2352 if (window.removeEventListener) {
2353 return function (el, eventName, fn, capture) {
2354 el.removeEventListener(eventName, fn, (capture));
2356 } else if (window.detachEvent) {
2357 return function (el, eventName, fn) {
2358 el.detachEvent("on" + eventName, fn);
2370 var E = Roo.lib.Event;
2371 E.on = E.addListener;
2372 E.un = E.removeListener;
2374 if (document && document.body) {
2377 E.doAdd(window, "load", E._load);
2379 E.doAdd(window, "unload", E._unload);
2380 E._tryPreloadAttach();
2384 * Portions of this file are based on pieces of Yahoo User Interface Library
2385 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2386 * YUI licensed under the BSD License:
2387 * http://developer.yahoo.net/yui/license.txt
2388 * <script type="text/javascript">
2395 request : function(method, uri, cb, data, options) {
2397 var hs = options.headers;
2400 if(hs.hasOwnProperty(h)){
2401 this.initHeader(h, hs[h], false);
2405 if(options.xmlData){
2406 this.initHeader('Content-Type', 'text/xml', false);
2408 data = options.xmlData;
2412 return this.asyncRequest(method, uri, cb, data);
2415 serializeForm : function(form) {
2416 if(typeof form == 'string') {
2417 form = (document.getElementById(form) || document.forms[form]);
2420 var el, name, val, disabled, data = '', hasSubmit = false;
2421 for (var i = 0; i < form.elements.length; i++) {
2422 el = form.elements[i];
2423 disabled = form.elements[i].disabled;
2424 name = form.elements[i].name;
2425 val = form.elements[i].value;
2427 if (!disabled && name){
2431 case 'select-multiple':
2432 for (var j = 0; j < el.options.length; j++) {
2433 if (el.options[j].selected) {
2435 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2438 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2446 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2459 if(hasSubmit == false) {
2460 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2465 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2470 data = data.substr(0, data.length - 1);
2478 useDefaultHeader:true,
2480 defaultPostHeader:'application/x-www-form-urlencoded',
2482 useDefaultXhrHeader:true,
2484 defaultXhrHeader:'XMLHttpRequest',
2486 hasDefaultHeaders:true,
2498 setProgId:function(id)
2500 this.activeX.unshift(id);
2503 setDefaultPostHeader:function(b)
2505 this.useDefaultHeader = b;
2508 setDefaultXhrHeader:function(b)
2510 this.useDefaultXhrHeader = b;
2513 setPollingInterval:function(i)
2515 if (typeof i == 'number' && isFinite(i)) {
2516 this.pollInterval = i;
2520 createXhrObject:function(transactionId)
2526 http = new XMLHttpRequest();
2528 obj = { conn:http, tId:transactionId };
2532 for (var i = 0; i < this.activeX.length; ++i) {
2536 http = new ActiveXObject(this.activeX[i]);
2538 obj = { conn:http, tId:transactionId };
2551 getConnectionObject:function()
2554 var tId = this.transactionId;
2558 o = this.createXhrObject(tId);
2560 this.transactionId++;
2571 asyncRequest:function(method, uri, callback, postData)
2573 var o = this.getConnectionObject();
2579 o.conn.open(method, uri, true);
2581 if (this.useDefaultXhrHeader) {
2582 if (!this.defaultHeaders['X-Requested-With']) {
2583 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2587 if(postData && this.useDefaultHeader){
2588 this.initHeader('Content-Type', this.defaultPostHeader);
2591 if (this.hasDefaultHeaders || this.hasHeaders) {
2595 this.handleReadyState(o, callback);
2596 o.conn.send(postData || null);
2602 handleReadyState:function(o, callback)
2606 if (callback && callback.timeout) {
2607 this.timeout[o.tId] = window.setTimeout(function() {
2608 oConn.abort(o, callback, true);
2609 }, callback.timeout);
2612 this.poll[o.tId] = window.setInterval(
2614 if (o.conn && o.conn.readyState == 4) {
2615 window.clearInterval(oConn.poll[o.tId]);
2616 delete oConn.poll[o.tId];
2618 if(callback && callback.timeout) {
2619 window.clearTimeout(oConn.timeout[o.tId]);
2620 delete oConn.timeout[o.tId];
2623 oConn.handleTransactionResponse(o, callback);
2626 , this.pollInterval);
2629 handleTransactionResponse:function(o, callback, isAbort)
2633 this.releaseObject(o);
2637 var httpStatus, responseObject;
2641 if (o.conn.status !== undefined && o.conn.status != 0) {
2642 httpStatus = o.conn.status;
2654 if (httpStatus >= 200 && httpStatus < 300) {
2655 responseObject = this.createResponseObject(o, callback.argument);
2656 if (callback.success) {
2657 if (!callback.scope) {
2658 callback.success(responseObject);
2663 callback.success.apply(callback.scope, [responseObject]);
2668 switch (httpStatus) {
2676 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2677 if (callback.failure) {
2678 if (!callback.scope) {
2679 callback.failure(responseObject);
2682 callback.failure.apply(callback.scope, [responseObject]);
2687 responseObject = this.createResponseObject(o, callback.argument);
2688 if (callback.failure) {
2689 if (!callback.scope) {
2690 callback.failure(responseObject);
2693 callback.failure.apply(callback.scope, [responseObject]);
2699 this.releaseObject(o);
2700 responseObject = null;
2703 createResponseObject:function(o, callbackArg)
2710 var headerStr = o.conn.getAllResponseHeaders();
2711 var header = headerStr.split('\n');
2712 for (var i = 0; i < header.length; i++) {
2713 var delimitPos = header[i].indexOf(':');
2714 if (delimitPos != -1) {
2715 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2723 obj.status = o.conn.status;
2724 obj.statusText = o.conn.statusText;
2725 obj.getResponseHeader = headerObj;
2726 obj.getAllResponseHeaders = headerStr;
2727 obj.responseText = o.conn.responseText;
2728 obj.responseXML = o.conn.responseXML;
2730 if (typeof callbackArg !== undefined) {
2731 obj.argument = callbackArg;
2737 createExceptionObject:function(tId, callbackArg, isAbort)
2740 var COMM_ERROR = 'communication failure';
2741 var ABORT_CODE = -1;
2742 var ABORT_ERROR = 'transaction aborted';
2748 obj.status = ABORT_CODE;
2749 obj.statusText = ABORT_ERROR;
2752 obj.status = COMM_CODE;
2753 obj.statusText = COMM_ERROR;
2757 obj.argument = callbackArg;
2763 initHeader:function(label, value, isDefault)
2765 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2767 if (headerObj[label] === undefined) {
2768 headerObj[label] = value;
2773 headerObj[label] = value + "," + headerObj[label];
2777 this.hasDefaultHeaders = true;
2780 this.hasHeaders = true;
2785 setHeader:function(o)
2787 if (this.hasDefaultHeaders) {
2788 for (var prop in this.defaultHeaders) {
2789 if (this.defaultHeaders.hasOwnProperty(prop)) {
2790 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2795 if (this.hasHeaders) {
2796 for (var prop in this.headers) {
2797 if (this.headers.hasOwnProperty(prop)) {
2798 o.conn.setRequestHeader(prop, this.headers[prop]);
2802 this.hasHeaders = false;
2806 resetDefaultHeaders:function() {
2807 delete this.defaultHeaders;
2808 this.defaultHeaders = {};
2809 this.hasDefaultHeaders = false;
2812 abort:function(o, callback, isTimeout)
2814 if(this.isCallInProgress(o)) {
2816 window.clearInterval(this.poll[o.tId]);
2817 delete this.poll[o.tId];
2819 delete this.timeout[o.tId];
2822 this.handleTransactionResponse(o, callback, true);
2832 isCallInProgress:function(o)
2835 return o.conn.readyState != 4 && o.conn.readyState != 0;
2844 releaseObject:function(o)
2853 'MSXML2.XMLHTTP.3.0',
2861 * Portions of this file are based on pieces of Yahoo User Interface Library
2862 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2863 * YUI licensed under the BSD License:
2864 * http://developer.yahoo.net/yui/license.txt
2865 * <script type="text/javascript">
2869 Roo.lib.Region = function(t, r, b, l) {
2879 Roo.lib.Region.prototype = {
2880 contains : function(region) {
2881 return ( region.left >= this.left &&
2882 region.right <= this.right &&
2883 region.top >= this.top &&
2884 region.bottom <= this.bottom );
2888 getArea : function() {
2889 return ( (this.bottom - this.top) * (this.right - this.left) );
2892 intersect : function(region) {
2893 var t = Math.max(this.top, region.top);
2894 var r = Math.min(this.right, region.right);
2895 var b = Math.min(this.bottom, region.bottom);
2896 var l = Math.max(this.left, region.left);
2898 if (b >= t && r >= l) {
2899 return new Roo.lib.Region(t, r, b, l);
2904 union : function(region) {
2905 var t = Math.min(this.top, region.top);
2906 var r = Math.max(this.right, region.right);
2907 var b = Math.max(this.bottom, region.bottom);
2908 var l = Math.min(this.left, region.left);
2910 return new Roo.lib.Region(t, r, b, l);
2913 adjust : function(t, l, b, r) {
2922 Roo.lib.Region.getRegion = function(el) {
2923 var p = Roo.lib.Dom.getXY(el);
2926 var r = p[0] + el.offsetWidth;
2927 var b = p[1] + el.offsetHeight;
2930 return new Roo.lib.Region(t, r, b, l);
2933 * Portions of this file are based on pieces of Yahoo User Interface Library
2934 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2935 * YUI licensed under the BSD License:
2936 * http://developer.yahoo.net/yui/license.txt
2937 * <script type="text/javascript">
2940 //@@dep Roo.lib.Region
2943 Roo.lib.Point = function(x, y) {
2944 if (x instanceof Array) {
2948 this.x = this.right = this.left = this[0] = x;
2949 this.y = this.top = this.bottom = this[1] = y;
2952 Roo.lib.Point.prototype = new Roo.lib.Region();
2954 * Portions of this file are based on pieces of Yahoo User Interface Library
2955 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2956 * YUI licensed under the BSD License:
2957 * http://developer.yahoo.net/yui/license.txt
2958 * <script type="text/javascript">
2965 scroll : function(el, args, duration, easing, cb, scope) {
2966 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2969 motion : function(el, args, duration, easing, cb, scope) {
2970 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2973 color : function(el, args, duration, easing, cb, scope) {
2974 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2977 run : function(el, args, duration, easing, cb, scope, type) {
2978 type = type || Roo.lib.AnimBase;
2979 if (typeof easing == "string") {
2980 easing = Roo.lib.Easing[easing];
2982 var anim = new type(el, args, duration, easing);
2983 anim.animateX(function() {
2984 Roo.callback(cb, scope);
2990 * Portions of this file are based on pieces of Yahoo User Interface Library
2991 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2992 * YUI licensed under the BSD License:
2993 * http://developer.yahoo.net/yui/license.txt
2994 * <script type="text/javascript">
3002 if (!libFlyweight) {
3003 libFlyweight = new Roo.Element.Flyweight();
3005 libFlyweight.dom = el;
3006 return libFlyweight;
3009 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
3013 Roo.lib.AnimBase = function(el, attributes, duration, method) {
3015 this.init(el, attributes, duration, method);
3019 Roo.lib.AnimBase.fly = fly;
3023 Roo.lib.AnimBase.prototype = {
3025 toString: function() {
3026 var el = this.getEl();
3027 var id = el.id || el.tagName;
3028 return ("Anim " + id);
3032 noNegatives: /width|height|opacity|padding/i,
3033 offsetAttribute: /^((width|height)|(top|left))$/,
3034 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3035 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3039 doMethod: function(attr, start, end) {
3040 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3044 setAttribute: function(attr, val, unit) {
3045 if (this.patterns.noNegatives.test(attr)) {
3046 val = (val > 0) ? val : 0;
3049 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3053 getAttribute: function(attr) {
3054 var el = this.getEl();
3055 var val = fly(el).getStyle(attr);
3057 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3058 return parseFloat(val);
3061 var a = this.patterns.offsetAttribute.exec(attr) || [];
3062 var pos = !!( a[3] );
3063 var box = !!( a[2] );
3066 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3067 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3076 getDefaultUnit: function(attr) {
3077 if (this.patterns.defaultUnit.test(attr)) {
3084 animateX : function(callback, scope) {
3085 var f = function() {
3086 this.onComplete.removeListener(f);
3087 if (typeof callback == "function") {
3088 callback.call(scope || this, this);
3091 this.onComplete.addListener(f, this);
3096 setRuntimeAttribute: function(attr) {
3099 var attributes = this.attributes;
3101 this.runtimeAttributes[attr] = {};
3103 var isset = function(prop) {
3104 return (typeof prop !== 'undefined');
3107 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3111 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3114 if (isset(attributes[attr]['to'])) {
3115 end = attributes[attr]['to'];
3116 } else if (isset(attributes[attr]['by'])) {
3117 if (start.constructor == Array) {
3119 for (var i = 0, len = start.length; i < len; ++i) {
3120 end[i] = start[i] + attributes[attr]['by'][i];
3123 end = start + attributes[attr]['by'];
3127 this.runtimeAttributes[attr].start = start;
3128 this.runtimeAttributes[attr].end = end;
3131 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3135 init: function(el, attributes, duration, method) {
3137 var isAnimated = false;
3140 var startTime = null;
3143 var actualFrames = 0;
3146 el = Roo.getDom(el);
3149 this.attributes = attributes || {};
3152 this.duration = duration || 1;
3155 this.method = method || Roo.lib.Easing.easeNone;
3158 this.useSeconds = true;
3161 this.currentFrame = 0;
3164 this.totalFrames = Roo.lib.AnimMgr.fps;
3167 this.getEl = function() {
3172 this.isAnimated = function() {
3177 this.getStartTime = function() {
3181 this.runtimeAttributes = {};
3184 this.animate = function() {
3185 if (this.isAnimated()) {
3189 this.currentFrame = 0;
3191 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3193 Roo.lib.AnimMgr.registerElement(this);
3197 this.stop = function(finish) {
3199 this.currentFrame = this.totalFrames;
3200 this._onTween.fire();
3202 Roo.lib.AnimMgr.stop(this);
3205 var onStart = function() {
3206 this.onStart.fire();
3208 this.runtimeAttributes = {};
3209 for (var attr in this.attributes) {
3210 this.setRuntimeAttribute(attr);
3215 startTime = new Date();
3219 var onTween = function() {
3221 duration: new Date() - this.getStartTime(),
3222 currentFrame: this.currentFrame
3225 data.toString = function() {
3227 'duration: ' + data.duration +
3228 ', currentFrame: ' + data.currentFrame
3232 this.onTween.fire(data);
3234 var runtimeAttributes = this.runtimeAttributes;
3236 for (var attr in runtimeAttributes) {
3237 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3243 var onComplete = function() {
3244 var actual_duration = (new Date() - startTime) / 1000 ;
3247 duration: actual_duration,
3248 frames: actualFrames,
3249 fps: actualFrames / actual_duration
3252 data.toString = function() {
3254 'duration: ' + data.duration +
3255 ', frames: ' + data.frames +
3256 ', fps: ' + data.fps
3262 this.onComplete.fire(data);
3266 this._onStart = new Roo.util.Event(this);
3267 this.onStart = new Roo.util.Event(this);
3268 this.onTween = new Roo.util.Event(this);
3269 this._onTween = new Roo.util.Event(this);
3270 this.onComplete = new Roo.util.Event(this);
3271 this._onComplete = new Roo.util.Event(this);
3272 this._onStart.addListener(onStart);
3273 this._onTween.addListener(onTween);
3274 this._onComplete.addListener(onComplete);
3279 * Portions of this file are based on pieces of Yahoo User Interface Library
3280 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3281 * YUI licensed under the BSD License:
3282 * http://developer.yahoo.net/yui/license.txt
3283 * <script type="text/javascript">
3287 Roo.lib.AnimMgr = new function() {
3304 this.registerElement = function(tween) {
3305 queue[queue.length] = tween;
3307 tween._onStart.fire();
3312 this.unRegister = function(tween, index) {
3313 tween._onComplete.fire();
3314 index = index || getIndex(tween);
3316 queue.splice(index, 1);
3320 if (tweenCount <= 0) {
3326 this.start = function() {
3327 if (thread === null) {
3328 thread = setInterval(this.run, this.delay);
3333 this.stop = function(tween) {
3335 clearInterval(thread);
3337 for (var i = 0, len = queue.length; i < len; ++i) {
3338 if (queue[0].isAnimated()) {
3339 this.unRegister(queue[0], 0);
3348 this.unRegister(tween);
3353 this.run = function() {
3354 for (var i = 0, len = queue.length; i < len; ++i) {
3355 var tween = queue[i];
3356 if (!tween || !tween.isAnimated()) {
3360 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3362 tween.currentFrame += 1;
3364 if (tween.useSeconds) {
3365 correctFrame(tween);
3367 tween._onTween.fire();
3370 Roo.lib.AnimMgr.stop(tween, i);
3375 var getIndex = function(anim) {
3376 for (var i = 0, len = queue.length; i < len; ++i) {
3377 if (queue[i] == anim) {
3385 var correctFrame = function(tween) {
3386 var frames = tween.totalFrames;
3387 var frame = tween.currentFrame;
3388 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3389 var elapsed = (new Date() - tween.getStartTime());
3392 if (elapsed < tween.duration * 1000) {
3393 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3395 tweak = frames - (frame + 1);
3397 if (tweak > 0 && isFinite(tweak)) {
3398 if (tween.currentFrame + tweak >= frames) {
3399 tweak = frames - (frame + 1);
3402 tween.currentFrame += tweak;
3406 * Portions of this file are based on pieces of Yahoo User Interface Library
3407 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3408 * YUI licensed under the BSD License:
3409 * http://developer.yahoo.net/yui/license.txt
3410 * <script type="text/javascript">
3413 Roo.lib.Bezier = new function() {
3415 this.getPosition = function(points, t) {
3416 var n = points.length;
3419 for (var i = 0; i < n; ++i) {
3420 tmp[i] = [points[i][0], points[i][1]];
3423 for (var j = 1; j < n; ++j) {
3424 for (i = 0; i < n - j; ++i) {
3425 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3426 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3430 return [ tmp[0][0], tmp[0][1] ];
3434 * Portions of this file are based on pieces of Yahoo User Interface Library
3435 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3436 * YUI licensed under the BSD License:
3437 * http://developer.yahoo.net/yui/license.txt
3438 * <script type="text/javascript">
3443 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3444 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3447 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3449 var fly = Roo.lib.AnimBase.fly;
3451 var superclass = Y.ColorAnim.superclass;
3452 var proto = Y.ColorAnim.prototype;
3454 proto.toString = function() {
3455 var el = this.getEl();
3456 var id = el.id || el.tagName;
3457 return ("ColorAnim " + id);
3460 proto.patterns.color = /color$/i;
3461 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3462 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3463 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3464 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3467 proto.parseColor = function(s) {
3468 if (s.length == 3) {
3472 var c = this.patterns.hex.exec(s);
3473 if (c && c.length == 4) {
3474 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3477 c = this.patterns.rgb.exec(s);
3478 if (c && c.length == 4) {
3479 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3482 c = this.patterns.hex3.exec(s);
3483 if (c && c.length == 4) {
3484 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3489 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3490 proto.getAttribute = function(attr) {
3491 var el = this.getEl();
3492 if (this.patterns.color.test(attr)) {
3493 var val = fly(el).getStyle(attr);
3495 if (this.patterns.transparent.test(val)) {
3496 var parent = el.parentNode;
3497 val = fly(parent).getStyle(attr);
3499 while (parent && this.patterns.transparent.test(val)) {
3500 parent = parent.parentNode;
3501 val = fly(parent).getStyle(attr);
3502 if (parent.tagName.toUpperCase() == 'HTML') {
3508 val = superclass.getAttribute.call(this, attr);
3513 proto.getAttribute = function(attr) {
3514 var el = this.getEl();
3515 if (this.patterns.color.test(attr)) {
3516 var val = fly(el).getStyle(attr);
3518 if (this.patterns.transparent.test(val)) {
3519 var parent = el.parentNode;
3520 val = fly(parent).getStyle(attr);
3522 while (parent && this.patterns.transparent.test(val)) {
3523 parent = parent.parentNode;
3524 val = fly(parent).getStyle(attr);
3525 if (parent.tagName.toUpperCase() == 'HTML') {
3531 val = superclass.getAttribute.call(this, attr);
3537 proto.doMethod = function(attr, start, end) {
3540 if (this.patterns.color.test(attr)) {
3542 for (var i = 0, len = start.length; i < len; ++i) {
3543 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3546 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3549 val = superclass.doMethod.call(this, attr, start, end);
3555 proto.setRuntimeAttribute = function(attr) {
3556 superclass.setRuntimeAttribute.call(this, attr);
3558 if (this.patterns.color.test(attr)) {
3559 var attributes = this.attributes;
3560 var start = this.parseColor(this.runtimeAttributes[attr].start);
3561 var end = this.parseColor(this.runtimeAttributes[attr].end);
3563 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3564 end = this.parseColor(attributes[attr].by);
3566 for (var i = 0, len = start.length; i < len; ++i) {
3567 end[i] = start[i] + end[i];
3571 this.runtimeAttributes[attr].start = start;
3572 this.runtimeAttributes[attr].end = end;
3578 * Portions of this file are based on pieces of Yahoo User Interface Library
3579 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3580 * YUI licensed under the BSD License:
3581 * http://developer.yahoo.net/yui/license.txt
3582 * <script type="text/javascript">
3588 easeNone: function (t, b, c, d) {
3589 return c * t / d + b;
3593 easeIn: function (t, b, c, d) {
3594 return c * (t /= d) * t + b;
3598 easeOut: function (t, b, c, d) {
3599 return -c * (t /= d) * (t - 2) + b;
3603 easeBoth: function (t, b, c, d) {
3604 if ((t /= d / 2) < 1) {
3605 return c / 2 * t * t + b;
3608 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3612 easeInStrong: function (t, b, c, d) {
3613 return c * (t /= d) * t * t * t + b;
3617 easeOutStrong: function (t, b, c, d) {
3618 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3622 easeBothStrong: function (t, b, c, d) {
3623 if ((t /= d / 2) < 1) {
3624 return c / 2 * t * t * t * t + b;
3627 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3632 elasticIn: function (t, b, c, d, a, p) {
3636 if ((t /= d) == 1) {
3643 if (!a || a < Math.abs(c)) {
3648 var s = p / (2 * Math.PI) * Math.asin(c / a);
3651 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3655 elasticOut: function (t, b, c, d, a, p) {
3659 if ((t /= d) == 1) {
3666 if (!a || a < Math.abs(c)) {
3671 var s = p / (2 * Math.PI) * Math.asin(c / a);
3674 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3678 elasticBoth: function (t, b, c, d, a, p) {
3683 if ((t /= d / 2) == 2) {
3691 if (!a || a < Math.abs(c)) {
3696 var s = p / (2 * Math.PI) * Math.asin(c / a);
3700 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3701 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3703 return a * Math.pow(2, -10 * (t -= 1)) *
3704 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3709 backIn: function (t, b, c, d, s) {
3710 if (typeof s == 'undefined') {
3713 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3717 backOut: function (t, b, c, d, s) {
3718 if (typeof s == 'undefined') {
3721 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3725 backBoth: function (t, b, c, d, s) {
3726 if (typeof s == 'undefined') {
3730 if ((t /= d / 2 ) < 1) {
3731 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3733 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3737 bounceIn: function (t, b, c, d) {
3738 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3742 bounceOut: function (t, b, c, d) {
3743 if ((t /= d) < (1 / 2.75)) {
3744 return c * (7.5625 * t * t) + b;
3745 } else if (t < (2 / 2.75)) {
3746 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3747 } else if (t < (2.5 / 2.75)) {
3748 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3750 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3754 bounceBoth: function (t, b, c, d) {
3756 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3758 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3761 * Portions of this file are based on pieces of Yahoo User Interface Library
3762 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3763 * YUI licensed under the BSD License:
3764 * http://developer.yahoo.net/yui/license.txt
3765 * <script type="text/javascript">
3769 Roo.lib.Motion = function(el, attributes, duration, method) {
3771 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3775 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3779 var superclass = Y.Motion.superclass;
3780 var proto = Y.Motion.prototype;
3782 proto.toString = function() {
3783 var el = this.getEl();
3784 var id = el.id || el.tagName;
3785 return ("Motion " + id);
3788 proto.patterns.points = /^points$/i;
3790 proto.setAttribute = function(attr, val, unit) {
3791 if (this.patterns.points.test(attr)) {
3792 unit = unit || 'px';
3793 superclass.setAttribute.call(this, 'left', val[0], unit);
3794 superclass.setAttribute.call(this, 'top', val[1], unit);
3796 superclass.setAttribute.call(this, attr, val, unit);
3800 proto.getAttribute = function(attr) {
3801 if (this.patterns.points.test(attr)) {
3803 superclass.getAttribute.call(this, 'left'),
3804 superclass.getAttribute.call(this, 'top')
3807 val = superclass.getAttribute.call(this, attr);
3813 proto.doMethod = function(attr, start, end) {
3816 if (this.patterns.points.test(attr)) {
3817 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3818 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3820 val = superclass.doMethod.call(this, attr, start, end);
3825 proto.setRuntimeAttribute = function(attr) {
3826 if (this.patterns.points.test(attr)) {
3827 var el = this.getEl();
3828 var attributes = this.attributes;
3830 var control = attributes['points']['control'] || [];
3834 if (control.length > 0 && !(control[0] instanceof Array)) {
3835 control = [control];
3838 for (i = 0,len = control.length; i < len; ++i) {
3839 tmp[i] = control[i];
3844 Roo.fly(el).position();
3846 if (isset(attributes['points']['from'])) {
3847 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3850 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3853 start = this.getAttribute('points');
3856 if (isset(attributes['points']['to'])) {
3857 end = translateValues.call(this, attributes['points']['to'], start);
3859 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3860 for (i = 0,len = control.length; i < len; ++i) {
3861 control[i] = translateValues.call(this, control[i], start);
3865 } else if (isset(attributes['points']['by'])) {
3866 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3868 for (i = 0,len = control.length; i < len; ++i) {
3869 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3873 this.runtimeAttributes[attr] = [start];
3875 if (control.length > 0) {
3876 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3879 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3882 superclass.setRuntimeAttribute.call(this, attr);
3886 var translateValues = function(val, start) {
3887 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3888 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3893 var isset = function(prop) {
3894 return (typeof prop !== 'undefined');
3898 * Portions of this file are based on pieces of Yahoo User Interface Library
3899 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3900 * YUI licensed under the BSD License:
3901 * http://developer.yahoo.net/yui/license.txt
3902 * <script type="text/javascript">
3906 Roo.lib.Scroll = function(el, attributes, duration, method) {
3908 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3912 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3916 var superclass = Y.Scroll.superclass;
3917 var proto = Y.Scroll.prototype;
3919 proto.toString = function() {
3920 var el = this.getEl();
3921 var id = el.id || el.tagName;
3922 return ("Scroll " + id);
3925 proto.doMethod = function(attr, start, end) {
3928 if (attr == 'scroll') {
3930 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3931 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3935 val = superclass.doMethod.call(this, attr, start, end);
3940 proto.getAttribute = function(attr) {
3942 var el = this.getEl();
3944 if (attr == 'scroll') {
3945 val = [ el.scrollLeft, el.scrollTop ];
3947 val = superclass.getAttribute.call(this, attr);
3953 proto.setAttribute = function(attr, val, unit) {
3954 var el = this.getEl();
3956 if (attr == 'scroll') {
3957 el.scrollLeft = val[0];
3958 el.scrollTop = val[1];
3960 superclass.setAttribute.call(this, attr, val, unit);
3966 * Ext JS Library 1.1.1
3967 * Copyright(c) 2006-2007, Ext JS, LLC.
3969 * Originally Released Under LGPL - original licence link has changed is not relivant.
3972 * <script type="text/javascript">
3977 * @class Roo.DomHelper
3978 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3979 * 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>.
3982 Roo.DomHelper = function(){
3983 var tempTableEl = null;
3984 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3985 var tableRe = /^table|tbody|tr|td$/i;
3987 // build as innerHTML where available
3989 var createHtml = function(o){
3990 if(typeof o == 'string'){
3999 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
4000 if(attr == "style"){
4002 if(typeof s == "function"){
4005 if(typeof s == "string"){
4006 b += ' style="' + s + '"';
4007 }else if(typeof s == "object"){
4010 if(typeof s[key] != "function"){
4011 b += key + ":" + s[key] + ";";
4018 b += ' class="' + o["cls"] + '"';
4019 }else if(attr == "htmlFor"){
4020 b += ' for="' + o["htmlFor"] + '"';
4022 b += " " + attr + '="' + o[attr] + '"';
4026 if(emptyTags.test(o.tag)){
4030 var cn = o.children || o.cn;
4032 //http://bugs.kde.org/show_bug.cgi?id=71506
4033 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4034 for(var i = 0, len = cn.length; i < len; i++) {
4035 b += createHtml(cn[i], b);
4038 b += createHtml(cn, b);
4044 b += "</" + o.tag + ">";
4051 var createDom = function(o, parentNode){
4053 // defininition craeted..
4055 if (o.ns && o.ns != 'html') {
4057 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4058 xmlns[o.ns] = o.xmlns;
4061 if (typeof(xmlns[o.ns]) == 'undefined') {
4062 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4068 if (typeof(o) == 'string') {
4069 return parentNode.appendChild(document.createTextNode(o));
4071 o.tag = o.tag || div;
4072 if (o.ns && Roo.isIE) {
4074 o.tag = o.ns + ':' + o.tag;
4077 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4078 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4081 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4082 attr == "style" || typeof o[attr] == "function") continue;
4084 if(attr=="cls" && Roo.isIE){
4085 el.className = o["cls"];
4087 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4088 else el[attr] = o[attr];
4091 Roo.DomHelper.applyStyles(el, o.style);
4092 var cn = o.children || o.cn;
4094 //http://bugs.kde.org/show_bug.cgi?id=71506
4095 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4096 for(var i = 0, len = cn.length; i < len; i++) {
4097 createDom(cn[i], el);
4104 el.innerHTML = o.html;
4107 parentNode.appendChild(el);
4112 var ieTable = function(depth, s, h, e){
4113 tempTableEl.innerHTML = [s, h, e].join('');
4114 var i = -1, el = tempTableEl;
4121 // kill repeat to save bytes
4125 tbe = '</tbody>'+te,
4131 * Nasty code for IE's broken table implementation
4133 var insertIntoTable = function(tag, where, el, html){
4135 tempTableEl = document.createElement('div');
4140 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4143 if(where == 'beforebegin'){
4147 before = el.nextSibling;
4150 node = ieTable(4, trs, html, tre);
4152 else if(tag == 'tr'){
4153 if(where == 'beforebegin'){
4156 node = ieTable(3, tbs, html, tbe);
4157 } else if(where == 'afterend'){
4158 before = el.nextSibling;
4160 node = ieTable(3, tbs, html, tbe);
4161 } else{ // INTO a TR
4162 if(where == 'afterbegin'){
4163 before = el.firstChild;
4165 node = ieTable(4, trs, html, tre);
4167 } else if(tag == 'tbody'){
4168 if(where == 'beforebegin'){
4171 node = ieTable(2, ts, html, te);
4172 } else if(where == 'afterend'){
4173 before = el.nextSibling;
4175 node = ieTable(2, ts, html, te);
4177 if(where == 'afterbegin'){
4178 before = el.firstChild;
4180 node = ieTable(3, tbs, html, tbe);
4183 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4186 if(where == 'afterbegin'){
4187 before = el.firstChild;
4189 node = ieTable(2, ts, html, te);
4191 el.insertBefore(node, before);
4196 /** True to force the use of DOM instead of html fragments @type Boolean */
4200 * Returns the markup for the passed Element(s) config
4201 * @param {Object} o The Dom object spec (and children)
4204 markup : function(o){
4205 return createHtml(o);
4209 * Applies a style specification to an element
4210 * @param {String/HTMLElement} el The element to apply styles to
4211 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4212 * a function which returns such a specification.
4214 applyStyles : function(el, styles){
4217 if(typeof styles == "string"){
4218 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4220 while ((matches = re.exec(styles)) != null){
4221 el.setStyle(matches[1], matches[2]);
4223 }else if (typeof styles == "object"){
4224 for (var style in styles){
4225 el.setStyle(style, styles[style]);
4227 }else if (typeof styles == "function"){
4228 Roo.DomHelper.applyStyles(el, styles.call());
4234 * Inserts an HTML fragment into the Dom
4235 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4236 * @param {HTMLElement} el The context element
4237 * @param {String} html The HTML fragmenet
4238 * @return {HTMLElement} The new node
4240 insertHtml : function(where, el, html){
4241 where = where.toLowerCase();
4242 if(el.insertAdjacentHTML){
4243 if(tableRe.test(el.tagName)){
4245 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4251 el.insertAdjacentHTML('BeforeBegin', html);
4252 return el.previousSibling;
4254 el.insertAdjacentHTML('AfterBegin', html);
4255 return el.firstChild;
4257 el.insertAdjacentHTML('BeforeEnd', html);
4258 return el.lastChild;
4260 el.insertAdjacentHTML('AfterEnd', html);
4261 return el.nextSibling;
4263 throw 'Illegal insertion point -> "' + where + '"';
4265 var range = el.ownerDocument.createRange();
4269 range.setStartBefore(el);
4270 frag = range.createContextualFragment(html);
4271 el.parentNode.insertBefore(frag, el);
4272 return el.previousSibling;
4275 range.setStartBefore(el.firstChild);
4276 frag = range.createContextualFragment(html);
4277 el.insertBefore(frag, el.firstChild);
4278 return el.firstChild;
4280 el.innerHTML = html;
4281 return el.firstChild;
4285 range.setStartAfter(el.lastChild);
4286 frag = range.createContextualFragment(html);
4287 el.appendChild(frag);
4288 return el.lastChild;
4290 el.innerHTML = html;
4291 return el.lastChild;
4294 range.setStartAfter(el);
4295 frag = range.createContextualFragment(html);
4296 el.parentNode.insertBefore(frag, el.nextSibling);
4297 return el.nextSibling;
4299 throw 'Illegal insertion point -> "' + where + '"';
4303 * Creates new Dom element(s) and inserts them before el
4304 * @param {String/HTMLElement/Element} el The context element
4305 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4306 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4307 * @return {HTMLElement/Roo.Element} The new node
4309 insertBefore : function(el, o, returnElement){
4310 return this.doInsert(el, o, returnElement, "beforeBegin");
4314 * Creates new Dom element(s) and inserts them after el
4315 * @param {String/HTMLElement/Element} el The context element
4316 * @param {Object} o The Dom object spec (and children)
4317 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4318 * @return {HTMLElement/Roo.Element} The new node
4320 insertAfter : function(el, o, returnElement){
4321 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4325 * Creates new Dom element(s) and inserts them as the first child of el
4326 * @param {String/HTMLElement/Element} el The context element
4327 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4328 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4329 * @return {HTMLElement/Roo.Element} The new node
4331 insertFirst : function(el, o, returnElement){
4332 return this.doInsert(el, o, returnElement, "afterBegin");
4336 doInsert : function(el, o, returnElement, pos, sibling){
4337 el = Roo.getDom(el);
4339 if(this.useDom || o.ns){
4340 newNode = createDom(o, null);
4341 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4343 var html = createHtml(o);
4344 newNode = this.insertHtml(pos, el, html);
4346 return returnElement ? Roo.get(newNode, true) : newNode;
4350 * Creates new Dom element(s) and appends them to el
4351 * @param {String/HTMLElement/Element} el The context element
4352 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4353 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4354 * @return {HTMLElement/Roo.Element} The new node
4356 append : function(el, o, returnElement){
4357 el = Roo.getDom(el);
4359 if(this.useDom || o.ns){
4360 newNode = createDom(o, null);
4361 el.appendChild(newNode);
4363 var html = createHtml(o);
4364 newNode = this.insertHtml("beforeEnd", el, html);
4366 return returnElement ? Roo.get(newNode, true) : newNode;
4370 * Creates new Dom element(s) and overwrites the contents of el with them
4371 * @param {String/HTMLElement/Element} el The context element
4372 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4373 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4374 * @return {HTMLElement/Roo.Element} The new node
4376 overwrite : function(el, o, returnElement){
4377 el = Roo.getDom(el);
4380 while (el.childNodes.length) {
4381 el.removeChild(el.firstChild);
4385 el.innerHTML = createHtml(o);
4388 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4392 * Creates a new Roo.DomHelper.Template from the Dom object spec
4393 * @param {Object} o The Dom object spec (and children)
4394 * @return {Roo.DomHelper.Template} The new template
4396 createTemplate : function(o){
4397 var html = createHtml(o);
4398 return new Roo.Template(html);
4404 * Ext JS Library 1.1.1
4405 * Copyright(c) 2006-2007, Ext JS, LLC.
4407 * Originally Released Under LGPL - original licence link has changed is not relivant.
4410 * <script type="text/javascript">
4414 * @class Roo.Template
4415 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4416 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4419 var t = new Roo.Template({
4420 html : '<div name="{id}">' +
4421 '<span class="{cls}">{name:trim} {someval:this.myformat}{value:ellipsis(10)}</span>' +
4423 myformat: function (value, allValues) {
4424 return 'XX' + value;
4427 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4429 * 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>.
4431 * @param {Object} cfg - Configuration object.
4433 Roo.Template = function(cfg){
4435 if(cfg instanceof Array){
4437 }else if(arguments.length > 1){
4438 cfg = Array.prototype.join.call(arguments, "");
4442 if (typeof(cfg) == 'object') {
4451 Roo.Template.prototype = {
4454 * @cfg {String} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4458 * Returns an HTML fragment of this template with the specified values applied.
4459 * @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'})
4460 * @return {String} The HTML fragment
4462 applyTemplate : function(values){
4466 return this.compiled(values);
4468 var useF = this.disableFormats !== true;
4469 var fm = Roo.util.Format, tpl = this;
4470 var fn = function(m, name, format, args){
4472 if(format.substr(0, 5) == "this."){
4473 return tpl.call(format.substr(5), values[name], values);
4476 // quoted values are required for strings in compiled templates,
4477 // but for non compiled we need to strip them
4478 // quoted reversed for jsmin
4479 var re = /^\s*['"](.*)["']\s*$/;
4480 args = args.split(',');
4481 for(var i = 0, len = args.length; i < len; i++){
4482 args[i] = args[i].replace(re, "$1");
4484 args = [values[name]].concat(args);
4486 args = [values[name]];
4488 return fm[format].apply(fm, args);
4491 return values[name] !== undefined ? values[name] : "";
4494 return this.html.replace(this.re, fn);
4503 * Sets the HTML used as the template and optionally compiles it.
4504 * @param {String} html
4505 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4506 * @return {Roo.Template} this
4508 set : function(html, compile){
4510 this.compiled = null;
4518 * True to disable format functions (defaults to false)
4521 disableFormats : false,
4524 * The regular expression used to match template variables
4528 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4531 * Compiles the template into an internal function, eliminating the RegEx overhead.
4532 * @return {Roo.Template} this
4534 compile : function(){
4535 var fm = Roo.util.Format;
4536 var useF = this.disableFormats !== true;
4537 var sep = Roo.isGecko ? "+" : ",";
4538 var fn = function(m, name, format, args){
4540 args = args ? ',' + args : "";
4541 if(format.substr(0, 5) != "this."){
4542 format = "fm." + format + '(';
4544 format = 'this.call("'+ format.substr(5) + '", ';
4548 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4550 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4553 // branched to use + in gecko and [].join() in others
4555 body = "this.compiled = function(values){ return '" +
4556 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4559 body = ["this.compiled = function(values){ return ['"];
4560 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4561 body.push("'].join('');};");
4562 body = body.join('');
4572 // private function used to call members
4573 call : function(fnName, value, allValues){
4574 return this[fnName](value, allValues);
4578 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4579 * @param {String/HTMLElement/Roo.Element} el The context element
4580 * @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'})
4581 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4582 * @return {HTMLElement/Roo.Element} The new node or Element
4584 insertFirst: function(el, values, returnElement){
4585 return this.doInsert('afterBegin', el, values, returnElement);
4589 * Applies the supplied values to the template and inserts the new node(s) before el.
4590 * @param {String/HTMLElement/Roo.Element} el The context element
4591 * @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'})
4592 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4593 * @return {HTMLElement/Roo.Element} The new node or Element
4595 insertBefore: function(el, values, returnElement){
4596 return this.doInsert('beforeBegin', el, values, returnElement);
4600 * Applies the supplied values to the template and inserts the new node(s) after el.
4601 * @param {String/HTMLElement/Roo.Element} el The context element
4602 * @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'})
4603 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4604 * @return {HTMLElement/Roo.Element} The new node or Element
4606 insertAfter : function(el, values, returnElement){
4607 return this.doInsert('afterEnd', el, values, returnElement);
4611 * Applies the supplied values to the template and appends the new node(s) to el.
4612 * @param {String/HTMLElement/Roo.Element} el The context element
4613 * @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'})
4614 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4615 * @return {HTMLElement/Roo.Element} The new node or Element
4617 append : function(el, values, returnElement){
4618 return this.doInsert('beforeEnd', el, values, returnElement);
4621 doInsert : function(where, el, values, returnEl){
4622 el = Roo.getDom(el);
4623 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4624 return returnEl ? Roo.get(newNode, true) : newNode;
4628 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4629 * @param {String/HTMLElement/Roo.Element} el The context element
4630 * @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'})
4631 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4632 * @return {HTMLElement/Roo.Element} The new node or Element
4634 overwrite : function(el, values, returnElement){
4635 el = Roo.getDom(el);
4636 el.innerHTML = this.applyTemplate(values);
4637 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4641 * Alias for {@link #applyTemplate}
4644 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4647 Roo.DomHelper.Template = Roo.Template;
4650 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4651 * @param {String/HTMLElement} el A DOM element or its id
4652 * @returns {Roo.Template} The created template
4655 Roo.Template.from = function(el){
4656 el = Roo.getDom(el);
4657 return new Roo.Template(el.value || el.innerHTML);
4660 * Ext JS Library 1.1.1
4661 * Copyright(c) 2006-2007, Ext JS, LLC.
4663 * Originally Released Under LGPL - original licence link has changed is not relivant.
4666 * <script type="text/javascript">
4671 * This is code is also distributed under MIT license for use
4672 * with jQuery and prototype JavaScript libraries.
4675 * @class Roo.DomQuery
4676 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).
4678 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>
4681 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.
4683 <h4>Element Selectors:</h4>
4685 <li> <b>*</b> any element</li>
4686 <li> <b>E</b> an element with the tag E</li>
4687 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4688 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4689 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4690 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4692 <h4>Attribute Selectors:</h4>
4693 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4695 <li> <b>E[foo]</b> has an attribute "foo"</li>
4696 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4697 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4698 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4699 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4700 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4701 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4703 <h4>Pseudo Classes:</h4>
4705 <li> <b>E:first-child</b> E is the first child of its parent</li>
4706 <li> <b>E:last-child</b> E is the last child of its parent</li>
4707 <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>
4708 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4709 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4710 <li> <b>E:only-child</b> E is the only child of its parent</li>
4711 <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>
4712 <li> <b>E:first</b> the first E in the resultset</li>
4713 <li> <b>E:last</b> the last E in the resultset</li>
4714 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4715 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4716 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4717 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4718 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4719 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4720 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4721 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4722 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4724 <h4>CSS Value Selectors:</h4>
4726 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4727 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4728 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4729 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4730 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4731 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4735 Roo.DomQuery = function(){
4736 var cache = {}, simpleCache = {}, valueCache = {};
4737 var nonSpace = /\S/;
4738 var trimRe = /^\s+|\s+$/g;
4739 var tplRe = /\{(\d+)\}/g;
4740 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4741 var tagTokenRe = /^(#)?([\w-\*]+)/;
4742 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4744 function child(p, index){
4746 var n = p.firstChild;
4748 if(n.nodeType == 1){
4759 while((n = n.nextSibling) && n.nodeType != 1);
4764 while((n = n.previousSibling) && n.nodeType != 1);
4768 function children(d){
4769 var n = d.firstChild, ni = -1;
4771 var nx = n.nextSibling;
4772 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4782 function byClassName(c, a, v){
4786 var r = [], ri = -1, cn;
4787 for(var i = 0, ci; ci = c[i]; i++){
4788 if((' '+ci.className+' ').indexOf(v) != -1){
4795 function attrValue(n, attr){
4796 if(!n.tagName && typeof n.length != "undefined"){
4805 if(attr == "class" || attr == "className"){
4808 return n.getAttribute(attr) || n[attr];
4812 function getNodes(ns, mode, tagName){
4813 var result = [], ri = -1, cs;
4817 tagName = tagName || "*";
4818 if(typeof ns.getElementsByTagName != "undefined"){
4822 for(var i = 0, ni; ni = ns[i]; i++){
4823 cs = ni.getElementsByTagName(tagName);
4824 for(var j = 0, ci; ci = cs[j]; j++){
4828 }else if(mode == "/" || mode == ">"){
4829 var utag = tagName.toUpperCase();
4830 for(var i = 0, ni, cn; ni = ns[i]; i++){
4831 cn = ni.children || ni.childNodes;
4832 for(var j = 0, cj; cj = cn[j]; j++){
4833 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4838 }else if(mode == "+"){
4839 var utag = tagName.toUpperCase();
4840 for(var i = 0, n; n = ns[i]; i++){
4841 while((n = n.nextSibling) && n.nodeType != 1);
4842 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4846 }else if(mode == "~"){
4847 for(var i = 0, n; n = ns[i]; i++){
4848 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4857 function concat(a, b){
4861 for(var i = 0, l = b.length; i < l; i++){
4867 function byTag(cs, tagName){
4868 if(cs.tagName || cs == document){
4874 var r = [], ri = -1;
4875 tagName = tagName.toLowerCase();
4876 for(var i = 0, ci; ci = cs[i]; i++){
4877 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4884 function byId(cs, attr, id){
4885 if(cs.tagName || cs == document){
4891 var r = [], ri = -1;
4892 for(var i = 0,ci; ci = cs[i]; i++){
4893 if(ci && ci.id == id){
4901 function byAttribute(cs, attr, value, op, custom){
4902 var r = [], ri = -1, st = custom=="{";
4903 var f = Roo.DomQuery.operators[op];
4904 for(var i = 0, ci; ci = cs[i]; i++){
4907 a = Roo.DomQuery.getStyle(ci, attr);
4909 else if(attr == "class" || attr == "className"){
4911 }else if(attr == "for"){
4913 }else if(attr == "href"){
4914 a = ci.getAttribute("href", 2);
4916 a = ci.getAttribute(attr);
4918 if((f && f(a, value)) || (!f && a)){
4925 function byPseudo(cs, name, value){
4926 return Roo.DomQuery.pseudos[name](cs, value);
4929 // This is for IE MSXML which does not support expandos.
4930 // IE runs the same speed using setAttribute, however FF slows way down
4931 // and Safari completely fails so they need to continue to use expandos.
4932 var isIE = window.ActiveXObject ? true : false;
4934 // this eval is stop the compressor from
4935 // renaming the variable to something shorter
4937 /** eval:var:batch */
4942 function nodupIEXml(cs){
4944 cs[0].setAttribute("_nodup", d);
4946 for(var i = 1, len = cs.length; i < len; i++){
4948 if(!c.getAttribute("_nodup") != d){
4949 c.setAttribute("_nodup", d);
4953 for(var i = 0, len = cs.length; i < len; i++){
4954 cs[i].removeAttribute("_nodup");
4963 var len = cs.length, c, i, r = cs, cj, ri = -1;
4964 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4967 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4968 return nodupIEXml(cs);
4972 for(i = 1; c = cs[i]; i++){
4977 for(var j = 0; j < i; j++){
4980 for(j = i+1; cj = cs[j]; j++){
4992 function quickDiffIEXml(c1, c2){
4994 for(var i = 0, len = c1.length; i < len; i++){
4995 c1[i].setAttribute("_qdiff", d);
4998 for(var i = 0, len = c2.length; i < len; i++){
4999 if(c2[i].getAttribute("_qdiff") != d){
5000 r[r.length] = c2[i];
5003 for(var i = 0, len = c1.length; i < len; i++){
5004 c1[i].removeAttribute("_qdiff");
5009 function quickDiff(c1, c2){
5010 var len1 = c1.length;
5014 if(isIE && c1[0].selectSingleNode){
5015 return quickDiffIEXml(c1, c2);
5018 for(var i = 0; i < len1; i++){
5022 for(var i = 0, len = c2.length; i < len; i++){
5023 if(c2[i]._qdiff != d){
5024 r[r.length] = c2[i];
5030 function quickId(ns, mode, root, id){
5032 var d = root.ownerDocument || root;
5033 return d.getElementById(id);
5035 ns = getNodes(ns, mode, "*");
5036 return byId(ns, null, id);
5040 getStyle : function(el, name){
5041 return Roo.fly(el).getStyle(name);
5044 * Compiles a selector/xpath query into a reusable function. The returned function
5045 * takes one parameter "root" (optional), which is the context node from where the query should start.
5046 * @param {String} selector The selector/xpath query
5047 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
5048 * @return {Function}
5050 compile : function(path, type){
5051 type = type || "select";
5053 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
5054 var q = path, mode, lq;
5055 var tk = Roo.DomQuery.matchers;
5056 var tklen = tk.length;
5059 // accept leading mode switch
5060 var lmode = q.match(modeRe);
5061 if(lmode && lmode[1]){
5062 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5063 q = q.replace(lmode[1], "");
5065 // strip leading slashes
5066 while(path.substr(0, 1)=="/"){
5067 path = path.substr(1);
5070 while(q && lq != q){
5072 var tm = q.match(tagTokenRe);
5073 if(type == "select"){
5076 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5078 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5080 q = q.replace(tm[0], "");
5081 }else if(q.substr(0, 1) != '@'){
5082 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5087 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5089 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5091 q = q.replace(tm[0], "");
5094 while(!(mm = q.match(modeRe))){
5095 var matched = false;
5096 for(var j = 0; j < tklen; j++){
5098 var m = q.match(t.re);
5100 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5103 q = q.replace(m[0], "");
5108 // prevent infinite loop on bad selector
5110 throw 'Error parsing selector, parsing failed at "' + q + '"';
5114 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5115 q = q.replace(mm[1], "");
5118 fn[fn.length] = "return nodup(n);\n}";
5121 * list of variables that need from compression as they are used by eval.
5131 * eval:var:byClassName
5133 * eval:var:byAttribute
5134 * eval:var:attrValue
5142 * Selects a group of elements.
5143 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5144 * @param {Node} root (optional) The start of the query (defaults to document).
5147 select : function(path, root, type){
5148 if(!root || root == document){
5151 if(typeof root == "string"){
5152 root = document.getElementById(root);
5154 var paths = path.split(",");
5156 for(var i = 0, len = paths.length; i < len; i++){
5157 var p = paths[i].replace(trimRe, "");
5159 cache[p] = Roo.DomQuery.compile(p);
5161 throw p + " is not a valid selector";
5164 var result = cache[p](root);
5165 if(result && result != document){
5166 results = results.concat(result);
5169 if(paths.length > 1){
5170 return nodup(results);
5176 * Selects a single element.
5177 * @param {String} selector The selector/xpath query
5178 * @param {Node} root (optional) The start of the query (defaults to document).
5181 selectNode : function(path, root){
5182 return Roo.DomQuery.select(path, root)[0];
5186 * Selects the value of a node, optionally replacing null with the defaultValue.
5187 * @param {String} selector The selector/xpath query
5188 * @param {Node} root (optional) The start of the query (defaults to document).
5189 * @param {String} defaultValue
5191 selectValue : function(path, root, defaultValue){
5192 path = path.replace(trimRe, "");
5193 if(!valueCache[path]){
5194 valueCache[path] = Roo.DomQuery.compile(path, "select");
5196 var n = valueCache[path](root);
5197 n = n[0] ? n[0] : n;
5198 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5199 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5203 * Selects the value of a node, parsing integers and floats.
5204 * @param {String} selector The selector/xpath query
5205 * @param {Node} root (optional) The start of the query (defaults to document).
5206 * @param {Number} defaultValue
5209 selectNumber : function(path, root, defaultValue){
5210 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5211 return parseFloat(v);
5215 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5216 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5217 * @param {String} selector The simple selector to test
5220 is : function(el, ss){
5221 if(typeof el == "string"){
5222 el = document.getElementById(el);
5224 var isArray = (el instanceof Array);
5225 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5226 return isArray ? (result.length == el.length) : (result.length > 0);
5230 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5231 * @param {Array} el An array of elements to filter
5232 * @param {String} selector The simple selector to test
5233 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5234 * the selector instead of the ones that match
5237 filter : function(els, ss, nonMatches){
5238 ss = ss.replace(trimRe, "");
5239 if(!simpleCache[ss]){
5240 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5242 var result = simpleCache[ss](els);
5243 return nonMatches ? quickDiff(result, els) : result;
5247 * Collection of matching regular expressions and code snippets.
5251 select: 'n = byClassName(n, null, " {1} ");'
5253 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5254 select: 'n = byPseudo(n, "{1}", "{2}");'
5256 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5257 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5260 select: 'n = byId(n, null, "{1}");'
5263 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5268 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5269 * 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, > <.
5272 "=" : function(a, v){
5275 "!=" : function(a, v){
5278 "^=" : function(a, v){
5279 return a && a.substr(0, v.length) == v;
5281 "$=" : function(a, v){
5282 return a && a.substr(a.length-v.length) == v;
5284 "*=" : function(a, v){
5285 return a && a.indexOf(v) !== -1;
5287 "%=" : function(a, v){
5288 return (a % v) == 0;
5290 "|=" : function(a, v){
5291 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5293 "~=" : function(a, v){
5294 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5299 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5300 * and the argument (if any) supplied in the selector.
5303 "first-child" : function(c){
5304 var r = [], ri = -1, n;
5305 for(var i = 0, ci; ci = n = c[i]; i++){
5306 while((n = n.previousSibling) && n.nodeType != 1);
5314 "last-child" : function(c){
5315 var r = [], ri = -1, n;
5316 for(var i = 0, ci; ci = n = c[i]; i++){
5317 while((n = n.nextSibling) && n.nodeType != 1);
5325 "nth-child" : function(c, a) {
5326 var r = [], ri = -1;
5327 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5328 var f = (m[1] || 1) - 0, l = m[2] - 0;
5329 for(var i = 0, n; n = c[i]; i++){
5330 var pn = n.parentNode;
5331 if (batch != pn._batch) {
5333 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5334 if(cn.nodeType == 1){
5341 if (l == 0 || n.nodeIndex == l){
5344 } else if ((n.nodeIndex + l) % f == 0){
5352 "only-child" : function(c){
5353 var r = [], ri = -1;;
5354 for(var i = 0, ci; ci = c[i]; i++){
5355 if(!prev(ci) && !next(ci)){
5362 "empty" : function(c){
5363 var r = [], ri = -1;
5364 for(var i = 0, ci; ci = c[i]; i++){
5365 var cns = ci.childNodes, j = 0, cn, empty = true;
5368 if(cn.nodeType == 1 || cn.nodeType == 3){
5380 "contains" : function(c, v){
5381 var r = [], ri = -1;
5382 for(var i = 0, ci; ci = c[i]; i++){
5383 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5390 "nodeValue" : function(c, v){
5391 var r = [], ri = -1;
5392 for(var i = 0, ci; ci = c[i]; i++){
5393 if(ci.firstChild && ci.firstChild.nodeValue == v){
5400 "checked" : function(c){
5401 var r = [], ri = -1;
5402 for(var i = 0, ci; ci = c[i]; i++){
5403 if(ci.checked == true){
5410 "not" : function(c, ss){
5411 return Roo.DomQuery.filter(c, ss, true);
5414 "odd" : function(c){
5415 return this["nth-child"](c, "odd");
5418 "even" : function(c){
5419 return this["nth-child"](c, "even");
5422 "nth" : function(c, a){
5423 return c[a-1] || [];
5426 "first" : function(c){
5430 "last" : function(c){
5431 return c[c.length-1] || [];
5434 "has" : function(c, ss){
5435 var s = Roo.DomQuery.select;
5436 var r = [], ri = -1;
5437 for(var i = 0, ci; ci = c[i]; i++){
5438 if(s(ss, ci).length > 0){
5445 "next" : function(c, ss){
5446 var is = Roo.DomQuery.is;
5447 var r = [], ri = -1;
5448 for(var i = 0, ci; ci = c[i]; i++){
5457 "prev" : function(c, ss){
5458 var is = Roo.DomQuery.is;
5459 var r = [], ri = -1;
5460 for(var i = 0, ci; ci = c[i]; i++){
5473 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5474 * @param {String} path The selector/xpath query
5475 * @param {Node} root (optional) The start of the query (defaults to document).
5480 Roo.query = Roo.DomQuery.select;
5483 * Ext JS Library 1.1.1
5484 * Copyright(c) 2006-2007, Ext JS, LLC.
5486 * Originally Released Under LGPL - original licence link has changed is not relivant.
5489 * <script type="text/javascript">
5493 * @class Roo.util.Observable
5494 * Base class that provides a common interface for publishing events. Subclasses are expected to
5495 * to have a property "events" with all the events defined.<br>
5498 Employee = function(name){
5505 Roo.extend(Employee, Roo.util.Observable);
5507 * @param {Object} config properties to use (incuding events / listeners)
5510 Roo.util.Observable = function(cfg){
5513 this.addEvents(cfg.events || {});
5515 delete cfg.events; // make sure
5518 Roo.apply(this, cfg);
5521 this.on(this.listeners);
5522 delete this.listeners;
5525 Roo.util.Observable.prototype = {
5527 * @cfg {Object} listeners list of events and functions to call for this object,
5531 'click' : function(e) {
5541 * Fires the specified event with the passed parameters (minus the event name).
5542 * @param {String} eventName
5543 * @param {Object...} args Variable number of parameters are passed to handlers
5544 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5546 fireEvent : function(){
5547 var ce = this.events[arguments[0].toLowerCase()];
5548 if(typeof ce == "object"){
5549 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5556 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5559 * Appends an event handler to this component
5560 * @param {String} eventName The type of event to listen for
5561 * @param {Function} handler The method the event invokes
5562 * @param {Object} scope (optional) The scope in which to execute the handler
5563 * function. The handler function's "this" context.
5564 * @param {Object} options (optional) An object containing handler configuration
5565 * properties. This may contain any of the following properties:<ul>
5566 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5567 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5568 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5569 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5570 * by the specified number of milliseconds. If the event fires again within that time, the original
5571 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5574 * <b>Combining Options</b><br>
5575 * Using the options argument, it is possible to combine different types of listeners:<br>
5577 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5579 el.on('click', this.onClick, this, {
5586 * <b>Attaching multiple handlers in 1 call</b><br>
5587 * The method also allows for a single argument to be passed which is a config object containing properties
5588 * which specify multiple handlers.
5597 fn: this.onMouseOver,
5601 fn: this.onMouseOut,
5607 * Or a shorthand syntax which passes the same scope object to all handlers:
5610 'click': this.onClick,
5611 'mouseover': this.onMouseOver,
5612 'mouseout': this.onMouseOut,
5617 addListener : function(eventName, fn, scope, o){
5618 if(typeof eventName == "object"){
5621 if(this.filterOptRe.test(e)){
5624 if(typeof o[e] == "function"){
5626 this.addListener(e, o[e], o.scope, o);
5628 // individual options
5629 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5634 o = (!o || typeof o == "boolean") ? {} : o;
5635 eventName = eventName.toLowerCase();
5636 var ce = this.events[eventName] || true;
5637 if(typeof ce == "boolean"){
5638 ce = new Roo.util.Event(this, eventName);
5639 this.events[eventName] = ce;
5641 ce.addListener(fn, scope, o);
5645 * Removes a listener
5646 * @param {String} eventName The type of event to listen for
5647 * @param {Function} handler The handler to remove
5648 * @param {Object} scope (optional) The scope (this object) for the handler
5650 removeListener : function(eventName, fn, scope){
5651 var ce = this.events[eventName.toLowerCase()];
5652 if(typeof ce == "object"){
5653 ce.removeListener(fn, scope);
5658 * Removes all listeners for this object
5660 purgeListeners : function(){
5661 for(var evt in this.events){
5662 if(typeof this.events[evt] == "object"){
5663 this.events[evt].clearListeners();
5668 relayEvents : function(o, events){
5669 var createHandler = function(ename){
5671 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5674 for(var i = 0, len = events.length; i < len; i++){
5675 var ename = events[i];
5676 if(!this.events[ename]){ this.events[ename] = true; };
5677 o.on(ename, createHandler(ename), this);
5682 * Used to define events on this Observable
5683 * @param {Object} object The object with the events defined
5685 addEvents : function(o){
5689 Roo.applyIf(this.events, o);
5693 * Checks to see if this object has any listeners for a specified event
5694 * @param {String} eventName The name of the event to check for
5695 * @return {Boolean} True if the event is being listened for, else false
5697 hasListener : function(eventName){
5698 var e = this.events[eventName];
5699 return typeof e == "object" && e.listeners.length > 0;
5703 * Appends an event handler to this element (shorthand for addListener)
5704 * @param {String} eventName The type of event to listen for
5705 * @param {Function} handler The method the event invokes
5706 * @param {Object} scope (optional) The scope in which to execute the handler
5707 * function. The handler function's "this" context.
5708 * @param {Object} options (optional)
5711 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5713 * Removes a listener (shorthand for removeListener)
5714 * @param {String} eventName The type of event to listen for
5715 * @param {Function} handler The handler to remove
5716 * @param {Object} scope (optional) The scope (this object) for the handler
5719 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5722 * Starts capture on the specified Observable. All events will be passed
5723 * to the supplied function with the event name + standard signature of the event
5724 * <b>before</b> the event is fired. If the supplied function returns false,
5725 * the event will not fire.
5726 * @param {Observable} o The Observable to capture
5727 * @param {Function} fn The function to call
5728 * @param {Object} scope (optional) The scope (this object) for the fn
5731 Roo.util.Observable.capture = function(o, fn, scope){
5732 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5736 * Removes <b>all</b> added captures from the Observable.
5737 * @param {Observable} o The Observable to release
5740 Roo.util.Observable.releaseCapture = function(o){
5741 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5746 var createBuffered = function(h, o, scope){
5747 var task = new Roo.util.DelayedTask();
5749 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5753 var createSingle = function(h, e, fn, scope){
5755 e.removeListener(fn, scope);
5756 return h.apply(scope, arguments);
5760 var createDelayed = function(h, o, scope){
5762 var args = Array.prototype.slice.call(arguments, 0);
5763 setTimeout(function(){
5764 h.apply(scope, args);
5769 Roo.util.Event = function(obj, name){
5772 this.listeners = [];
5775 Roo.util.Event.prototype = {
5776 addListener : function(fn, scope, options){
5777 var o = options || {};
5778 scope = scope || this.obj;
5779 if(!this.isListening(fn, scope)){
5780 var l = {fn: fn, scope: scope, options: o};
5783 h = createDelayed(h, o, scope);
5786 h = createSingle(h, this, fn, scope);
5789 h = createBuffered(h, o, scope);
5792 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5793 this.listeners.push(l);
5795 this.listeners = this.listeners.slice(0);
5796 this.listeners.push(l);
5801 findListener : function(fn, scope){
5802 scope = scope || this.obj;
5803 var ls = this.listeners;
5804 for(var i = 0, len = ls.length; i < len; i++){
5806 if(l.fn == fn && l.scope == scope){
5813 isListening : function(fn, scope){
5814 return this.findListener(fn, scope) != -1;
5817 removeListener : function(fn, scope){
5819 if((index = this.findListener(fn, scope)) != -1){
5821 this.listeners.splice(index, 1);
5823 this.listeners = this.listeners.slice(0);
5824 this.listeners.splice(index, 1);
5831 clearListeners : function(){
5832 this.listeners = [];
5836 var ls = this.listeners, scope, len = ls.length;
5839 var args = Array.prototype.slice.call(arguments, 0);
5840 for(var i = 0; i < len; i++){
5842 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5843 this.firing = false;
5847 this.firing = false;
5854 * Ext JS Library 1.1.1
5855 * Copyright(c) 2006-2007, Ext JS, LLC.
5857 * Originally Released Under LGPL - original licence link has changed is not relivant.
5860 * <script type="text/javascript">
5864 * @class Roo.EventManager
5865 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5866 * several useful events directly.
5867 * See {@link Roo.EventObject} for more details on normalized event objects.
5870 Roo.EventManager = function(){
5871 var docReadyEvent, docReadyProcId, docReadyState = false;
5872 var resizeEvent, resizeTask, textEvent, textSize;
5873 var E = Roo.lib.Event;
5874 var D = Roo.lib.Dom;
5877 var fireDocReady = function(){
5879 docReadyState = true;
5882 clearInterval(docReadyProcId);
5884 if(Roo.isGecko || Roo.isOpera) {
5885 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5888 var defer = document.getElementById("ie-deferred-loader");
5890 defer.onreadystatechange = null;
5891 defer.parentNode.removeChild(defer);
5895 docReadyEvent.fire();
5896 docReadyEvent.clearListeners();
5901 var initDocReady = function(){
5902 docReadyEvent = new Roo.util.Event();
5903 if(Roo.isGecko || Roo.isOpera) {
5904 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5906 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5907 var defer = document.getElementById("ie-deferred-loader");
5908 defer.onreadystatechange = function(){
5909 if(this.readyState == "complete"){
5913 }else if(Roo.isSafari){
5914 docReadyProcId = setInterval(function(){
5915 var rs = document.readyState;
5916 if(rs == "complete") {
5921 // no matter what, make sure it fires on load
5922 E.on(window, "load", fireDocReady);
5925 var createBuffered = function(h, o){
5926 var task = new Roo.util.DelayedTask(h);
5928 // create new event object impl so new events don't wipe out properties
5929 e = new Roo.EventObjectImpl(e);
5930 task.delay(o.buffer, h, null, [e]);
5934 var createSingle = function(h, el, ename, fn){
5936 Roo.EventManager.removeListener(el, ename, fn);
5941 var createDelayed = function(h, o){
5943 // create new event object impl so new events don't wipe out properties
5944 e = new Roo.EventObjectImpl(e);
5945 setTimeout(function(){
5951 var listen = function(element, ename, opt, fn, scope){
5952 var o = (!opt || typeof opt == "boolean") ? {} : opt;
5953 fn = fn || o.fn; scope = scope || o.scope;
5954 var el = Roo.getDom(element);
5956 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
5958 var h = function(e){
5959 e = Roo.EventObject.setEvent(e);
5962 t = e.getTarget(o.delegate, el);
5969 if(o.stopEvent === true){
5972 if(o.preventDefault === true){
5975 if(o.stopPropagation === true){
5976 e.stopPropagation();
5979 if(o.normalized === false){
5983 fn.call(scope || el, e, t, o);
5986 h = createDelayed(h, o);
5989 h = createSingle(h, el, ename, fn);
5992 h = createBuffered(h, o);
5994 fn._handlers = fn._handlers || [];
5995 fn._handlers.push([Roo.id(el), ename, h]);
5998 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
5999 el.addEventListener("DOMMouseScroll", h, false);
6000 E.on(window, 'unload', function(){
6001 el.removeEventListener("DOMMouseScroll", h, false);
6004 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6005 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
6010 var stopListening = function(el, ename, fn){
6011 var id = Roo.id(el), hds = fn._handlers, hd = fn;
6013 for(var i = 0, len = hds.length; i < len; i++){
6015 if(h[0] == id && h[1] == ename){
6022 E.un(el, ename, hd);
6023 el = Roo.getDom(el);
6024 if(ename == "mousewheel" && el.addEventListener){
6025 el.removeEventListener("DOMMouseScroll", hd, false);
6027 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
6028 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
6032 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
6039 * @scope Roo.EventManager
6044 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
6045 * object with a Roo.EventObject
6046 * @param {Function} fn The method the event invokes
6047 * @param {Object} scope An object that becomes the scope of the handler
6048 * @param {boolean} override If true, the obj passed in becomes
6049 * the execution scope of the listener
6050 * @return {Function} The wrapped function
6053 wrap : function(fn, scope, override){
6055 Roo.EventObject.setEvent(e);
6056 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6061 * Appends an event handler to an element (shorthand for addListener)
6062 * @param {String/HTMLElement} element The html element or id to assign the
6063 * @param {String} eventName The type of event to listen for
6064 * @param {Function} handler The method the event invokes
6065 * @param {Object} scope (optional) The scope in which to execute the handler
6066 * function. The handler function's "this" context.
6067 * @param {Object} options (optional) An object containing handler configuration
6068 * properties. This may contain any of the following properties:<ul>
6069 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6070 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6071 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6072 * <li>preventDefault {Boolean} True to prevent the default action</li>
6073 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6074 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6075 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6076 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6077 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6078 * by the specified number of milliseconds. If the event fires again within that time, the original
6079 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6082 * <b>Combining Options</b><br>
6083 * Using the options argument, it is possible to combine different types of listeners:<br>
6085 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6087 el.on('click', this.onClick, this, {
6094 * <b>Attaching multiple handlers in 1 call</b><br>
6095 * The method also allows for a single argument to be passed which is a config object containing properties
6096 * which specify multiple handlers.
6106 fn: this.onMouseOver
6115 * Or a shorthand syntax:<br>
6118 'click' : this.onClick,
6119 'mouseover' : this.onMouseOver,
6120 'mouseout' : this.onMouseOut
6124 addListener : function(element, eventName, fn, scope, options){
6125 if(typeof eventName == "object"){
6131 if(typeof o[e] == "function"){
6133 listen(element, e, o, o[e], o.scope);
6135 // individual options
6136 listen(element, e, o[e]);
6141 return listen(element, eventName, options, fn, scope);
6145 * Removes an event handler
6147 * @param {String/HTMLElement} element The id or html element to remove the
6149 * @param {String} eventName The type of event
6150 * @param {Function} fn
6151 * @return {Boolean} True if a listener was actually removed
6153 removeListener : function(element, eventName, fn){
6154 return stopListening(element, eventName, fn);
6158 * Fires when the document is ready (before onload and before images are loaded). Can be
6159 * accessed shorthanded Roo.onReady().
6160 * @param {Function} fn The method the event invokes
6161 * @param {Object} scope An object that becomes the scope of the handler
6162 * @param {boolean} options
6164 onDocumentReady : function(fn, scope, options){
6165 if(docReadyState){ // if it already fired
6166 docReadyEvent.addListener(fn, scope, options);
6167 docReadyEvent.fire();
6168 docReadyEvent.clearListeners();
6174 docReadyEvent.addListener(fn, scope, options);
6178 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6179 * @param {Function} fn The method the event invokes
6180 * @param {Object} scope An object that becomes the scope of the handler
6181 * @param {boolean} options
6183 onWindowResize : function(fn, scope, options){
6185 resizeEvent = new Roo.util.Event();
6186 resizeTask = new Roo.util.DelayedTask(function(){
6187 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6189 E.on(window, "resize", function(){
6191 resizeTask.delay(50);
6193 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6197 resizeEvent.addListener(fn, scope, options);
6201 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6202 * @param {Function} fn The method the event invokes
6203 * @param {Object} scope An object that becomes the scope of the handler
6204 * @param {boolean} options
6206 onTextResize : function(fn, scope, options){
6208 textEvent = new Roo.util.Event();
6209 var textEl = new Roo.Element(document.createElement('div'));
6210 textEl.dom.className = 'x-text-resize';
6211 textEl.dom.innerHTML = 'X';
6212 textEl.appendTo(document.body);
6213 textSize = textEl.dom.offsetHeight;
6214 setInterval(function(){
6215 if(textEl.dom.offsetHeight != textSize){
6216 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6218 }, this.textResizeInterval);
6220 textEvent.addListener(fn, scope, options);
6224 * Removes the passed window resize listener.
6225 * @param {Function} fn The method the event invokes
6226 * @param {Object} scope The scope of handler
6228 removeResizeListener : function(fn, scope){
6230 resizeEvent.removeListener(fn, scope);
6235 fireResize : function(){
6237 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6241 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6245 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6247 textResizeInterval : 50
6252 * @scopeAlias pub=Roo.EventManager
6256 * Appends an event handler to an element (shorthand for addListener)
6257 * @param {String/HTMLElement} element The html element or id to assign the
6258 * @param {String} eventName The type of event to listen for
6259 * @param {Function} handler The method the event invokes
6260 * @param {Object} scope (optional) The scope in which to execute the handler
6261 * function. The handler function's "this" context.
6262 * @param {Object} options (optional) An object containing handler configuration
6263 * properties. This may contain any of the following properties:<ul>
6264 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6265 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6266 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6267 * <li>preventDefault {Boolean} True to prevent the default action</li>
6268 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6269 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6270 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6271 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6272 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6273 * by the specified number of milliseconds. If the event fires again within that time, the original
6274 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6277 * <b>Combining Options</b><br>
6278 * Using the options argument, it is possible to combine different types of listeners:<br>
6280 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6282 el.on('click', this.onClick, this, {
6289 * <b>Attaching multiple handlers in 1 call</b><br>
6290 * The method also allows for a single argument to be passed which is a config object containing properties
6291 * which specify multiple handlers.
6301 fn: this.onMouseOver
6310 * Or a shorthand syntax:<br>
6313 'click' : this.onClick,
6314 'mouseover' : this.onMouseOver,
6315 'mouseout' : this.onMouseOut
6319 pub.on = pub.addListener;
6320 pub.un = pub.removeListener;
6322 pub.stoppedMouseDownEvent = new Roo.util.Event();
6326 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6327 * @param {Function} fn The method the event invokes
6328 * @param {Object} scope An object that becomes the scope of the handler
6329 * @param {boolean} override If true, the obj passed in becomes
6330 * the execution scope of the listener
6334 Roo.onReady = Roo.EventManager.onDocumentReady;
6336 Roo.onReady(function(){
6337 var bd = Roo.get(document.body);
6342 : Roo.isGecko ? "roo-gecko"
6343 : Roo.isOpera ? "roo-opera"
6344 : Roo.isSafari ? "roo-safari" : ""];
6347 cls.push("roo-mac");
6350 cls.push("roo-linux");
6352 if(Roo.isBorderBox){
6353 cls.push('roo-border-box');
6355 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6356 var p = bd.dom.parentNode;
6358 p.className += ' roo-strict';
6361 bd.addClass(cls.join(' '));
6365 * @class Roo.EventObject
6366 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6367 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6370 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6372 var target = e.getTarget();
6375 var myDiv = Roo.get("myDiv");
6376 myDiv.on("click", handleClick);
6378 Roo.EventManager.on("myDiv", 'click', handleClick);
6379 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6383 Roo.EventObject = function(){
6385 var E = Roo.lib.Event;
6387 // safari keypress events for special keys return bad keycodes
6390 63235 : 39, // right
6393 63276 : 33, // page up
6394 63277 : 34, // page down
6395 63272 : 46, // delete
6400 // normalize button clicks
6401 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6402 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6404 Roo.EventObjectImpl = function(e){
6406 this.setEvent(e.browserEvent || e);
6409 Roo.EventObjectImpl.prototype = {
6411 * Used to fix doc tools.
6412 * @scope Roo.EventObject.prototype
6418 /** The normal browser event */
6419 browserEvent : null,
6420 /** The button pressed in a mouse event */
6422 /** True if the shift key was down during the event */
6424 /** True if the control key was down during the event */
6426 /** True if the alt key was down during the event */
6485 setEvent : function(e){
6486 if(e == this || (e && e.browserEvent)){ // already wrapped
6489 this.browserEvent = e;
6491 // normalize buttons
6492 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6493 if(e.type == 'click' && this.button == -1){
6497 this.shiftKey = e.shiftKey;
6498 // mac metaKey behaves like ctrlKey
6499 this.ctrlKey = e.ctrlKey || e.metaKey;
6500 this.altKey = e.altKey;
6501 // in getKey these will be normalized for the mac
6502 this.keyCode = e.keyCode;
6503 // keyup warnings on firefox.
6504 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6505 // cache the target for the delayed and or buffered events
6506 this.target = E.getTarget(e);
6508 this.xy = E.getXY(e);
6511 this.shiftKey = false;
6512 this.ctrlKey = false;
6513 this.altKey = false;
6523 * Stop the event (preventDefault and stopPropagation)
6525 stopEvent : function(){
6526 if(this.browserEvent){
6527 if(this.browserEvent.type == 'mousedown'){
6528 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6530 E.stopEvent(this.browserEvent);
6535 * Prevents the browsers default handling of the event.
6537 preventDefault : function(){
6538 if(this.browserEvent){
6539 E.preventDefault(this.browserEvent);
6544 isNavKeyPress : function(){
6545 var k = this.keyCode;
6546 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6547 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6550 isSpecialKey : function(){
6551 var k = this.keyCode;
6552 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6553 (k == 16) || (k == 17) ||
6554 (k >= 18 && k <= 20) ||
6555 (k >= 33 && k <= 35) ||
6556 (k >= 36 && k <= 39) ||
6557 (k >= 44 && k <= 45);
6560 * Cancels bubbling of the event.
6562 stopPropagation : function(){
6563 if(this.browserEvent){
6564 if(this.type == 'mousedown'){
6565 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6567 E.stopPropagation(this.browserEvent);
6572 * Gets the key code for the event.
6575 getCharCode : function(){
6576 return this.charCode || this.keyCode;
6580 * Returns a normalized keyCode for the event.
6581 * @return {Number} The key code
6583 getKey : function(){
6584 var k = this.keyCode || this.charCode;
6585 return Roo.isSafari ? (safariKeys[k] || k) : k;
6589 * Gets the x coordinate of the event.
6592 getPageX : function(){
6597 * Gets the y coordinate of the event.
6600 getPageY : function(){
6605 * Gets the time of the event.
6608 getTime : function(){
6609 if(this.browserEvent){
6610 return E.getTime(this.browserEvent);
6616 * Gets the page coordinates of the event.
6617 * @return {Array} The xy values like [x, y]
6624 * Gets the target for the event.
6625 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6626 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6627 search as a number or element (defaults to 10 || document.body)
6628 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6629 * @return {HTMLelement}
6631 getTarget : function(selector, maxDepth, returnEl){
6632 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6635 * Gets the related target.
6636 * @return {HTMLElement}
6638 getRelatedTarget : function(){
6639 if(this.browserEvent){
6640 return E.getRelatedTarget(this.browserEvent);
6646 * Normalizes mouse wheel delta across browsers
6647 * @return {Number} The delta
6649 getWheelDelta : function(){
6650 var e = this.browserEvent;
6652 if(e.wheelDelta){ /* IE/Opera. */
6653 delta = e.wheelDelta/120;
6654 }else if(e.detail){ /* Mozilla case. */
6655 delta = -e.detail/3;
6661 * Returns true if the control, meta, shift or alt key was pressed during this event.
6664 hasModifier : function(){
6665 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6669 * Returns true if the target of this event equals el or is a child of el
6670 * @param {String/HTMLElement/Element} el
6671 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6674 within : function(el, related){
6675 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6676 return t && Roo.fly(el).contains(t);
6679 getPoint : function(){
6680 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6684 return new Roo.EventObjectImpl();
6689 * Ext JS Library 1.1.1
6690 * Copyright(c) 2006-2007, Ext JS, LLC.
6692 * Originally Released Under LGPL - original licence link has changed is not relivant.
6695 * <script type="text/javascript">
6699 // was in Composite Element!??!?!
6702 var D = Roo.lib.Dom;
6703 var E = Roo.lib.Event;
6704 var A = Roo.lib.Anim;
6706 // local style camelizing for speed
6708 var camelRe = /(-[a-z])/gi;
6709 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6710 var view = document.defaultView;
6713 * @class Roo.Element
6714 * Represents an Element in the DOM.<br><br>
6717 var el = Roo.get("my-div");
6720 var el = getEl("my-div");
6722 // or with a DOM element
6723 var el = Roo.get(myDivElement);
6725 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6726 * each call instead of constructing a new one.<br><br>
6727 * <b>Animations</b><br />
6728 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6729 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6731 Option Default Description
6732 --------- -------- ---------------------------------------------
6733 duration .35 The duration of the animation in seconds
6734 easing easeOut The YUI easing method
6735 callback none A function to execute when the anim completes
6736 scope this The scope (this) of the callback function
6738 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6739 * manipulate the animation. Here's an example:
6741 var el = Roo.get("my-div");
6746 // default animation
6747 el.setWidth(100, true);
6749 // animation with some options set
6756 // using the "anim" property to get the Anim object
6762 el.setWidth(100, opt);
6764 if(opt.anim.isAnimated()){
6768 * <b> Composite (Collections of) Elements</b><br />
6769 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6770 * @constructor Create a new Element directly.
6771 * @param {String/HTMLElement} element
6772 * @param {Boolean} forceNew (optional) By default the constructor checks to see if there is already an instance of this element in the cache and if there is it returns the same instance. This will skip that check (useful for extending this class).
6774 Roo.Element = function(element, forceNew){
6775 var dom = typeof element == "string" ?
6776 document.getElementById(element) : element;
6777 if(!dom){ // invalid id/element
6781 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6782 return Roo.Element.cache[id];
6792 * The DOM element ID
6795 this.id = id || Roo.id(dom);
6798 var El = Roo.Element;
6802 * The element's default display mode (defaults to "")
6805 originalDisplay : "",
6809 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6814 * Sets the element's visibility mode. When setVisible() is called it
6815 * will use this to determine whether to set the visibility or the display property.
6816 * @param visMode Element.VISIBILITY or Element.DISPLAY
6817 * @return {Roo.Element} this
6819 setVisibilityMode : function(visMode){
6820 this.visibilityMode = visMode;
6824 * Convenience method for setVisibilityMode(Element.DISPLAY)
6825 * @param {String} display (optional) What to set display to when visible
6826 * @return {Roo.Element} this
6828 enableDisplayMode : function(display){
6829 this.setVisibilityMode(El.DISPLAY);
6830 if(typeof display != "undefined") this.originalDisplay = display;
6835 * Looks at this node and then at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6836 * @param {String} selector The simple selector to test
6837 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6838 search as a number or element (defaults to 10 || document.body)
6839 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6840 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6842 findParent : function(simpleSelector, maxDepth, returnEl){
6843 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6844 maxDepth = maxDepth || 50;
6845 if(typeof maxDepth != "number"){
6846 stopEl = Roo.getDom(maxDepth);
6849 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6850 if(dq.is(p, simpleSelector)){
6851 return returnEl ? Roo.get(p) : p;
6861 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6862 * @param {String} selector The simple selector to test
6863 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6864 search as a number or element (defaults to 10 || document.body)
6865 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6866 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6868 findParentNode : function(simpleSelector, maxDepth, returnEl){
6869 var p = Roo.fly(this.dom.parentNode, '_internal');
6870 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6874 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6875 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6876 * @param {String} selector The simple selector to test
6877 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6878 search as a number or element (defaults to 10 || document.body)
6879 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6881 up : function(simpleSelector, maxDepth){
6882 return this.findParentNode(simpleSelector, maxDepth, true);
6888 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6889 * @param {String} selector The simple selector to test
6890 * @return {Boolean} True if this element matches the selector, else false
6892 is : function(simpleSelector){
6893 return Roo.DomQuery.is(this.dom, simpleSelector);
6897 * Perform animation on this element.
6898 * @param {Object} args The YUI animation control args
6899 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6900 * @param {Function} onComplete (optional) Function to call when animation completes
6901 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6902 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6903 * @return {Roo.Element} this
6905 animate : function(args, duration, onComplete, easing, animType){
6906 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6911 * @private Internal animation call
6913 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6914 animType = animType || 'run';
6916 var anim = Roo.lib.Anim[animType](
6918 (opt.duration || defaultDur) || .35,
6919 (opt.easing || defaultEase) || 'easeOut',
6921 Roo.callback(cb, this);
6922 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6930 // private legacy anim prep
6931 preanim : function(a, i){
6932 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6936 * Removes worthless text nodes
6937 * @param {Boolean} forceReclean (optional) By default the element
6938 * keeps track if it has been cleaned already so
6939 * you can call this over and over. However, if you update the element and
6940 * need to force a reclean, you can pass true.
6942 clean : function(forceReclean){
6943 if(this.isCleaned && forceReclean !== true){
6947 var d = this.dom, n = d.firstChild, ni = -1;
6949 var nx = n.nextSibling;
6950 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
6957 this.isCleaned = true;
6962 calcOffsetsTo : function(el){
6965 var restorePos = false;
6966 if(el.getStyle('position') == 'static'){
6967 el.position('relative');
6972 while(op && op != d && op.tagName != 'HTML'){
6975 op = op.offsetParent;
6978 el.position('static');
6984 * Scrolls this element into view within the passed container.
6985 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
6986 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
6987 * @return {Roo.Element} this
6989 scrollIntoView : function(container, hscroll){
6990 var c = Roo.getDom(container) || document.body;
6993 var o = this.calcOffsetsTo(c),
6996 b = t+el.offsetHeight,
6997 r = l+el.offsetWidth;
6999 var ch = c.clientHeight;
7000 var ct = parseInt(c.scrollTop, 10);
7001 var cl = parseInt(c.scrollLeft, 10);
7003 var cr = cl + c.clientWidth;
7011 if(hscroll !== false){
7015 c.scrollLeft = r-c.clientWidth;
7022 scrollChildIntoView : function(child, hscroll){
7023 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
7027 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
7028 * the new height may not be available immediately.
7029 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
7030 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
7031 * @param {Function} onComplete (optional) Function to call when animation completes
7032 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
7033 * @return {Roo.Element} this
7035 autoHeight : function(animate, duration, onComplete, easing){
7036 var oldHeight = this.getHeight();
7038 this.setHeight(1); // force clipping
7039 setTimeout(function(){
7040 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
7042 this.setHeight(height);
7044 if(typeof onComplete == "function"){
7048 this.setHeight(oldHeight); // restore original height
7049 this.setHeight(height, animate, duration, function(){
7051 if(typeof onComplete == "function") onComplete();
7052 }.createDelegate(this), easing);
7054 }.createDelegate(this), 0);
7059 * Returns true if this element is an ancestor of the passed element
7060 * @param {HTMLElement/String} el The element to check
7061 * @return {Boolean} True if this element is an ancestor of el, else false
7063 contains : function(el){
7064 if(!el){return false;}
7065 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7069 * Checks whether the element is currently visible using both visibility and display properties.
7070 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7071 * @return {Boolean} True if the element is currently visible, else false
7073 isVisible : function(deep) {
7074 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7075 if(deep !== true || !vis){
7078 var p = this.dom.parentNode;
7079 while(p && p.tagName.toLowerCase() != "body"){
7080 if(!Roo.fly(p, '_isVisible').isVisible()){
7089 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7090 * @param {String} selector The CSS selector
7091 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7092 * @return {CompositeElement/CompositeElementLite} The composite element
7094 select : function(selector, unique){
7095 return El.select(selector, unique, this.dom);
7099 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7100 * @param {String} selector The CSS selector
7101 * @return {Array} An array of the matched nodes
7103 query : function(selector, unique){
7104 return Roo.DomQuery.select(selector, this.dom);
7108 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7109 * @param {String} selector The CSS selector
7110 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7111 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7113 child : function(selector, returnDom){
7114 var n = Roo.DomQuery.selectNode(selector, this.dom);
7115 return returnDom ? n : Roo.get(n);
7119 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7120 * @param {String} selector The CSS selector
7121 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7122 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7124 down : function(selector, returnDom){
7125 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7126 return returnDom ? n : Roo.get(n);
7130 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7131 * @param {String} group The group the DD object is member of
7132 * @param {Object} config The DD config object
7133 * @param {Object} overrides An object containing methods to override/implement on the DD object
7134 * @return {Roo.dd.DD} The DD object
7136 initDD : function(group, config, overrides){
7137 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7138 return Roo.apply(dd, overrides);
7142 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7143 * @param {String} group The group the DDProxy object is member of
7144 * @param {Object} config The DDProxy config object
7145 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7146 * @return {Roo.dd.DDProxy} The DDProxy object
7148 initDDProxy : function(group, config, overrides){
7149 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7150 return Roo.apply(dd, overrides);
7154 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7155 * @param {String} group The group the DDTarget object is member of
7156 * @param {Object} config The DDTarget config object
7157 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7158 * @return {Roo.dd.DDTarget} The DDTarget object
7160 initDDTarget : function(group, config, overrides){
7161 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7162 return Roo.apply(dd, overrides);
7166 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7167 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7168 * @param {Boolean} visible Whether the element is visible
7169 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7170 * @return {Roo.Element} this
7172 setVisible : function(visible, animate){
7174 if(this.visibilityMode == El.DISPLAY){
7175 this.setDisplayed(visible);
7178 this.dom.style.visibility = visible ? "visible" : "hidden";
7181 // closure for composites
7183 var visMode = this.visibilityMode;
7185 this.setOpacity(.01);
7186 this.setVisible(true);
7188 this.anim({opacity: { to: (visible?1:0) }},
7189 this.preanim(arguments, 1),
7190 null, .35, 'easeIn', function(){
7192 if(visMode == El.DISPLAY){
7193 dom.style.display = "none";
7195 dom.style.visibility = "hidden";
7197 Roo.get(dom).setOpacity(1);
7205 * Returns true if display is not "none"
7208 isDisplayed : function() {
7209 return this.getStyle("display") != "none";
7213 * Toggles the element's visibility or display, depending on visibility mode.
7214 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7215 * @return {Roo.Element} this
7217 toggle : function(animate){
7218 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7223 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7224 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7225 * @return {Roo.Element} this
7227 setDisplayed : function(value) {
7228 if(typeof value == "boolean"){
7229 value = value ? this.originalDisplay : "none";
7231 this.setStyle("display", value);
7236 * Tries to focus the element. Any exceptions are caught and ignored.
7237 * @return {Roo.Element} this
7239 focus : function() {
7247 * Tries to blur the element. Any exceptions are caught and ignored.
7248 * @return {Roo.Element} this
7258 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7259 * @param {String/Array} className The CSS class to add, or an array of classes
7260 * @return {Roo.Element} this
7262 addClass : function(className){
7263 if(className instanceof Array){
7264 for(var i = 0, len = className.length; i < len; i++) {
7265 this.addClass(className[i]);
7268 if(className && !this.hasClass(className)){
7269 this.dom.className = this.dom.className + " " + className;
7276 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7277 * @param {String/Array} className The CSS class to add, or an array of classes
7278 * @return {Roo.Element} this
7280 radioClass : function(className){
7281 var siblings = this.dom.parentNode.childNodes;
7282 for(var i = 0; i < siblings.length; i++) {
7283 var s = siblings[i];
7284 if(s.nodeType == 1){
7285 Roo.get(s).removeClass(className);
7288 this.addClass(className);
7293 * Removes one or more CSS classes from the element.
7294 * @param {String/Array} className The CSS class to remove, or an array of classes
7295 * @return {Roo.Element} this
7297 removeClass : function(className){
7298 if(!className || !this.dom.className){
7301 if(className instanceof Array){
7302 for(var i = 0, len = className.length; i < len; i++) {
7303 this.removeClass(className[i]);
7306 if(this.hasClass(className)){
7307 var re = this.classReCache[className];
7309 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7310 this.classReCache[className] = re;
7312 this.dom.className =
7313 this.dom.className.replace(re, " ");
7323 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7324 * @param {String} className The CSS class to toggle
7325 * @return {Roo.Element} this
7327 toggleClass : function(className){
7328 if(this.hasClass(className)){
7329 this.removeClass(className);
7331 this.addClass(className);
7337 * Checks if the specified CSS class exists on this element's DOM node.
7338 * @param {String} className The CSS class to check for
7339 * @return {Boolean} True if the class exists, else false
7341 hasClass : function(className){
7342 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7346 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7347 * @param {String} oldClassName The CSS class to replace
7348 * @param {String} newClassName The replacement CSS class
7349 * @return {Roo.Element} this
7351 replaceClass : function(oldClassName, newClassName){
7352 this.removeClass(oldClassName);
7353 this.addClass(newClassName);
7358 * Returns an object with properties matching the styles requested.
7359 * For example, el.getStyles('color', 'font-size', 'width') might return
7360 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7361 * @param {String} style1 A style name
7362 * @param {String} style2 A style name
7363 * @param {String} etc.
7364 * @return {Object} The style object
7366 getStyles : function(){
7367 var a = arguments, len = a.length, r = {};
7368 for(var i = 0; i < len; i++){
7369 r[a[i]] = this.getStyle(a[i]);
7375 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7376 * @param {String} property The style property whose value is returned.
7377 * @return {String} The current value of the style property for this element.
7379 getStyle : function(){
7380 return view && view.getComputedStyle ?
7382 var el = this.dom, v, cs, camel;
7383 if(prop == 'float'){
7386 if(el.style && (v = el.style[prop])){
7389 if(cs = view.getComputedStyle(el, "")){
7390 if(!(camel = propCache[prop])){
7391 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7398 var el = this.dom, v, cs, camel;
7399 if(prop == 'opacity'){
7400 if(typeof el.style.filter == 'string'){
7401 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7403 var fv = parseFloat(m[1]);
7405 return fv ? fv / 100 : 0;
7410 }else if(prop == 'float'){
7411 prop = "styleFloat";
7413 if(!(camel = propCache[prop])){
7414 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7416 if(v = el.style[camel]){
7419 if(cs = el.currentStyle){
7427 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7428 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7429 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7430 * @return {Roo.Element} this
7432 setStyle : function(prop, value){
7433 if(typeof prop == "string"){
7435 if (prop == 'float') {
7436 this.setStyle(Roo.isIE ? 'styleFloat' : 'cssFloat', value);
7441 if(!(camel = propCache[prop])){
7442 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7445 if(camel == 'opacity') {
7446 this.setOpacity(value);
7448 this.dom.style[camel] = value;
7451 for(var style in prop){
7452 if(typeof prop[style] != "function"){
7453 this.setStyle(style, prop[style]);
7461 * More flexible version of {@link #setStyle} for setting style properties.
7462 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7463 * a function which returns such a specification.
7464 * @return {Roo.Element} this
7466 applyStyles : function(style){
7467 Roo.DomHelper.applyStyles(this.dom, style);
7472 * Gets the current X position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7473 * @return {Number} The X position of the element
7476 return D.getX(this.dom);
7480 * Gets the current Y position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7481 * @return {Number} The Y position of the element
7484 return D.getY(this.dom);
7488 * Gets the current position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7489 * @return {Array} The XY position of the element
7492 return D.getXY(this.dom);
7496 * Sets the X position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7497 * @param {Number} The X position of the element
7498 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7499 * @return {Roo.Element} this
7501 setX : function(x, animate){
7503 D.setX(this.dom, x);
7505 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7511 * Sets the Y position of the element based on page coordinates. Element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7512 * @param {Number} The Y position of the element
7513 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7514 * @return {Roo.Element} this
7516 setY : function(y, animate){
7518 D.setY(this.dom, y);
7520 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7526 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7527 * @param {String} left The left CSS property value
7528 * @return {Roo.Element} this
7530 setLeft : function(left){
7531 this.setStyle("left", this.addUnits(left));
7536 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7537 * @param {String} top The top CSS property value
7538 * @return {Roo.Element} this
7540 setTop : function(top){
7541 this.setStyle("top", this.addUnits(top));
7546 * Sets the element's CSS right style.
7547 * @param {String} right The right CSS property value
7548 * @return {Roo.Element} this
7550 setRight : function(right){
7551 this.setStyle("right", this.addUnits(right));
7556 * Sets the element's CSS bottom style.
7557 * @param {String} bottom The bottom CSS property value
7558 * @return {Roo.Element} this
7560 setBottom : function(bottom){
7561 this.setStyle("bottom", this.addUnits(bottom));
7566 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7567 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7568 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7569 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7570 * @return {Roo.Element} this
7572 setXY : function(pos, animate){
7574 D.setXY(this.dom, pos);
7576 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7582 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7583 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7584 * @param {Number} x X value for new position (coordinates are page-based)
7585 * @param {Number} y Y value for new position (coordinates are page-based)
7586 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7587 * @return {Roo.Element} this
7589 setLocation : function(x, y, animate){
7590 this.setXY([x, y], this.preanim(arguments, 2));
7595 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7596 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7597 * @param {Number} x X value for new position (coordinates are page-based)
7598 * @param {Number} y Y value for new position (coordinates are page-based)
7599 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7600 * @return {Roo.Element} this
7602 moveTo : function(x, y, animate){
7603 this.setXY([x, y], this.preanim(arguments, 2));
7608 * Returns the region of the given element.
7609 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7610 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7612 getRegion : function(){
7613 return D.getRegion(this.dom);
7617 * Returns the offset height of the element
7618 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7619 * @return {Number} The element's height
7621 getHeight : function(contentHeight){
7622 var h = this.dom.offsetHeight || 0;
7623 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7627 * Returns the offset width of the element
7628 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7629 * @return {Number} The element's width
7631 getWidth : function(contentWidth){
7632 var w = this.dom.offsetWidth || 0;
7633 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7637 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7638 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7639 * if a height has not been set using CSS.
7642 getComputedHeight : function(){
7643 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7645 h = parseInt(this.getStyle('height'), 10) || 0;
7646 if(!this.isBorderBox()){
7647 h += this.getFrameWidth('tb');
7654 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7655 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7656 * if a width has not been set using CSS.
7659 getComputedWidth : function(){
7660 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7662 w = parseInt(this.getStyle('width'), 10) || 0;
7663 if(!this.isBorderBox()){
7664 w += this.getFrameWidth('lr');
7671 * Returns the size of the element.
7672 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7673 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7675 getSize : function(contentSize){
7676 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7680 * Returns the width and height of the viewport.
7681 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7683 getViewSize : function(){
7684 var d = this.dom, doc = document, aw = 0, ah = 0;
7685 if(d == doc || d == doc.body){
7686 return {width : D.getViewWidth(), height: D.getViewHeight()};
7689 width : d.clientWidth,
7690 height: d.clientHeight
7696 * Returns the value of the "value" attribute
7697 * @param {Boolean} asNumber true to parse the value as a number
7698 * @return {String/Number}
7700 getValue : function(asNumber){
7701 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7705 adjustWidth : function(width){
7706 if(typeof width == "number"){
7707 if(this.autoBoxAdjust && !this.isBorderBox()){
7708 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7718 adjustHeight : function(height){
7719 if(typeof height == "number"){
7720 if(this.autoBoxAdjust && !this.isBorderBox()){
7721 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7731 * Set the width of the element
7732 * @param {Number} width The new width
7733 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7734 * @return {Roo.Element} this
7736 setWidth : function(width, animate){
7737 width = this.adjustWidth(width);
7739 this.dom.style.width = this.addUnits(width);
7741 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7747 * Set the height of the element
7748 * @param {Number} height The new height
7749 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7750 * @return {Roo.Element} this
7752 setHeight : function(height, animate){
7753 height = this.adjustHeight(height);
7755 this.dom.style.height = this.addUnits(height);
7757 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7763 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7764 * @param {Number} width The new width
7765 * @param {Number} height The new height
7766 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7767 * @return {Roo.Element} this
7769 setSize : function(width, height, animate){
7770 if(typeof width == "object"){ // in case of object from getSize()
7771 height = width.height; width = width.width;
7773 width = this.adjustWidth(width); height = this.adjustHeight(height);
7775 this.dom.style.width = this.addUnits(width);
7776 this.dom.style.height = this.addUnits(height);
7778 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7784 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7785 * @param {Number} x X value for new position (coordinates are page-based)
7786 * @param {Number} y Y value for new position (coordinates are page-based)
7787 * @param {Number} width The new width
7788 * @param {Number} height The new height
7789 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7790 * @return {Roo.Element} this
7792 setBounds : function(x, y, width, height, animate){
7794 this.setSize(width, height);
7795 this.setLocation(x, y);
7797 width = this.adjustWidth(width); height = this.adjustHeight(height);
7798 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7799 this.preanim(arguments, 4), 'motion');
7805 * Sets the element's position and size the the specified region. If animation is true then width, height, x and y will be animated concurrently.
7806 * @param {Roo.lib.Region} region The region to fill
7807 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7808 * @return {Roo.Element} this
7810 setRegion : function(region, animate){
7811 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7816 * Appends an event handler
7818 * @param {String} eventName The type of event to append
7819 * @param {Function} fn The method the event invokes
7820 * @param {Object} scope (optional) The scope (this object) of the fn
7821 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7823 addListener : function(eventName, fn, scope, options){
7824 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7828 * Removes an event handler from this element
7829 * @param {String} eventName the type of event to remove
7830 * @param {Function} fn the method the event invokes
7831 * @return {Roo.Element} this
7833 removeListener : function(eventName, fn){
7834 Roo.EventManager.removeListener(this.dom, eventName, fn);
7839 * Removes all previous added listeners from this element
7840 * @return {Roo.Element} this
7842 removeAllListeners : function(){
7843 E.purgeElement(this.dom);
7847 relayEvent : function(eventName, observable){
7848 this.on(eventName, function(e){
7849 observable.fireEvent(eventName, e);
7854 * Set the opacity of the element
7855 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7856 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7857 * @return {Roo.Element} this
7859 setOpacity : function(opacity, animate){
7861 var s = this.dom.style;
7864 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7865 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7867 s.opacity = opacity;
7870 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7876 * Gets the left X coordinate
7877 * @param {Boolean} local True to get the local css position instead of page coordinate
7880 getLeft : function(local){
7884 return parseInt(this.getStyle("left"), 10) || 0;
7889 * Gets the right X coordinate of the element (element X position + element width)
7890 * @param {Boolean} local True to get the local css position instead of page coordinate
7893 getRight : function(local){
7895 return this.getX() + this.getWidth();
7897 return (this.getLeft(true) + this.getWidth()) || 0;
7902 * Gets the top Y coordinate
7903 * @param {Boolean} local True to get the local css position instead of page coordinate
7906 getTop : function(local) {
7910 return parseInt(this.getStyle("top"), 10) || 0;
7915 * Gets the bottom Y coordinate of the element (element Y position + element height)
7916 * @param {Boolean} local True to get the local css position instead of page coordinate
7919 getBottom : function(local){
7921 return this.getY() + this.getHeight();
7923 return (this.getTop(true) + this.getHeight()) || 0;
7928 * Initializes positioning on this element. If a desired position is not passed, it will make the
7929 * the element positioned relative IF it is not already positioned.
7930 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7931 * @param {Number} zIndex (optional) The zIndex to apply
7932 * @param {Number} x (optional) Set the page X position
7933 * @param {Number} y (optional) Set the page Y position
7935 position : function(pos, zIndex, x, y){
7937 if(this.getStyle('position') == 'static'){
7938 this.setStyle('position', 'relative');
7941 this.setStyle("position", pos);
7944 this.setStyle("z-index", zIndex);
7946 if(x !== undefined && y !== undefined){
7948 }else if(x !== undefined){
7950 }else if(y !== undefined){
7956 * Clear positioning back to the default when the document was loaded
7957 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7958 * @return {Roo.Element} this
7960 clearPositioning : function(value){
7968 "position" : "static"
7974 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7975 * snapshot before performing an update and then restoring the element.
7978 getPositioning : function(){
7979 var l = this.getStyle("left");
7980 var t = this.getStyle("top");
7982 "position" : this.getStyle("position"),
7984 "right" : l ? "" : this.getStyle("right"),
7986 "bottom" : t ? "" : this.getStyle("bottom"),
7987 "z-index" : this.getStyle("z-index")
7992 * Gets the width of the border(s) for the specified side(s)
7993 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7994 * passing lr would get the border (l)eft width + the border (r)ight width.
7995 * @return {Number} The width of the sides passed added together
7997 getBorderWidth : function(side){
7998 return this.addStyles(side, El.borders);
8002 * Gets the width of the padding(s) for the specified side(s)
8003 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8004 * passing lr would get the padding (l)eft + the padding (r)ight.
8005 * @return {Number} The padding of the sides passed added together
8007 getPadding : function(side){
8008 return this.addStyles(side, El.paddings);
8012 * Set positioning with an object returned by getPositioning().
8013 * @param {Object} posCfg
8014 * @return {Roo.Element} this
8016 setPositioning : function(pc){
8017 this.applyStyles(pc);
8018 if(pc.right == "auto"){
8019 this.dom.style.right = "";
8021 if(pc.bottom == "auto"){
8022 this.dom.style.bottom = "";
8028 fixDisplay : function(){
8029 if(this.getStyle("display") == "none"){
8030 this.setStyle("visibility", "hidden");
8031 this.setStyle("display", this.originalDisplay); // first try reverting to default
8032 if(this.getStyle("display") == "none"){ // if that fails, default to block
8033 this.setStyle("display", "block");
8039 * Quick set left and top adding default units
8040 * @param {String} left The left CSS property value
8041 * @param {String} top The top CSS property value
8042 * @return {Roo.Element} this
8044 setLeftTop : function(left, top){
8045 this.dom.style.left = this.addUnits(left);
8046 this.dom.style.top = this.addUnits(top);
8051 * Move this element relative to its current position.
8052 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8053 * @param {Number} distance How far to move the element in pixels
8054 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8055 * @return {Roo.Element} this
8057 move : function(direction, distance, animate){
8058 var xy = this.getXY();
8059 direction = direction.toLowerCase();
8063 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8067 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8072 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8077 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8084 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8085 * @return {Roo.Element} this
8088 if(!this.isClipped){
8089 this.isClipped = true;
8090 this.originalClip = {
8091 "o": this.getStyle("overflow"),
8092 "x": this.getStyle("overflow-x"),
8093 "y": this.getStyle("overflow-y")
8095 this.setStyle("overflow", "hidden");
8096 this.setStyle("overflow-x", "hidden");
8097 this.setStyle("overflow-y", "hidden");
8103 * Return clipping (overflow) to original clipping before clip() was called
8104 * @return {Roo.Element} this
8106 unclip : function(){
8108 this.isClipped = false;
8109 var o = this.originalClip;
8110 if(o.o){this.setStyle("overflow", o.o);}
8111 if(o.x){this.setStyle("overflow-x", o.x);}
8112 if(o.y){this.setStyle("overflow-y", o.y);}
8119 * Gets the x,y coordinates specified by the anchor position on the element.
8120 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8121 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8122 * {width: (target width), height: (target height)} (defaults to the element's current size)
8123 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8124 * @return {Array} [x, y] An array containing the element's x and y coordinates
8126 getAnchorXY : function(anchor, local, s){
8127 //Passing a different size is useful for pre-calculating anchors,
8128 //especially for anchored animations that change the el size.
8130 var w, h, vp = false;
8133 if(d == document.body || d == document){
8135 w = D.getViewWidth(); h = D.getViewHeight();
8137 w = this.getWidth(); h = this.getHeight();
8140 w = s.width; h = s.height;
8142 var x = 0, y = 0, r = Math.round;
8143 switch((anchor || "tl").toLowerCase()){
8185 var sc = this.getScroll();
8186 return [x + sc.left, y + sc.top];
8188 //Add the element's offset xy
8189 var o = this.getXY();
8190 return [x+o[0], y+o[1]];
8194 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8195 * supported position values.
8196 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8197 * @param {String} position The position to align to.
8198 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8199 * @return {Array} [x, y]
8201 getAlignToXY : function(el, p, o){
8205 throw "Element.alignTo with an element that doesn't exist";
8207 var c = false; //constrain to viewport
8208 var p1 = "", p2 = "";
8215 }else if(p.indexOf("-") == -1){
8218 p = p.toLowerCase();
8219 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8221 throw "Element.alignTo with an invalid alignment " + p;
8223 p1 = m[1]; p2 = m[2]; c = !!m[3];
8225 //Subtract the aligned el's internal xy from the target's offset xy
8226 //plus custom offset to get the aligned el's new offset xy
8227 var a1 = this.getAnchorXY(p1, true);
8228 var a2 = el.getAnchorXY(p2, false);
8229 var x = a2[0] - a1[0] + o[0];
8230 var y = a2[1] - a1[1] + o[1];
8232 //constrain the aligned el to viewport if necessary
8233 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8234 // 5px of margin for ie
8235 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8237 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8238 //perpendicular to the vp border, allow the aligned el to slide on that border,
8239 //otherwise swap the aligned el to the opposite border of the target.
8240 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8241 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8242 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8243 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8246 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8247 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8249 if((x+w) > dw + scrollX){
8250 x = swapX ? r.left-w : dw+scrollX-w;
8253 x = swapX ? r.right : scrollX;
8255 if((y+h) > dh + scrollY){
8256 y = swapY ? r.top-h : dh+scrollY-h;
8259 y = swapY ? r.bottom : scrollY;
8266 getConstrainToXY : function(){
8267 var os = {top:0, left:0, bottom:0, right: 0};
8269 return function(el, local, offsets, proposedXY){
8271 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8273 var vw, vh, vx = 0, vy = 0;
8274 if(el.dom == document.body || el.dom == document){
8275 vw = Roo.lib.Dom.getViewWidth();
8276 vh = Roo.lib.Dom.getViewHeight();
8278 vw = el.dom.clientWidth;
8279 vh = el.dom.clientHeight;
8281 var vxy = el.getXY();
8287 var s = el.getScroll();
8289 vx += offsets.left + s.left;
8290 vy += offsets.top + s.top;
8292 vw -= offsets.right;
8293 vh -= offsets.bottom;
8298 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8299 var x = xy[0], y = xy[1];
8300 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8302 // only move it if it needs it
8305 // first validate right/bottom
8314 // then make sure top/left isn't negative
8323 return moved ? [x, y] : false;
8328 adjustForConstraints : function(xy, parent, offsets){
8329 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8333 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8334 * document it aligns it to the viewport.
8335 * The position parameter is optional, and can be specified in any one of the following formats:
8337 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8338 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8339 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8340 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8341 * <li><b>Two anchors</b>: If two values from the table below are passed separated by a dash, the first value is used as the
8342 * element's anchor point, and the second value is used as the target's anchor point.</li>
8344 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8345 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8346 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8347 * that specified in order to enforce the viewport constraints.
8348 * Following are all of the supported anchor positions:
8351 ----- -----------------------------
8352 tl The top left corner (default)
8353 t The center of the top edge
8354 tr The top right corner
8355 l The center of the left edge
8356 c In the center of the element
8357 r The center of the right edge
8358 bl The bottom left corner
8359 b The center of the bottom edge
8360 br The bottom right corner
8364 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8365 el.alignTo("other-el");
8367 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8368 el.alignTo("other-el", "tr?");
8370 // align the bottom right corner of el with the center left edge of other-el
8371 el.alignTo("other-el", "br-l?");
8373 // align the center of el with the bottom left corner of other-el and
8374 // adjust the x position by -6 pixels (and the y position by 0)
8375 el.alignTo("other-el", "c-bl", [-6, 0]);
8377 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8378 * @param {String} position The position to align to.
8379 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8380 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8381 * @return {Roo.Element} this
8383 alignTo : function(element, position, offsets, animate){
8384 var xy = this.getAlignToXY(element, position, offsets);
8385 this.setXY(xy, this.preanim(arguments, 3));
8390 * Anchors an element to another element and realigns it when the window is resized.
8391 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8392 * @param {String} position The position to align to.
8393 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8394 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8395 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8396 * is a number, it is used as the buffer delay (defaults to 50ms).
8397 * @param {Function} callback The function to call after the animation finishes
8398 * @return {Roo.Element} this
8400 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8401 var action = function(){
8402 this.alignTo(el, alignment, offsets, animate);
8403 Roo.callback(callback, this);
8405 Roo.EventManager.onWindowResize(action, this);
8406 var tm = typeof monitorScroll;
8407 if(tm != 'undefined'){
8408 Roo.EventManager.on(window, 'scroll', action, this,
8409 {buffer: tm == 'number' ? monitorScroll : 50});
8411 action.call(this); // align immediately
8415 * Clears any opacity settings from this element. Required in some cases for IE.
8416 * @return {Roo.Element} this
8418 clearOpacity : function(){
8419 if (window.ActiveXObject) {
8420 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8421 this.dom.style.filter = "";
8424 this.dom.style.opacity = "";
8425 this.dom.style["-moz-opacity"] = "";
8426 this.dom.style["-khtml-opacity"] = "";
8432 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8433 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8434 * @return {Roo.Element} this
8436 hide : function(animate){
8437 this.setVisible(false, this.preanim(arguments, 0));
8442 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8443 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8444 * @return {Roo.Element} this
8446 show : function(animate){
8447 this.setVisible(true, this.preanim(arguments, 0));
8452 * @private Test if size has a unit, otherwise appends the default
8454 addUnits : function(size){
8455 return Roo.Element.addUnits(size, this.defaultUnit);
8459 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8460 * @return {Roo.Element} this
8462 beginMeasure : function(){
8464 if(el.offsetWidth || el.offsetHeight){
8465 return this; // offsets work already
8468 var p = this.dom, b = document.body; // start with this element
8469 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8470 var pe = Roo.get(p);
8471 if(pe.getStyle('display') == 'none'){
8472 changed.push({el: p, visibility: pe.getStyle("visibility")});
8473 p.style.visibility = "hidden";
8474 p.style.display = "block";
8478 this._measureChanged = changed;
8484 * Restores displays to before beginMeasure was called
8485 * @return {Roo.Element} this
8487 endMeasure : function(){
8488 var changed = this._measureChanged;
8490 for(var i = 0, len = changed.length; i < len; i++) {
8492 r.el.style.visibility = r.visibility;
8493 r.el.style.display = "none";
8495 this._measureChanged = null;
8501 * Update the innerHTML of this element, optionally searching for and processing scripts
8502 * @param {String} html The new HTML
8503 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8504 * @param {Function} callback For async script loading you can be noticed when the update completes
8505 * @return {Roo.Element} this
8507 update : function(html, loadScripts, callback){
8508 if(typeof html == "undefined"){
8511 if(loadScripts !== true){
8512 this.dom.innerHTML = html;
8513 if(typeof callback == "function"){
8521 html += '<span id="' + id + '"></span>';
8523 E.onAvailable(id, function(){
8524 var hd = document.getElementsByTagName("head")[0];
8525 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8526 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8527 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8530 while(match = re.exec(html)){
8531 var attrs = match[1];
8532 var srcMatch = attrs ? attrs.match(srcRe) : false;
8533 if(srcMatch && srcMatch[2]){
8534 var s = document.createElement("script");
8535 s.src = srcMatch[2];
8536 var typeMatch = attrs.match(typeRe);
8537 if(typeMatch && typeMatch[2]){
8538 s.type = typeMatch[2];
8541 }else if(match[2] && match[2].length > 0){
8542 if(window.execScript) {
8543 window.execScript(match[2]);
8551 window.eval(match[2]);
8555 var el = document.getElementById(id);
8556 if(el){el.parentNode.removeChild(el);}
8557 if(typeof callback == "function"){
8561 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8566 * Direct access to the UpdateManager update() method (takes the same parameters).
8567 * @param {String/Function} url The url for this request or a function to call to get the url
8568 * @param {String/Object} params (optional) The parameters to pass as either a url encoded string "param1=1&param2=2" or an object {param1: 1, param2: 2}
8569 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8570 * @param {Boolean} discardUrl (optional) By default when you execute an update the defaultUrl is changed to the last used url. If true, it will not store the url.
8571 * @return {Roo.Element} this
8574 var um = this.getUpdateManager();
8575 um.update.apply(um, arguments);
8580 * Gets this element's UpdateManager
8581 * @return {Roo.UpdateManager} The UpdateManager
8583 getUpdateManager : function(){
8584 if(!this.updateManager){
8585 this.updateManager = new Roo.UpdateManager(this);
8587 return this.updateManager;
8591 * Disables text selection for this element (normalized across browsers)
8592 * @return {Roo.Element} this
8594 unselectable : function(){
8595 this.dom.unselectable = "on";
8596 this.swallowEvent("selectstart", true);
8597 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8598 this.addClass("x-unselectable");
8603 * Calculates the x, y to center this element on the screen
8604 * @return {Array} The x, y values [x, y]
8606 getCenterXY : function(){
8607 return this.getAlignToXY(document, 'c-c');
8611 * Centers the Element in either the viewport, or another Element.
8612 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8614 center : function(centerIn){
8615 this.alignTo(centerIn || document, 'c-c');
8620 * Tests various css rules/browsers to determine if this element uses a border box
8623 isBorderBox : function(){
8624 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8628 * Return a box {x, y, width, height} that can be used to set another elements
8629 * size/location to match this element.
8630 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8631 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8632 * @return {Object} box An object in the format {x, y, width, height}
8634 getBox : function(contentBox, local){
8639 var left = parseInt(this.getStyle("left"), 10) || 0;
8640 var top = parseInt(this.getStyle("top"), 10) || 0;
8643 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8645 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8647 var l = this.getBorderWidth("l")+this.getPadding("l");
8648 var r = this.getBorderWidth("r")+this.getPadding("r");
8649 var t = this.getBorderWidth("t")+this.getPadding("t");
8650 var b = this.getBorderWidth("b")+this.getPadding("b");
8651 bx = {x: xy[0]+l, y: xy[1]+t, 0: xy[0]+l, 1: xy[1]+t, width: w-(l+r), height: h-(t+b)};
8653 bx.right = bx.x + bx.width;
8654 bx.bottom = bx.y + bx.height;
8659 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8660 for more information about the sides.
8661 * @param {String} sides
8664 getFrameWidth : function(sides, onlyContentBox){
8665 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8669 * Sets the element's box. Use getBox() on another element to get a box obj. If animate is true then width, height, x and y will be animated concurrently.
8670 * @param {Object} box The box to fill {x, y, width, height}
8671 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8672 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8673 * @return {Roo.Element} this
8675 setBox : function(box, adjust, animate){
8676 var w = box.width, h = box.height;
8677 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8678 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8679 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8681 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8686 * Forces the browser to repaint this element
8687 * @return {Roo.Element} this
8689 repaint : function(){
8691 this.addClass("x-repaint");
8692 setTimeout(function(){
8693 Roo.get(dom).removeClass("x-repaint");
8699 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8700 * then it returns the calculated width of the sides (see getPadding)
8701 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8702 * @return {Object/Number}
8704 getMargins : function(side){
8707 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8708 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8709 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8710 right: parseInt(this.getStyle("margin-right"), 10) || 0
8713 return this.addStyles(side, El.margins);
8718 addStyles : function(sides, styles){
8720 for(var i = 0, len = sides.length; i < len; i++){
8721 v = this.getStyle(styles[sides.charAt(i)]);
8723 w = parseInt(v, 10);
8731 * Creates a proxy element of this element
8732 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8733 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8734 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8735 * @return {Roo.Element} The new proxy element
8737 createProxy : function(config, renderTo, matchBox){
8739 renderTo = Roo.getDom(renderTo);
8741 renderTo = document.body;
8743 config = typeof config == "object" ?
8744 config : {tag : "div", cls: config};
8745 var proxy = Roo.DomHelper.append(renderTo, config, true);
8747 proxy.setBox(this.getBox());
8753 * Puts a mask over this element to disable user interaction. Requires core.css.
8754 * This method can only be applied to elements which accept child nodes.
8755 * @param {String} msg (optional) A message to display in the mask
8756 * @param {String} msgCls (optional) A css class to apply to the msg element
8757 * @return {Element} The mask element
8759 mask : function(msg, msgCls){
8760 if(this.getStyle("position") == "static"){
8761 this.setStyle("position", "relative");
8764 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8766 this.addClass("x-masked");
8767 this._mask.setDisplayed(true);
8768 if(typeof msg == 'string'){
8770 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8772 var mm = this._maskMsg;
8773 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8774 mm.dom.firstChild.innerHTML = msg;
8775 mm.setDisplayed(true);
8778 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8779 this._mask.setHeight(this.getHeight());
8785 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8786 * it is cached for reuse.
8788 unmask : function(removeEl){
8790 if(removeEl === true){
8791 this._mask.remove();
8794 this._maskMsg.remove();
8795 delete this._maskMsg;
8798 this._mask.setDisplayed(false);
8800 this._maskMsg.setDisplayed(false);
8804 this.removeClass("x-masked");
8808 * Returns true if this element is masked
8811 isMasked : function(){
8812 return this._mask && this._mask.isVisible();
8816 * Creates an iframe shim for this element to keep selects and other windowed objects from
8818 * @return {Roo.Element} The new shim element
8820 createShim : function(){
8821 var el = document.createElement('iframe');
8822 el.frameBorder = 'no';
8823 el.className = 'roo-shim';
8824 if(Roo.isIE && Roo.isSecure){
8825 el.src = Roo.SSL_SECURE_URL;
8827 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8828 shim.autoBoxAdjust = false;
8833 * Removes this element from the DOM and deletes it from the cache
8835 remove : function(){
8836 if(this.dom.parentNode){
8837 this.dom.parentNode.removeChild(this.dom);
8839 delete El.cache[this.dom.id];
8843 * Sets up event handlers to add and remove a css class when the mouse is over this element
8844 * @param {String} className
8845 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8846 * mouseout events for children elements
8847 * @return {Roo.Element} this
8849 addClassOnOver : function(className, preventFlicker){
8850 this.on("mouseover", function(){
8851 Roo.fly(this, '_internal').addClass(className);
8853 var removeFn = function(e){
8854 if(preventFlicker !== true || !e.within(this, true)){
8855 Roo.fly(this, '_internal').removeClass(className);
8858 this.on("mouseout", removeFn, this.dom);
8863 * Sets up event handlers to add and remove a css class when this element has the focus
8864 * @param {String} className
8865 * @return {Roo.Element} this
8867 addClassOnFocus : function(className){
8868 this.on("focus", function(){
8869 Roo.fly(this, '_internal').addClass(className);
8871 this.on("blur", function(){
8872 Roo.fly(this, '_internal').removeClass(className);
8877 * Sets up event handlers to add and remove a css class when the mouse is down and then up on this element (a click effect)
8878 * @param {String} className
8879 * @return {Roo.Element} this
8881 addClassOnClick : function(className){
8883 this.on("mousedown", function(){
8884 Roo.fly(dom, '_internal').addClass(className);
8885 var d = Roo.get(document);
8886 var fn = function(){
8887 Roo.fly(dom, '_internal').removeClass(className);
8888 d.removeListener("mouseup", fn);
8890 d.on("mouseup", fn);
8896 * Stops the specified event from bubbling and optionally prevents the default action
8897 * @param {String} eventName
8898 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8899 * @return {Roo.Element} this
8901 swallowEvent : function(eventName, preventDefault){
8902 var fn = function(e){
8903 e.stopPropagation();
8908 if(eventName instanceof Array){
8909 for(var i = 0, len = eventName.length; i < len; i++){
8910 this.on(eventName[i], fn);
8914 this.on(eventName, fn);
8921 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8924 * Sizes this element to its parent element's dimensions performing
8925 * neccessary box adjustments.
8926 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8927 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8928 * @return {Roo.Element} this
8930 fitToParent : function(monitorResize, targetParent) {
8931 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8932 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8933 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8936 var p = Roo.get(targetParent || this.dom.parentNode);
8937 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8938 if (monitorResize === true) {
8939 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8940 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8946 * Gets the next sibling, skipping text nodes
8947 * @return {HTMLElement} The next sibling or null
8949 getNextSibling : function(){
8950 var n = this.dom.nextSibling;
8951 while(n && n.nodeType != 1){
8958 * Gets the previous sibling, skipping text nodes
8959 * @return {HTMLElement} The previous sibling or null
8961 getPrevSibling : function(){
8962 var n = this.dom.previousSibling;
8963 while(n && n.nodeType != 1){
8964 n = n.previousSibling;
8971 * Appends the passed element(s) to this element
8972 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8973 * @return {Roo.Element} this
8975 appendChild: function(el){
8982 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8983 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8984 * automatically generated with the specified attributes.
8985 * @param {HTMLElement} insertBefore (optional) a child element of this element
8986 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8987 * @return {Roo.Element} The new child element
8989 createChild: function(config, insertBefore, returnDom){
8990 config = config || {tag:'div'};
8992 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8994 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8998 * Appends this element to the passed element
8999 * @param {String/HTMLElement/Element} el The new parent element
9000 * @return {Roo.Element} this
9002 appendTo: function(el){
9003 el = Roo.getDom(el);
9004 el.appendChild(this.dom);
9009 * Inserts this element before the passed element in the DOM
9010 * @param {String/HTMLElement/Element} el The element to insert before
9011 * @return {Roo.Element} this
9013 insertBefore: function(el){
9014 el = Roo.getDom(el);
9015 el.parentNode.insertBefore(this.dom, el);
9020 * Inserts this element after the passed element in the DOM
9021 * @param {String/HTMLElement/Element} el The element to insert after
9022 * @return {Roo.Element} this
9024 insertAfter: function(el){
9025 el = Roo.getDom(el);
9026 el.parentNode.insertBefore(this.dom, el.nextSibling);
9031 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9032 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9033 * @return {Roo.Element} The new child
9035 insertFirst: function(el, returnDom){
9037 if(typeof el == 'object' && !el.nodeType){ // dh config
9038 return this.createChild(el, this.dom.firstChild, returnDom);
9040 el = Roo.getDom(el);
9041 this.dom.insertBefore(el, this.dom.firstChild);
9042 return !returnDom ? Roo.get(el) : el;
9047 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9048 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9049 * @param {String} where (optional) 'before' or 'after' defaults to before
9050 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9051 * @return {Roo.Element} the inserted Element
9053 insertSibling: function(el, where, returnDom){
9054 where = where ? where.toLowerCase() : 'before';
9056 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9058 if(typeof el == 'object' && !el.nodeType){ // dh config
9059 if(where == 'after' && !this.dom.nextSibling){
9060 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9062 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9066 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9067 where == 'before' ? this.dom : this.dom.nextSibling);
9076 * Creates and wraps this element with another element
9077 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9078 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9079 * @return {HTMLElement/Element} The newly created wrapper element
9081 wrap: function(config, returnDom){
9083 config = {tag: "div"};
9085 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9086 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9091 * Replaces the passed element with this element
9092 * @param {String/HTMLElement/Element} el The element to replace
9093 * @return {Roo.Element} this
9095 replace: function(el){
9097 this.insertBefore(el);
9103 * Inserts an html fragment into this element
9104 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9105 * @param {String} html The HTML fragment
9106 * @param {Boolean} returnEl True to return an Roo.Element
9107 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9109 insertHtml : function(where, html, returnEl){
9110 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9111 return returnEl ? Roo.get(el) : el;
9115 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9116 * @param {Object} o The object with the attributes
9117 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9118 * @return {Roo.Element} this
9120 set : function(o, useSet){
9122 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9124 if(attr == "style" || typeof o[attr] == "function") continue;
9126 el.className = o["cls"];
9128 if(useSet) el.setAttribute(attr, o[attr]);
9129 else el[attr] = o[attr];
9133 Roo.DomHelper.applyStyles(el, o.style);
9139 * Convenience method for constructing a KeyMap
9140 * @param {Number/Array/Object/String} key Either a string with the keys to listen for, the numeric key code, array of key codes or an object with the following options:
9141 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9142 * @param {Function} fn The function to call
9143 * @param {Object} scope (optional) The scope of the function
9144 * @return {Roo.KeyMap} The KeyMap created
9146 addKeyListener : function(key, fn, scope){
9148 if(typeof key != "object" || key instanceof Array){
9164 return new Roo.KeyMap(this, config);
9168 * Creates a KeyMap for this element
9169 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9170 * @return {Roo.KeyMap} The KeyMap created
9172 addKeyMap : function(config){
9173 return new Roo.KeyMap(this, config);
9177 * Returns true if this element is scrollable.
9180 isScrollable : function(){
9182 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9186 * Scrolls this element the specified scroll point. It does NOT do bounds checking so if you scroll to a weird value it will try to do it. For auto bounds checking, use scroll().
9187 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9188 * @param {Number} value The new scroll value
9189 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9190 * @return {Element} this
9193 scrollTo : function(side, value, animate){
9194 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9196 this.dom[prop] = value;
9198 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9199 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9205 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9206 * within this element's scrollable range.
9207 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9208 * @param {Number} distance How far to scroll the element in pixels
9209 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9210 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9211 * was scrolled as far as it could go.
9213 scroll : function(direction, distance, animate){
9214 if(!this.isScrollable()){
9218 var l = el.scrollLeft, t = el.scrollTop;
9219 var w = el.scrollWidth, h = el.scrollHeight;
9220 var cw = el.clientWidth, ch = el.clientHeight;
9221 direction = direction.toLowerCase();
9222 var scrolled = false;
9223 var a = this.preanim(arguments, 2);
9228 var v = Math.min(l + distance, w-cw);
9229 this.scrollTo("left", v, a);
9236 var v = Math.max(l - distance, 0);
9237 this.scrollTo("left", v, a);
9245 var v = Math.max(t - distance, 0);
9246 this.scrollTo("top", v, a);
9254 var v = Math.min(t + distance, h-ch);
9255 this.scrollTo("top", v, a);
9264 * Translates the passed page coordinates into left/top css values for this element
9265 * @param {Number/Array} x The page x or an array containing [x, y]
9266 * @param {Number} y The page y
9267 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9269 translatePoints : function(x, y){
9270 if(typeof x == 'object' || x instanceof Array){
9273 var p = this.getStyle('position');
9274 var o = this.getXY();
9276 var l = parseInt(this.getStyle('left'), 10);
9277 var t = parseInt(this.getStyle('top'), 10);
9280 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9283 t = (p == "relative") ? 0 : this.dom.offsetTop;
9286 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9290 * Returns the current scroll position of the element.
9291 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9293 getScroll : function(){
9294 var d = this.dom, doc = document;
9295 if(d == doc || d == doc.body){
9296 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9297 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9298 return {left: l, top: t};
9300 return {left: d.scrollLeft, top: d.scrollTop};
9305 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9306 * are convert to standard 6 digit hex color.
9307 * @param {String} attr The css attribute
9308 * @param {String} defaultValue The default value to use when a valid color isn't found
9309 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9312 getColor : function(attr, defaultValue, prefix){
9313 var v = this.getStyle(attr);
9314 if(!v || v == "transparent" || v == "inherit") {
9315 return defaultValue;
9317 var color = typeof prefix == "undefined" ? "#" : prefix;
9318 if(v.substr(0, 4) == "rgb("){
9319 var rvs = v.slice(4, v.length -1).split(",");
9320 for(var i = 0; i < 3; i++){
9321 var h = parseInt(rvs[i]).toString(16);
9328 if(v.substr(0, 1) == "#"){
9330 for(var i = 1; i < 4; i++){
9331 var c = v.charAt(i);
9334 }else if(v.length == 7){
9335 color += v.substr(1);
9339 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9343 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9344 * gradient background, rounded corners and a 4-way shadow.
9345 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9346 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9347 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9348 * @return {Roo.Element} this
9350 boxWrap : function(cls){
9351 cls = cls || 'x-box';
9352 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9353 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9358 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9359 * @param {String} namespace The namespace in which to look for the attribute
9360 * @param {String} name The attribute name
9361 * @return {String} The attribute value
9363 getAttributeNS : Roo.isIE ? function(ns, name){
9365 var type = typeof d[ns+":"+name];
9366 if(type != 'undefined' && type != 'unknown'){
9367 return d[ns+":"+name];
9370 } : function(ns, name){
9372 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9376 var ep = El.prototype;
9379 * Appends an event handler (Shorthand for addListener)
9380 * @param {String} eventName The type of event to append
9381 * @param {Function} fn The method the event invokes
9382 * @param {Object} scope (optional) The scope (this object) of the fn
9383 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9386 ep.on = ep.addListener;
9388 ep.mon = ep.addListener;
9391 * Removes an event handler from this element (shorthand for removeListener)
9392 * @param {String} eventName the type of event to remove
9393 * @param {Function} fn the method the event invokes
9394 * @return {Roo.Element} this
9397 ep.un = ep.removeListener;
9400 * true to automatically adjust width and height settings for box-model issues (default to true)
9402 ep.autoBoxAdjust = true;
9405 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9408 El.addUnits = function(v, defaultUnit){
9409 if(v === "" || v == "auto"){
9412 if(v === undefined){
9415 if(typeof v == "number" || !El.unitPattern.test(v)){
9416 return v + (defaultUnit || 'px');
9421 // special markup used throughout Roo when box wrapping elements
9422 El.boxMarkup = '<div class="{0}-tl"><div class="{0}-tr"><div class="{0}-tc"></div></div></div><div class="{0}-ml"><div class="{0}-mr"><div class="{0}-mc"></div></div></div><div class="{0}-bl"><div class="{0}-br"><div class="{0}-bc"></div></div></div>';
9424 * Visibility mode constant - Use visibility to hide element
9430 * Visibility mode constant - Use display to hide element
9436 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9437 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9438 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9450 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9451 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9452 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9453 * @return {Element} The Element object
9456 El.get = function(el){
9458 if(!el){ return null; }
9459 if(typeof el == "string"){ // element id
9460 if(!(elm = document.getElementById(el))){
9463 if(ex = El.cache[el]){
9466 ex = El.cache[el] = new El(elm);
9469 }else if(el.tagName){ // dom element
9473 if(ex = El.cache[id]){
9476 ex = El.cache[id] = new El(el);
9479 }else if(el instanceof El){
9481 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9482 // catch case where it hasn't been appended
9483 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9486 }else if(el.isComposite){
9488 }else if(el instanceof Array){
9489 return El.select(el);
9490 }else if(el == document){
9491 // create a bogus element object representing the document object
9493 var f = function(){};
9494 f.prototype = El.prototype;
9496 docEl.dom = document;
9504 El.uncache = function(el){
9505 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9507 delete El.cache[a[i].id || a[i]];
9513 // Garbage collection - uncache elements/purge listeners on orphaned elements
9514 // so we don't hold a reference and cause the browser to retain them
9515 El.garbageCollect = function(){
9516 if(!Roo.enableGarbageCollector){
9517 clearInterval(El.collectorThread);
9520 for(var eid in El.cache){
9521 var el = El.cache[eid], d = el.dom;
9522 // -------------------------------------------------------
9523 // Determining what is garbage:
9524 // -------------------------------------------------------
9526 // dom node is null, definitely garbage
9527 // -------------------------------------------------------
9529 // no parentNode == direct orphan, definitely garbage
9530 // -------------------------------------------------------
9531 // !d.offsetParent && !document.getElementById(eid)
9532 // display none elements have no offsetParent so we will
9533 // also try to look it up by it's id. However, check
9534 // offsetParent first so we don't do unneeded lookups.
9535 // This enables collection of elements that are not orphans
9536 // directly, but somewhere up the line they have an orphan
9538 // -------------------------------------------------------
9539 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9540 delete El.cache[eid];
9541 if(d && Roo.enableListenerCollection){
9547 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9551 El.Flyweight = function(dom){
9554 El.Flyweight.prototype = El.prototype;
9556 El._flyweights = {};
9558 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9559 * the dom node can be overwritten by other code.
9560 * @param {String/HTMLElement} el The dom node or id
9561 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9562 * prevent conflicts (e.g. internally Roo uses "_internal")
9564 * @return {Element} The shared Element object
9566 El.fly = function(el, named){
9567 named = named || '_global';
9568 el = Roo.getDom(el);
9572 if(!El._flyweights[named]){
9573 El._flyweights[named] = new El.Flyweight();
9575 El._flyweights[named].dom = el;
9576 return El._flyweights[named];
9580 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9581 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9582 * Shorthand of {@link Roo.Element#get}
9583 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9584 * @return {Element} The Element object
9590 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9591 * the dom node can be overwritten by other code.
9592 * Shorthand of {@link Roo.Element#fly}
9593 * @param {String/HTMLElement} el The dom node or id
9594 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9595 * prevent conflicts (e.g. internally Roo uses "_internal")
9597 * @return {Element} The shared Element object
9603 // speedy lookup for elements never to box adjust
9604 var noBoxAdjust = Roo.isStrict ? {
9607 input:1, select:1, textarea:1
9609 if(Roo.isIE || Roo.isGecko){
9610 noBoxAdjust['button'] = 1;
9614 Roo.EventManager.on(window, 'unload', function(){
9616 delete El._flyweights;
9624 Roo.Element.selectorFunction = Roo.DomQuery.select;
9627 Roo.Element.select = function(selector, unique, root){
9629 if(typeof selector == "string"){
9630 els = Roo.Element.selectorFunction(selector, root);
9631 }else if(selector.length !== undefined){
9634 throw "Invalid selector";
9636 if(unique === true){
9637 return new Roo.CompositeElement(els);
9639 return new Roo.CompositeElementLite(els);
9643 * Selects elements based on the passed CSS selector to enable working on them as 1.
9644 * @param {String/Array} selector The CSS selector or an array of elements
9645 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9646 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9647 * @return {CompositeElementLite/CompositeElement}
9651 Roo.select = Roo.Element.select;