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 : element(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;
9668 * Ext JS Library 1.1.1
9669 * Copyright(c) 2006-2007, Ext JS, LLC.
9671 * Originally Released Under LGPL - original licence link has changed is not relivant.
9674 * <script type="text/javascript">
9679 //Notifies Element that fx methods are available
9680 Roo.enableFx = true;
9684 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9685 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9686 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9687 * Element effects to work.</p><br/>
9689 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9690 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9691 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9692 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9693 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9694 * expected results and should be done with care.</p><br/>
9696 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9697 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9700 ----- -----------------------------
9701 tl The top left corner
9702 t The center of the top edge
9703 tr The top right corner
9704 l The center of the left edge
9705 r The center of the right edge
9706 bl The bottom left corner
9707 b The center of the bottom edge
9708 br The bottom right corner
9710 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9711 * below are common options that can be passed to any Fx method.</b>
9712 * @cfg {Function} callback A function called when the effect is finished
9713 * @cfg {Object} scope The scope of the effect function
9714 * @cfg {String} easing A valid Easing value for the effect
9715 * @cfg {String} afterCls A css class to apply after the effect
9716 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9717 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9718 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9719 * effects that end with the element being visually hidden, ignored otherwise)
9720 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9721 * a function which returns such a specification that will be applied to the Element after the effect finishes
9722 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9723 * @cfg {Boolean} concurrent Whether to allow subsequently-queued effects to run at the same time as the current effect, or to ensure that they run in sequence
9724 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9728 * Slides the element into view. An anchor point can be optionally passed to set the point of
9729 * origin for the slide effect. This function automatically handles wrapping the element with
9730 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9733 // default: slide the element in from the top
9736 // custom: slide the element in from the right with a 2-second duration
9737 el.slideIn('r', { duration: 2 });
9739 // common config options shown with default values
9745 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9746 * @param {Object} options (optional) Object literal with any of the Fx config options
9747 * @return {Roo.Element} The Element
9749 slideIn : function(anchor, o){
9750 var el = this.getFxEl();
9753 el.queueFx(o, function(){
9755 anchor = anchor || "t";
9757 // fix display to visibility
9760 // restore values after effect
9761 var r = this.getFxRestore();
9762 var b = this.getBox();
9763 // fixed size for slide
9767 var wrap = this.fxWrap(r.pos, o, "hidden");
9769 var st = this.dom.style;
9770 st.visibility = "visible";
9771 st.position = "absolute";
9773 // clear out temp styles after slide and unwrap
9774 var after = function(){
9775 el.fxUnwrap(wrap, r.pos, o);
9777 st.height = r.height;
9780 // time to calc the positions
9781 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9783 switch(anchor.toLowerCase()){
9785 wrap.setSize(b.width, 0);
9786 st.left = st.bottom = "0";
9790 wrap.setSize(0, b.height);
9791 st.right = st.top = "0";
9795 wrap.setSize(0, b.height);
9797 st.left = st.top = "0";
9798 a = {width: bw, points: pt};
9801 wrap.setSize(b.width, 0);
9802 wrap.setY(b.bottom);
9803 st.left = st.top = "0";
9804 a = {height: bh, points: pt};
9808 st.right = st.bottom = "0";
9809 a = {width: bw, height: bh};
9813 wrap.setY(b.y+b.height);
9814 st.right = st.top = "0";
9815 a = {width: bw, height: bh, points: pt};
9819 wrap.setXY([b.right, b.bottom]);
9820 st.left = st.top = "0";
9821 a = {width: bw, height: bh, points: pt};
9825 wrap.setX(b.x+b.width);
9826 st.left = st.bottom = "0";
9827 a = {width: bw, height: bh, points: pt};
9830 this.dom.style.visibility = "visible";
9833 arguments.callee.anim = wrap.fxanim(a,
9843 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9844 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9845 * 'hidden') but block elements will still take up space in the document. The element must be removed
9846 * from the DOM using the 'remove' config option if desired. This function automatically handles
9847 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9850 // default: slide the element out to the top
9853 // custom: slide the element out to the right with a 2-second duration
9854 el.slideOut('r', { duration: 2 });
9856 // common config options shown with default values
9864 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9865 * @param {Object} options (optional) Object literal with any of the Fx config options
9866 * @return {Roo.Element} The Element
9868 slideOut : function(anchor, o){
9869 var el = this.getFxEl();
9872 el.queueFx(o, function(){
9874 anchor = anchor || "t";
9876 // restore values after effect
9877 var r = this.getFxRestore();
9879 var b = this.getBox();
9880 // fixed size for slide
9884 var wrap = this.fxWrap(r.pos, o, "visible");
9886 var st = this.dom.style;
9887 st.visibility = "visible";
9888 st.position = "absolute";
9892 var after = function(){
9894 el.setDisplayed(false);
9899 el.fxUnwrap(wrap, r.pos, o);
9902 st.height = r.height;
9907 var a, zero = {to: 0};
9908 switch(anchor.toLowerCase()){
9910 st.left = st.bottom = "0";
9914 st.right = st.top = "0";
9918 st.left = st.top = "0";
9919 a = {width: zero, points: {to:[b.right, b.y]}};
9922 st.left = st.top = "0";
9923 a = {height: zero, points: {to:[b.x, b.bottom]}};
9926 st.right = st.bottom = "0";
9927 a = {width: zero, height: zero};
9930 st.right = st.top = "0";
9931 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9934 st.left = st.top = "0";
9935 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9938 st.left = st.bottom = "0";
9939 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9943 arguments.callee.anim = wrap.fxanim(a,
9953 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
9954 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
9955 * The element must be removed from the DOM using the 'remove' config option if desired.
9961 // common config options shown with default values
9969 * @param {Object} options (optional) Object literal with any of the Fx config options
9970 * @return {Roo.Element} The Element
9973 var el = this.getFxEl();
9976 el.queueFx(o, function(){
9977 this.clearOpacity();
9980 // restore values after effect
9981 var r = this.getFxRestore();
9982 var st = this.dom.style;
9984 var after = function(){
9986 el.setDisplayed(false);
9993 el.setPositioning(r.pos);
9995 st.height = r.height;
10000 var width = this.getWidth();
10001 var height = this.getHeight();
10003 arguments.callee.anim = this.fxanim({
10004 width : {to: this.adjustWidth(width * 2)},
10005 height : {to: this.adjustHeight(height * 2)},
10006 points : {by: [-(width * .5), -(height * .5)]},
10008 fontSize: {to:200, unit: "%"}
10019 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10020 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10021 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10027 // all config options shown with default values
10035 * @param {Object} options (optional) Object literal with any of the Fx config options
10036 * @return {Roo.Element} The Element
10038 switchOff : function(o){
10039 var el = this.getFxEl();
10042 el.queueFx(o, function(){
10043 this.clearOpacity();
10046 // restore values after effect
10047 var r = this.getFxRestore();
10048 var st = this.dom.style;
10050 var after = function(){
10052 el.setDisplayed(false);
10058 el.setPositioning(r.pos);
10059 st.width = r.width;
10060 st.height = r.height;
10065 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10066 this.clearOpacity();
10070 points:{by:[0, this.getHeight() * .5]}
10071 }, o, 'motion', 0.3, 'easeIn', after);
10072 }).defer(100, this);
10079 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10080 * changed using the "attr" config option) and then fading back to the original color. If no original
10081 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10084 // default: highlight background to yellow
10087 // custom: highlight foreground text to blue for 2 seconds
10088 el.highlight("0000ff", { attr: 'color', duration: 2 });
10090 // common config options shown with default values
10091 el.highlight("ffff9c", {
10092 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10093 endColor: (current color) or "ffffff",
10098 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10099 * @param {Object} options (optional) Object literal with any of the Fx config options
10100 * @return {Roo.Element} The Element
10102 highlight : function(color, o){
10103 var el = this.getFxEl();
10106 el.queueFx(o, function(){
10107 color = color || "ffff9c";
10108 attr = o.attr || "backgroundColor";
10110 this.clearOpacity();
10113 var origColor = this.getColor(attr);
10114 var restoreColor = this.dom.style[attr];
10115 endColor = (o.endColor || origColor) || "ffffff";
10117 var after = function(){
10118 el.dom.style[attr] = restoreColor;
10123 a[attr] = {from: color, to: endColor};
10124 arguments.callee.anim = this.fxanim(a,
10134 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10137 // default: a single light blue ripple
10140 // custom: 3 red ripples lasting 3 seconds total
10141 el.frame("ff0000", 3, { duration: 3 });
10143 // common config options shown with default values
10144 el.frame("C3DAF9", 1, {
10145 duration: 1 //duration of entire animation (not each individual ripple)
10146 // Note: Easing is not configurable and will be ignored if included
10149 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10150 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10151 * @param {Object} options (optional) Object literal with any of the Fx config options
10152 * @return {Roo.Element} The Element
10154 frame : function(color, count, o){
10155 var el = this.getFxEl();
10158 el.queueFx(o, function(){
10159 color = color || "#C3DAF9";
10160 if(color.length == 6){
10161 color = "#" + color;
10163 count = count || 1;
10164 duration = o.duration || 1;
10167 var b = this.getBox();
10168 var animFn = function(){
10169 var proxy = this.createProxy({
10172 visbility:"hidden",
10173 position:"absolute",
10174 "z-index":"35000", // yee haw
10175 border:"0px solid " + color
10178 var scale = Roo.isBorderBox ? 2 : 1;
10180 top:{from:b.y, to:b.y - 20},
10181 left:{from:b.x, to:b.x - 20},
10182 borderWidth:{from:0, to:10},
10183 opacity:{from:1, to:0},
10184 height:{from:b.height, to:(b.height + (20*scale))},
10185 width:{from:b.width, to:(b.width + (20*scale))}
10186 }, duration, function(){
10190 animFn.defer((duration/2)*1000, this);
10201 * Creates a pause before any subsequent queued effects begin. If there are
10202 * no effects queued after the pause it will have no effect.
10207 * @param {Number} seconds The length of time to pause (in seconds)
10208 * @return {Roo.Element} The Element
10210 pause : function(seconds){
10211 var el = this.getFxEl();
10214 el.queueFx(o, function(){
10215 setTimeout(function(){
10217 }, seconds * 1000);
10223 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10224 * using the "endOpacity" config option.
10227 // default: fade in from opacity 0 to 100%
10230 // custom: fade in from opacity 0 to 75% over 2 seconds
10231 el.fadeIn({ endOpacity: .75, duration: 2});
10233 // common config options shown with default values
10235 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10240 * @param {Object} options (optional) Object literal with any of the Fx config options
10241 * @return {Roo.Element} The Element
10243 fadeIn : function(o){
10244 var el = this.getFxEl();
10246 el.queueFx(o, function(){
10247 this.setOpacity(0);
10249 this.dom.style.visibility = 'visible';
10250 var to = o.endOpacity || 1;
10251 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10252 o, null, .5, "easeOut", function(){
10254 this.clearOpacity();
10263 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10264 * using the "endOpacity" config option.
10267 // default: fade out from the element's current opacity to 0
10270 // custom: fade out from the element's current opacity to 25% over 2 seconds
10271 el.fadeOut({ endOpacity: .25, duration: 2});
10273 // common config options shown with default values
10275 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10282 * @param {Object} options (optional) Object literal with any of the Fx config options
10283 * @return {Roo.Element} The Element
10285 fadeOut : function(o){
10286 var el = this.getFxEl();
10288 el.queueFx(o, function(){
10289 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10290 o, null, .5, "easeOut", function(){
10291 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10292 this.dom.style.display = "none";
10294 this.dom.style.visibility = "hidden";
10296 this.clearOpacity();
10304 * Animates the transition of an element's dimensions from a starting height/width
10305 * to an ending height/width.
10308 // change height and width to 100x100 pixels
10309 el.scale(100, 100);
10311 // common config options shown with default values. The height and width will default to
10312 // the element's existing values if passed as null.
10315 [element's height], {
10320 * @param {Number} width The new width (pass undefined to keep the original width)
10321 * @param {Number} height The new height (pass undefined to keep the original height)
10322 * @param {Object} options (optional) Object literal with any of the Fx config options
10323 * @return {Roo.Element} The Element
10325 scale : function(w, h, o){
10326 this.shift(Roo.apply({}, o, {
10334 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10335 * Any of these properties not specified in the config object will not be changed. This effect
10336 * requires that at least one new dimension, position or opacity setting must be passed in on
10337 * the config object in order for the function to have any effect.
10340 // slide the element horizontally to x position 200 while changing the height and opacity
10341 el.shift({ x: 200, height: 50, opacity: .8 });
10343 // common config options shown with default values.
10345 width: [element's width],
10346 height: [element's height],
10347 x: [element's x position],
10348 y: [element's y position],
10349 opacity: [element's opacity],
10354 * @param {Object} options Object literal with any of the Fx config options
10355 * @return {Roo.Element} The Element
10357 shift : function(o){
10358 var el = this.getFxEl();
10360 el.queueFx(o, function(){
10361 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10362 if(w !== undefined){
10363 a.width = {to: this.adjustWidth(w)};
10365 if(h !== undefined){
10366 a.height = {to: this.adjustHeight(h)};
10368 if(x !== undefined || y !== undefined){
10370 x !== undefined ? x : this.getX(),
10371 y !== undefined ? y : this.getY()
10374 if(op !== undefined){
10375 a.opacity = {to: op};
10377 if(o.xy !== undefined){
10378 a.points = {to: o.xy};
10380 arguments.callee.anim = this.fxanim(a,
10381 o, 'motion', .35, "easeOut", function(){
10389 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10390 * ending point of the effect.
10393 // default: slide the element downward while fading out
10396 // custom: slide the element out to the right with a 2-second duration
10397 el.ghost('r', { duration: 2 });
10399 // common config options shown with default values
10407 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10408 * @param {Object} options (optional) Object literal with any of the Fx config options
10409 * @return {Roo.Element} The Element
10411 ghost : function(anchor, o){
10412 var el = this.getFxEl();
10415 el.queueFx(o, function(){
10416 anchor = anchor || "b";
10418 // restore values after effect
10419 var r = this.getFxRestore();
10420 var w = this.getWidth(),
10421 h = this.getHeight();
10423 var st = this.dom.style;
10425 var after = function(){
10427 el.setDisplayed(false);
10433 el.setPositioning(r.pos);
10434 st.width = r.width;
10435 st.height = r.height;
10440 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10441 switch(anchor.toLowerCase()){
10468 arguments.callee.anim = this.fxanim(a,
10478 * Ensures that all effects queued after syncFx is called on the element are
10479 * run concurrently. This is the opposite of {@link #sequenceFx}.
10480 * @return {Roo.Element} The Element
10482 syncFx : function(){
10483 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10492 * Ensures that all effects queued after sequenceFx is called on the element are
10493 * run in sequence. This is the opposite of {@link #syncFx}.
10494 * @return {Roo.Element} The Element
10496 sequenceFx : function(){
10497 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10499 concurrent : false,
10506 nextFx : function(){
10507 var ef = this.fxQueue[0];
10514 * Returns true if the element has any effects actively running or queued, else returns false.
10515 * @return {Boolean} True if element has active effects, else false
10517 hasActiveFx : function(){
10518 return this.fxQueue && this.fxQueue[0];
10522 * Stops any running effects and clears the element's internal effects queue if it contains
10523 * any additional effects that haven't started yet.
10524 * @return {Roo.Element} The Element
10526 stopFx : function(){
10527 if(this.hasActiveFx()){
10528 var cur = this.fxQueue[0];
10529 if(cur && cur.anim && cur.anim.isAnimated()){
10530 this.fxQueue = [cur]; // clear out others
10531 cur.anim.stop(true);
10538 beforeFx : function(o){
10539 if(this.hasActiveFx() && !o.concurrent){
10550 * Returns true if the element is currently blocking so that no other effect can be queued
10551 * until this effect is finished, else returns false if blocking is not set. This is commonly
10552 * used to ensure that an effect initiated by a user action runs to completion prior to the
10553 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10554 * @return {Boolean} True if blocking, else false
10556 hasFxBlock : function(){
10557 var q = this.fxQueue;
10558 return q && q[0] && q[0].block;
10562 queueFx : function(o, fn){
10566 if(!this.hasFxBlock()){
10567 Roo.applyIf(o, this.fxDefaults);
10569 var run = this.beforeFx(o);
10570 fn.block = o.block;
10571 this.fxQueue.push(fn);
10583 fxWrap : function(pos, o, vis){
10585 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10588 wrapXY = this.getXY();
10590 var div = document.createElement("div");
10591 div.style.visibility = vis;
10592 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10593 wrap.setPositioning(pos);
10594 if(wrap.getStyle("position") == "static"){
10595 wrap.position("relative");
10597 this.clearPositioning('auto');
10599 wrap.dom.appendChild(this.dom);
10601 wrap.setXY(wrapXY);
10608 fxUnwrap : function(wrap, pos, o){
10609 this.clearPositioning();
10610 this.setPositioning(pos);
10612 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10618 getFxRestore : function(){
10619 var st = this.dom.style;
10620 return {pos: this.getPositioning(), width: st.width, height : st.height};
10624 afterFx : function(o){
10626 this.applyStyles(o.afterStyle);
10629 this.addClass(o.afterCls);
10631 if(o.remove === true){
10634 Roo.callback(o.callback, o.scope, [this]);
10636 this.fxQueue.shift();
10642 getFxEl : function(){ // support for composite element fx
10643 return Roo.get(this.dom);
10647 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10648 animType = animType || 'run';
10650 var anim = Roo.lib.Anim[animType](
10652 (opt.duration || defaultDur) || .35,
10653 (opt.easing || defaultEase) || 'easeOut',
10655 Roo.callback(cb, this);
10664 // backwords compat
10665 Roo.Fx.resize = Roo.Fx.scale;
10667 //When included, Roo.Fx is automatically applied to Element so that all basic
10668 //effects are available directly via the Element API
10669 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10671 * Ext JS Library 1.1.1
10672 * Copyright(c) 2006-2007, Ext JS, LLC.
10674 * Originally Released Under LGPL - original licence link has changed is not relivant.
10677 * <script type="text/javascript">
10682 * @class Roo.CompositeElement
10683 * Standard composite class. Creates a Roo.Element for every element in the collection.
10685 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10686 * actions will be performed on all the elements in this collection.</b>
10688 * All methods return <i>this</i> and can be chained.
10690 var els = Roo.select("#some-el div.some-class", true);
10691 // or select directly from an existing element
10692 var el = Roo.get('some-el');
10693 el.select('div.some-class', true);
10695 els.setWidth(100); // all elements become 100 width
10696 els.hide(true); // all elements fade out and hide
10698 els.setWidth(100).hide(true);
10701 Roo.CompositeElement = function(els){
10702 this.elements = [];
10703 this.addElements(els);
10705 Roo.CompositeElement.prototype = {
10707 addElements : function(els){
10708 if(!els) return this;
10709 if(typeof els == "string"){
10710 els = Roo.Element.selectorFunction(els);
10712 var yels = this.elements;
10713 var index = yels.length-1;
10714 for(var i = 0, len = els.length; i < len; i++) {
10715 yels[++index] = Roo.get(els[i]);
10721 * Clears this composite and adds the elements returned by the passed selector.
10722 * @param {String/Array} els A string CSS selector, an array of elements or an element
10723 * @return {CompositeElement} this
10725 fill : function(els){
10726 this.elements = [];
10732 * Filters this composite to only elements that match the passed selector.
10733 * @param {String} selector A string CSS selector
10734 * @return {CompositeElement} this
10736 filter : function(selector){
10738 this.each(function(el){
10739 if(el.is(selector)){
10740 els[els.length] = el.dom;
10747 invoke : function(fn, args){
10748 var els = this.elements;
10749 for(var i = 0, len = els.length; i < len; i++) {
10750 Roo.Element.prototype[fn].apply(els[i], args);
10755 * Adds elements to this composite.
10756 * @param {String/Array} els A string CSS selector, an array of elements or an element
10757 * @return {CompositeElement} this
10759 add : function(els){
10760 if(typeof els == "string"){
10761 this.addElements(Roo.Element.selectorFunction(els));
10762 }else if(els.length !== undefined){
10763 this.addElements(els);
10765 this.addElements([els]);
10770 * Calls the passed function passing (el, this, index) for each element in this composite.
10771 * @param {Function} fn The function to call
10772 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10773 * @return {CompositeElement} this
10775 each : function(fn, scope){
10776 var els = this.elements;
10777 for(var i = 0, len = els.length; i < len; i++){
10778 if(fn.call(scope || els[i], els[i], this, i) === false) {
10786 * Returns the Element object at the specified index
10787 * @param {Number} index
10788 * @return {Roo.Element}
10790 item : function(index){
10791 return this.elements[index] || null;
10795 * Returns the first Element
10796 * @return {Roo.Element}
10798 first : function(){
10799 return this.item(0);
10803 * Returns the last Element
10804 * @return {Roo.Element}
10807 return this.item(this.elements.length-1);
10811 * Returns the number of elements in this composite
10814 getCount : function(){
10815 return this.elements.length;
10819 * Returns true if this composite contains the passed element
10822 contains : function(el){
10823 return this.indexOf(el) !== -1;
10827 * Returns true if this composite contains the passed element
10830 indexOf : function(el){
10831 return this.elements.indexOf(Roo.get(el));
10836 * Removes the specified element(s).
10837 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10838 * or an array of any of those.
10839 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10840 * @return {CompositeElement} this
10842 removeElement : function(el, removeDom){
10843 if(el instanceof Array){
10844 for(var i = 0, len = el.length; i < len; i++){
10845 this.removeElement(el[i]);
10849 var index = typeof el == 'number' ? el : this.indexOf(el);
10852 var d = this.elements[index];
10856 d.parentNode.removeChild(d);
10859 this.elements.splice(index, 1);
10865 * Replaces the specified element with the passed element.
10866 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10868 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10869 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10870 * @return {CompositeElement} this
10872 replaceElement : function(el, replacement, domReplace){
10873 var index = typeof el == 'number' ? el : this.indexOf(el);
10876 this.elements[index].replaceWith(replacement);
10878 this.elements.splice(index, 1, Roo.get(replacement))
10885 * Removes all elements.
10887 clear : function(){
10888 this.elements = [];
10892 Roo.CompositeElement.createCall = function(proto, fnName){
10893 if(!proto[fnName]){
10894 proto[fnName] = function(){
10895 return this.invoke(fnName, arguments);
10899 for(var fnName in Roo.Element.prototype){
10900 if(typeof Roo.Element.prototype[fnName] == "function"){
10901 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10907 * Ext JS Library 1.1.1
10908 * Copyright(c) 2006-2007, Ext JS, LLC.
10910 * Originally Released Under LGPL - original licence link has changed is not relivant.
10913 * <script type="text/javascript">
10917 * @class Roo.CompositeElementLite
10918 * @extends Roo.CompositeElement
10919 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10921 var els = Roo.select("#some-el div.some-class");
10922 // or select directly from an existing element
10923 var el = Roo.get('some-el');
10924 el.select('div.some-class');
10926 els.setWidth(100); // all elements become 100 width
10927 els.hide(true); // all elements fade out and hide
10929 els.setWidth(100).hide(true);
10930 </code></pre><br><br>
10931 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10932 * actions will be performed on all the elements in this collection.</b>
10934 Roo.CompositeElementLite = function(els){
10935 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10936 this.el = new Roo.Element.Flyweight();
10938 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10939 addElements : function(els){
10941 if(els instanceof Array){
10942 this.elements = this.elements.concat(els);
10944 var yels = this.elements;
10945 var index = yels.length-1;
10946 for(var i = 0, len = els.length; i < len; i++) {
10947 yels[++index] = els[i];
10953 invoke : function(fn, args){
10954 var els = this.elements;
10956 for(var i = 0, len = els.length; i < len; i++) {
10958 Roo.Element.prototype[fn].apply(el, args);
10963 * Returns a flyweight Element of the dom element object at the specified index
10964 * @param {Number} index
10965 * @return {Roo.Element}
10967 item : function(index){
10968 if(!this.elements[index]){
10971 this.el.dom = this.elements[index];
10975 // fixes scope with flyweight
10976 addListener : function(eventName, handler, scope, opt){
10977 var els = this.elements;
10978 for(var i = 0, len = els.length; i < len; i++) {
10979 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
10985 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
10986 * passed is the flyweight (shared) Roo.Element instance, so if you require a
10987 * a reference to the dom node, use el.dom.</b>
10988 * @param {Function} fn The function to call
10989 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10990 * @return {CompositeElement} this
10992 each : function(fn, scope){
10993 var els = this.elements;
10995 for(var i = 0, len = els.length; i < len; i++){
10997 if(fn.call(scope || el, el, this, i) === false){
11004 indexOf : function(el){
11005 return this.elements.indexOf(Roo.getDom(el));
11008 replaceElement : function(el, replacement, domReplace){
11009 var index = typeof el == 'number' ? el : this.indexOf(el);
11011 replacement = Roo.getDom(replacement);
11013 var d = this.elements[index];
11014 d.parentNode.insertBefore(replacement, d);
11015 d.parentNode.removeChild(d);
11017 this.elements.splice(index, 1, replacement);
11022 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11026 * Ext JS Library 1.1.1
11027 * Copyright(c) 2006-2007, Ext JS, LLC.
11029 * Originally Released Under LGPL - original licence link has changed is not relivant.
11032 * <script type="text/javascript">
11038 * @class Roo.data.Connection
11039 * @extends Roo.util.Observable
11040 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11041 * either to a configured URL, or to a URL specified at request time.<br><br>
11043 * Requests made by this class are asynchronous, and will return immediately. No data from
11044 * the server will be available to the statement immediately following the {@link #request} call.
11045 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11047 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11048 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11049 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11050 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11051 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11052 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11053 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11054 * standard DOM methods.
11056 * @param {Object} config a configuration object.
11058 Roo.data.Connection = function(config){
11059 Roo.apply(this, config);
11062 * @event beforerequest
11063 * Fires before a network request is made to retrieve a data object.
11064 * @param {Connection} conn This Connection object.
11065 * @param {Object} options The options config object passed to the {@link #request} method.
11067 "beforerequest" : true,
11069 * @event requestcomplete
11070 * Fires if the request was successfully completed.
11071 * @param {Connection} conn This Connection object.
11072 * @param {Object} response The XHR object containing the response data.
11073 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11074 * @param {Object} options The options config object passed to the {@link #request} method.
11076 "requestcomplete" : true,
11078 * @event requestexception
11079 * Fires if an error HTTP status was returned from the server.
11080 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11081 * @param {Connection} conn This Connection object.
11082 * @param {Object} response The XHR object containing the response data.
11083 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11084 * @param {Object} options The options config object passed to the {@link #request} method.
11086 "requestexception" : true
11088 Roo.data.Connection.superclass.constructor.call(this);
11091 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11093 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11096 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11097 * extra parameters to each request made by this object. (defaults to undefined)
11100 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11101 * to each request made by this object. (defaults to undefined)
11104 * @cfg {String} method (Optional) The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11107 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11111 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11117 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11120 disableCaching: true,
11123 * Sends an HTTP request to a remote server.
11124 * @param {Object} options An object which may contain the following properties:<ul>
11125 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11126 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11127 * request, a url encoded string or a function to call to get either.</li>
11128 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11129 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11130 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11131 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11132 * <li>options {Object} The parameter to the request call.</li>
11133 * <li>success {Boolean} True if the request succeeded.</li>
11134 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11136 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11137 * The callback is passed the following parameters:<ul>
11138 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11139 * <li>options {Object} The parameter to the request call.</li>
11141 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11142 * The callback is passed the following parameters:<ul>
11143 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11144 * <li>options {Object} The parameter to the request call.</li>
11146 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11147 * for the callback function. Defaults to the browser window.</li>
11148 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11149 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11150 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11151 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11152 * params for the post data. Any params will be appended to the URL.</li>
11153 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11155 * @return {Number} transactionId
11157 request : function(o){
11158 if(this.fireEvent("beforerequest", this, o) !== false){
11161 if(typeof p == "function"){
11162 p = p.call(o.scope||window, o);
11164 if(typeof p == "object"){
11165 p = Roo.urlEncode(o.params);
11167 if(this.extraParams){
11168 var extras = Roo.urlEncode(this.extraParams);
11169 p = p ? (p + '&' + extras) : extras;
11172 var url = o.url || this.url;
11173 if(typeof url == 'function'){
11174 url = url.call(o.scope||window, o);
11178 var form = Roo.getDom(o.form);
11179 url = url || form.action;
11181 var enctype = form.getAttribute("enctype");
11182 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11183 return this.doFormUpload(o, p, url);
11185 var f = Roo.lib.Ajax.serializeForm(form);
11186 p = p ? (p + '&' + f) : f;
11189 var hs = o.headers;
11190 if(this.defaultHeaders){
11191 hs = Roo.apply(hs || {}, this.defaultHeaders);
11198 success: this.handleResponse,
11199 failure: this.handleFailure,
11201 argument: {options: o},
11202 timeout : this.timeout
11205 var method = o.method||this.method||(p ? "POST" : "GET");
11207 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11208 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11211 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11215 }else if(this.autoAbort !== false){
11219 if((method == 'GET' && p) || o.xmlData){
11220 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11223 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11224 return this.transId;
11226 Roo.callback(o.callback, o.scope, [o, null, null]);
11232 * Determine whether this object has a request outstanding.
11233 * @param {Number} transactionId (Optional) defaults to the last transaction
11234 * @return {Boolean} True if there is an outstanding request.
11236 isLoading : function(transId){
11238 return Roo.lib.Ajax.isCallInProgress(transId);
11240 return this.transId ? true : false;
11245 * Aborts any outstanding request.
11246 * @param {Number} transactionId (Optional) defaults to the last transaction
11248 abort : function(transId){
11249 if(transId || this.isLoading()){
11250 Roo.lib.Ajax.abort(transId || this.transId);
11255 handleResponse : function(response){
11256 this.transId = false;
11257 var options = response.argument.options;
11258 response.argument = options ? options.argument : null;
11259 this.fireEvent("requestcomplete", this, response, options);
11260 Roo.callback(options.success, options.scope, [response, options]);
11261 Roo.callback(options.callback, options.scope, [options, true, response]);
11265 handleFailure : function(response, e){
11266 this.transId = false;
11267 var options = response.argument.options;
11268 response.argument = options ? options.argument : null;
11269 this.fireEvent("requestexception", this, response, options, e);
11270 Roo.callback(options.failure, options.scope, [response, options]);
11271 Roo.callback(options.callback, options.scope, [options, false, response]);
11275 doFormUpload : function(o, ps, url){
11277 var frame = document.createElement('iframe');
11280 frame.className = 'x-hidden';
11282 frame.src = Roo.SSL_SECURE_URL;
11284 document.body.appendChild(frame);
11287 document.frames[id].name = id;
11290 var form = Roo.getDom(o.form);
11292 form.method = 'POST';
11293 form.enctype = form.encoding = 'multipart/form-data';
11299 if(ps){ // add dynamic params
11301 ps = Roo.urlDecode(ps, false);
11303 if(ps.hasOwnProperty(k)){
11304 hd = document.createElement('input');
11305 hd.type = 'hidden';
11308 form.appendChild(hd);
11315 var r = { // bogus response object
11320 r.argument = o ? o.argument : null;
11325 doc = frame.contentWindow.document;
11327 doc = (frame.contentDocument || window.frames[id].document);
11329 if(doc && doc.body){
11330 r.responseText = doc.body.innerHTML;
11332 if(doc && doc.XMLDocument){
11333 r.responseXML = doc.XMLDocument;
11335 r.responseXML = doc;
11342 Roo.EventManager.removeListener(frame, 'load', cb, this);
11344 this.fireEvent("requestcomplete", this, r, o);
11345 Roo.callback(o.success, o.scope, [r, o]);
11346 Roo.callback(o.callback, o.scope, [o, true, r]);
11348 setTimeout(function(){document.body.removeChild(frame);}, 100);
11351 Roo.EventManager.on(frame, 'load', cb, this);
11354 if(hiddens){ // remove dynamic params
11355 for(var i = 0, len = hiddens.length; i < len; i++){
11356 form.removeChild(hiddens[i]);
11364 * @extends Roo.data.Connection
11365 * Global Ajax request class.
11369 Roo.Ajax = new Roo.data.Connection({
11372 * @cfg {String} url @hide
11375 * @cfg {Object} extraParams @hide
11378 * @cfg {Object} defaultHeaders @hide
11381 * @cfg {String} method (Optional) @hide
11384 * @cfg {Number} timeout (Optional) @hide
11387 * @cfg {Boolean} autoAbort (Optional) @hide
11391 * @cfg {Boolean} disableCaching (Optional) @hide
11395 * @property disableCaching
11396 * True to add a unique cache-buster param to GET requests. (defaults to true)
11401 * The default URL to be used for requests to the server. (defaults to undefined)
11405 * @property extraParams
11406 * An object containing properties which are used as
11407 * extra parameters to each request made by this object. (defaults to undefined)
11411 * @property defaultHeaders
11412 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11417 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11421 * @property timeout
11422 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11427 * @property autoAbort
11428 * Whether a new request should abort any pending requests. (defaults to false)
11434 * Serialize the passed form into a url encoded string
11435 * @param {String/HTMLElement} form
11438 serializeForm : function(form){
11439 return Roo.lib.Ajax.serializeForm(form);
11443 * Ext JS Library 1.1.1
11444 * Copyright(c) 2006-2007, Ext JS, LLC.
11446 * Originally Released Under LGPL - original licence link has changed is not relivant.
11449 * <script type="text/javascript">
11454 * @extends Roo.data.Connection
11455 * Global Ajax request class.
11457 * @instanceOf Roo.data.Connection
11459 Roo.Ajax = new Roo.data.Connection({
11468 * @cfg {String} url @hide
11471 * @cfg {Object} extraParams @hide
11474 * @cfg {Object} defaultHeaders @hide
11477 * @cfg {String} method (Optional) @hide
11480 * @cfg {Number} timeout (Optional) @hide
11483 * @cfg {Boolean} autoAbort (Optional) @hide
11487 * @cfg {Boolean} disableCaching (Optional) @hide
11491 * @property disableCaching
11492 * True to add a unique cache-buster param to GET requests. (defaults to true)
11497 * The default URL to be used for requests to the server. (defaults to undefined)
11501 * @property extraParams
11502 * An object containing properties which are used as
11503 * extra parameters to each request made by this object. (defaults to undefined)
11507 * @property defaultHeaders
11508 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11513 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11517 * @property timeout
11518 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11523 * @property autoAbort
11524 * Whether a new request should abort any pending requests. (defaults to false)
11530 * Serialize the passed form into a url encoded string
11531 * @param {String/HTMLElement} form
11534 serializeForm : function(form){
11535 return Roo.lib.Ajax.serializeForm(form);
11539 * Ext JS Library 1.1.1
11540 * Copyright(c) 2006-2007, Ext JS, LLC.
11542 * Originally Released Under LGPL - original licence link has changed is not relivant.
11545 * <script type="text/javascript">
11550 * @class Roo.UpdateManager
11551 * @extends Roo.util.Observable
11552 * Provides AJAX-style update for Element object.<br><br>
11555 * // Get it from a Roo.Element object
11556 * var el = Roo.get("foo");
11557 * var mgr = el.getUpdateManager();
11558 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11560 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11562 * // or directly (returns the same UpdateManager instance)
11563 * var mgr = new Roo.UpdateManager("myElementId");
11564 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11565 * mgr.on("update", myFcnNeedsToKnow);
11567 // short handed call directly from the element object
11568 Roo.get("foo").load({
11572 text: "Loading Foo..."
11576 * Create new UpdateManager directly.
11577 * @param {String/HTMLElement/Roo.Element} el The element to update
11578 * @param {Boolean} forceNew (optional) By default the constructor checks to see if the passed element already has an UpdateManager and if it does it returns the same instance. This will skip that check (useful for extending this class).
11580 Roo.UpdateManager = function(el, forceNew){
11582 if(!forceNew && el.updateManager){
11583 return el.updateManager;
11586 * The Element object
11587 * @type Roo.Element
11591 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11594 this.defaultUrl = null;
11598 * @event beforeupdate
11599 * Fired before an update is made, return false from your handler and the update is cancelled.
11600 * @param {Roo.Element} el
11601 * @param {String/Object/Function} url
11602 * @param {String/Object} params
11604 "beforeupdate": true,
11607 * Fired after successful update is made.
11608 * @param {Roo.Element} el
11609 * @param {Object} oResponseObject The response Object
11614 * Fired on update failure.
11615 * @param {Roo.Element} el
11616 * @param {Object} oResponseObject The response Object
11620 var d = Roo.UpdateManager.defaults;
11622 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11625 this.sslBlankUrl = d.sslBlankUrl;
11627 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11630 this.disableCaching = d.disableCaching;
11632 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11635 this.indicatorText = d.indicatorText;
11637 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11640 this.showLoadIndicator = d.showLoadIndicator;
11642 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11645 this.timeout = d.timeout;
11648 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11651 this.loadScripts = d.loadScripts;
11654 * Transaction object of current executing transaction
11656 this.transaction = null;
11661 this.autoRefreshProcId = null;
11663 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11666 this.refreshDelegate = this.refresh.createDelegate(this);
11668 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11671 this.updateDelegate = this.update.createDelegate(this);
11673 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11676 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11680 this.successDelegate = this.processSuccess.createDelegate(this);
11684 this.failureDelegate = this.processFailure.createDelegate(this);
11686 if(!this.renderer){
11688 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11690 this.renderer = new Roo.UpdateManager.BasicRenderer();
11693 Roo.UpdateManager.superclass.constructor.call(this);
11696 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11698 * Get the Element this UpdateManager is bound to
11699 * @return {Roo.Element} The element
11701 getEl : function(){
11705 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11706 * @param {Object/String/Function} url The url for this request or a function to call to get the url or a config object containing any of the following options:
11709 url: "your-url.php",<br/>
11710 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11711 callback: yourFunction,<br/>
11712 scope: yourObject, //(optional scope) <br/>
11713 discardUrl: false, <br/>
11714 nocache: false,<br/>
11715 text: "Loading...",<br/>
11717 scripts: false<br/>
11720 * The only required property is url. The optional properties nocache, text and scripts
11721 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11722 * @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}
11723 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11724 * @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.
11726 update : function(url, params, callback, discardUrl){
11727 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11728 var method = this.method, cfg;
11729 if(typeof url == "object"){ // must be config object
11732 params = params || cfg.params;
11733 callback = callback || cfg.callback;
11734 discardUrl = discardUrl || cfg.discardUrl;
11735 if(callback && cfg.scope){
11736 callback = callback.createDelegate(cfg.scope);
11738 if(typeof cfg.method != "undefined"){method = cfg.method;};
11739 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11740 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11741 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11742 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11744 this.showLoading();
11746 this.defaultUrl = url;
11748 if(typeof url == "function"){
11749 url = url.call(this);
11752 method = method || (params ? "POST" : "GET");
11753 if(method == "GET"){
11754 url = this.prepareUrl(url);
11757 var o = Roo.apply(cfg ||{}, {
11760 success: this.successDelegate,
11761 failure: this.failureDelegate,
11762 callback: undefined,
11763 timeout: (this.timeout*1000),
11764 argument: {"url": url, "form": null, "callback": callback, "params": params}
11767 this.transaction = Roo.Ajax.request(o);
11772 * Performs an async form post, updating this element with the response. If the form has the attribute enctype="multipart/form-data", it assumes it's a file upload.
11773 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11774 * @param {String/HTMLElement} form The form Id or form element
11775 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11776 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11777 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11779 formUpdate : function(form, url, reset, callback){
11780 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11781 if(typeof url == "function"){
11782 url = url.call(this);
11784 form = Roo.getDom(form);
11785 this.transaction = Roo.Ajax.request({
11788 success: this.successDelegate,
11789 failure: this.failureDelegate,
11790 timeout: (this.timeout*1000),
11791 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11793 this.showLoading.defer(1, this);
11798 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11799 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11801 refresh : function(callback){
11802 if(this.defaultUrl == null){
11805 this.update(this.defaultUrl, null, callback, true);
11809 * Set this element to auto refresh.
11810 * @param {Number} interval How often to update (in seconds).
11811 * @param {String/Function} url (optional) The url for this request or a function to call to get the url (Defaults to the last used url)
11812 * @param {String/Object} params (optional) The parameters to pass as either a url encoded string "¶m1=1¶m2=2" or as an object {param1: 1, param2: 2}
11813 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11814 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11816 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11818 this.update(url || this.defaultUrl, params, callback, true);
11820 if(this.autoRefreshProcId){
11821 clearInterval(this.autoRefreshProcId);
11823 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11827 * Stop auto refresh on this element.
11829 stopAutoRefresh : function(){
11830 if(this.autoRefreshProcId){
11831 clearInterval(this.autoRefreshProcId);
11832 delete this.autoRefreshProcId;
11836 isAutoRefreshing : function(){
11837 return this.autoRefreshProcId ? true : false;
11840 * Called to update the element to "Loading" state. Override to perform custom action.
11842 showLoading : function(){
11843 if(this.showLoadIndicator){
11844 this.el.update(this.indicatorText);
11849 * Adds unique parameter to query string if disableCaching = true
11852 prepareUrl : function(url){
11853 if(this.disableCaching){
11854 var append = "_dc=" + (new Date().getTime());
11855 if(url.indexOf("?") !== -1){
11856 url += "&" + append;
11858 url += "?" + append;
11867 processSuccess : function(response){
11868 this.transaction = null;
11869 if(response.argument.form && response.argument.reset){
11870 try{ // put in try/catch since some older FF releases had problems with this
11871 response.argument.form.reset();
11874 if(this.loadScripts){
11875 this.renderer.render(this.el, response, this,
11876 this.updateComplete.createDelegate(this, [response]));
11878 this.renderer.render(this.el, response, this);
11879 this.updateComplete(response);
11883 updateComplete : function(response){
11884 this.fireEvent("update", this.el, response);
11885 if(typeof response.argument.callback == "function"){
11886 response.argument.callback(this.el, true, response);
11893 processFailure : function(response){
11894 this.transaction = null;
11895 this.fireEvent("failure", this.el, response);
11896 if(typeof response.argument.callback == "function"){
11897 response.argument.callback(this.el, false, response);
11902 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11903 * @param {Object} renderer The object implementing the render() method
11905 setRenderer : function(renderer){
11906 this.renderer = renderer;
11909 getRenderer : function(){
11910 return this.renderer;
11914 * Set the defaultUrl used for updates
11915 * @param {String/Function} defaultUrl The url or a function to call to get the url
11917 setDefaultUrl : function(defaultUrl){
11918 this.defaultUrl = defaultUrl;
11922 * Aborts the executing transaction
11924 abort : function(){
11925 if(this.transaction){
11926 Roo.Ajax.abort(this.transaction);
11931 * Returns true if an update is in progress
11932 * @return {Boolean}
11934 isUpdating : function(){
11935 if(this.transaction){
11936 return Roo.Ajax.isLoading(this.transaction);
11943 * @class Roo.UpdateManager.defaults
11944 * @static (not really - but it helps the doc tool)
11945 * The defaults collection enables customizing the default properties of UpdateManager
11947 Roo.UpdateManager.defaults = {
11949 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
11955 * True to process scripts by default (Defaults to false).
11958 loadScripts : false,
11961 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
11964 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
11966 * Whether to append unique parameter on get request to disable caching (Defaults to false).
11969 disableCaching : false,
11971 * Whether to show indicatorText when loading (Defaults to true).
11974 showLoadIndicator : true,
11976 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
11979 indicatorText : '<div class="loading-indicator">Loading...</div>'
11983 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
11985 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
11986 * @param {String/HTMLElement/Roo.Element} el The element to update
11987 * @param {String} url The url
11988 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
11989 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
11992 * @member Roo.UpdateManager
11994 Roo.UpdateManager.updateElement = function(el, url, params, options){
11995 var um = Roo.get(el, true).getUpdateManager();
11996 Roo.apply(um, options);
11997 um.update(url, params, options ? options.callback : null);
11999 // alias for backwards compat
12000 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12002 * @class Roo.UpdateManager.BasicRenderer
12003 * Default Content renderer. Updates the elements innerHTML with the responseText.
12005 Roo.UpdateManager.BasicRenderer = function(){};
12007 Roo.UpdateManager.BasicRenderer.prototype = {
12009 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12010 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12011 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12012 * @param {Roo.Element} el The element being rendered
12013 * @param {Object} response The YUI Connect response object
12014 * @param {UpdateManager} updateManager The calling update manager
12015 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12017 render : function(el, response, updateManager, callback){
12018 el.update(response.responseText, updateManager.loadScripts, callback);
12023 * Ext JS Library 1.1.1
12024 * Copyright(c) 2006-2007, Ext JS, LLC.
12026 * Originally Released Under LGPL - original licence link has changed is not relivant.
12029 * <script type="text/javascript">
12033 * @class Roo.util.DelayedTask
12034 * Provides a convenient method of performing setTimeout where a new
12035 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12036 * You can use this class to buffer
12037 * the keypress events for a certain number of milliseconds, and perform only if they stop
12038 * for that amount of time.
12039 * @constructor The parameters to this constructor serve as defaults and are not required.
12040 * @param {Function} fn (optional) The default function to timeout
12041 * @param {Object} scope (optional) The default scope of that timeout
12042 * @param {Array} args (optional) The default Array of arguments
12044 Roo.util.DelayedTask = function(fn, scope, args){
12045 var id = null, d, t;
12047 var call = function(){
12048 var now = new Date().getTime();
12052 fn.apply(scope, args || []);
12056 * Cancels any pending timeout and queues a new one
12057 * @param {Number} delay The milliseconds to delay
12058 * @param {Function} newFn (optional) Overrides function passed to constructor
12059 * @param {Object} newScope (optional) Overrides scope passed to constructor
12060 * @param {Array} newArgs (optional) Overrides args passed to constructor
12062 this.delay = function(delay, newFn, newScope, newArgs){
12063 if(id && delay != d){
12067 t = new Date().getTime();
12069 scope = newScope || scope;
12070 args = newArgs || args;
12072 id = setInterval(call, d);
12077 * Cancel the last queued timeout
12079 this.cancel = function(){
12087 * Ext JS Library 1.1.1
12088 * Copyright(c) 2006-2007, Ext JS, LLC.
12090 * Originally Released Under LGPL - original licence link has changed is not relivant.
12093 * <script type="text/javascript">
12097 Roo.util.TaskRunner = function(interval){
12098 interval = interval || 10;
12099 var tasks = [], removeQueue = [];
12101 var running = false;
12103 var stopThread = function(){
12109 var startThread = function(){
12112 id = setInterval(runTasks, interval);
12116 var removeTask = function(task){
12117 removeQueue.push(task);
12123 var runTasks = function(){
12124 if(removeQueue.length > 0){
12125 for(var i = 0, len = removeQueue.length; i < len; i++){
12126 tasks.remove(removeQueue[i]);
12129 if(tasks.length < 1){
12134 var now = new Date().getTime();
12135 for(var i = 0, len = tasks.length; i < len; ++i){
12137 var itime = now - t.taskRunTime;
12138 if(t.interval <= itime){
12139 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12140 t.taskRunTime = now;
12141 if(rt === false || t.taskRunCount === t.repeat){
12146 if(t.duration && t.duration <= (now - t.taskStartTime)){
12153 * Queues a new task.
12154 * @param {Object} task
12156 this.start = function(task){
12158 task.taskStartTime = new Date().getTime();
12159 task.taskRunTime = 0;
12160 task.taskRunCount = 0;
12165 this.stop = function(task){
12170 this.stopAll = function(){
12172 for(var i = 0, len = tasks.length; i < len; i++){
12173 if(tasks[i].onStop){
12182 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12184 * Ext JS Library 1.1.1
12185 * Copyright(c) 2006-2007, Ext JS, LLC.
12187 * Originally Released Under LGPL - original licence link has changed is not relivant.
12190 * <script type="text/javascript">
12195 * @class Roo.util.MixedCollection
12196 * @extends Roo.util.Observable
12197 * A Collection class that maintains both numeric indexes and keys and exposes events.
12199 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12200 * collection (defaults to false)
12201 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12202 * and return the key value for that item. This is used when available to look up the key on items that
12203 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12204 * equivalent to providing an implementation for the {@link #getKey} method.
12206 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12214 * Fires when the collection is cleared.
12219 * Fires when an item is added to the collection.
12220 * @param {Number} index The index at which the item was added.
12221 * @param {Object} o The item added.
12222 * @param {String} key The key associated with the added item.
12227 * Fires when an item is replaced in the collection.
12228 * @param {String} key he key associated with the new added.
12229 * @param {Object} old The item being replaced.
12230 * @param {Object} new The new item.
12235 * Fires when an item is removed from the collection.
12236 * @param {Object} o The item being removed.
12237 * @param {String} key (optional) The key associated with the removed item.
12242 this.allowFunctions = allowFunctions === true;
12244 this.getKey = keyFn;
12246 Roo.util.MixedCollection.superclass.constructor.call(this);
12249 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12250 allowFunctions : false,
12253 * Adds an item to the collection.
12254 * @param {String} key The key to associate with the item
12255 * @param {Object} o The item to add.
12256 * @return {Object} The item added.
12258 add : function(key, o){
12259 if(arguments.length == 1){
12261 key = this.getKey(o);
12263 if(typeof key == "undefined" || key === null){
12265 this.items.push(o);
12266 this.keys.push(null);
12268 var old = this.map[key];
12270 return this.replace(key, o);
12273 this.items.push(o);
12275 this.keys.push(key);
12277 this.fireEvent("add", this.length-1, o, key);
12282 * MixedCollection has a generic way to fetch keys if you implement getKey.
12285 var mc = new Roo.util.MixedCollection();
12286 mc.add(someEl.dom.id, someEl);
12287 mc.add(otherEl.dom.id, otherEl);
12291 var mc = new Roo.util.MixedCollection();
12292 mc.getKey = function(el){
12298 // or via the constructor
12299 var mc = new Roo.util.MixedCollection(false, function(el){
12305 * @param o {Object} The item for which to find the key.
12306 * @return {Object} The key for the passed item.
12308 getKey : function(o){
12313 * Replaces an item in the collection.
12314 * @param {String} key The key associated with the item to replace, or the item to replace.
12315 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12316 * @return {Object} The new item.
12318 replace : function(key, o){
12319 if(arguments.length == 1){
12321 key = this.getKey(o);
12323 var old = this.item(key);
12324 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12325 return this.add(key, o);
12327 var index = this.indexOfKey(key);
12328 this.items[index] = o;
12330 this.fireEvent("replace", key, old, o);
12335 * Adds all elements of an Array or an Object to the collection.
12336 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12337 * an Array of values, each of which are added to the collection.
12339 addAll : function(objs){
12340 if(arguments.length > 1 || objs instanceof Array){
12341 var args = arguments.length > 1 ? arguments : objs;
12342 for(var i = 0, len = args.length; i < len; i++){
12346 for(var key in objs){
12347 if(this.allowFunctions || typeof objs[key] != "function"){
12348 this.add(key, objs[key]);
12355 * Executes the specified function once for every item in the collection, passing each
12356 * item as the first and only parameter. returning false from the function will stop the iteration.
12357 * @param {Function} fn The function to execute for each item.
12358 * @param {Object} scope (optional) The scope in which to execute the function.
12360 each : function(fn, scope){
12361 var items = [].concat(this.items); // each safe for removal
12362 for(var i = 0, len = items.length; i < len; i++){
12363 if(fn.call(scope || items[i], items[i], i, len) === false){
12370 * Executes the specified function once for every key in the collection, passing each
12371 * key, and its associated item as the first two parameters.
12372 * @param {Function} fn The function to execute for each item.
12373 * @param {Object} scope (optional) The scope in which to execute the function.
12375 eachKey : function(fn, scope){
12376 for(var i = 0, len = this.keys.length; i < len; i++){
12377 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12382 * Returns the first item in the collection which elicits a true return value from the
12383 * passed selection function.
12384 * @param {Function} fn The selection function to execute for each item.
12385 * @param {Object} scope (optional) The scope in which to execute the function.
12386 * @return {Object} The first item in the collection which returned true from the selection function.
12388 find : function(fn, scope){
12389 for(var i = 0, len = this.items.length; i < len; i++){
12390 if(fn.call(scope || window, this.items[i], this.keys[i])){
12391 return this.items[i];
12398 * Inserts an item at the specified index in the collection.
12399 * @param {Number} index The index to insert the item at.
12400 * @param {String} key The key to associate with the new item, or the item itself.
12401 * @param {Object} o (optional) If the second parameter was a key, the new item.
12402 * @return {Object} The item inserted.
12404 insert : function(index, key, o){
12405 if(arguments.length == 2){
12407 key = this.getKey(o);
12409 if(index >= this.length){
12410 return this.add(key, o);
12413 this.items.splice(index, 0, o);
12414 if(typeof key != "undefined" && key != null){
12417 this.keys.splice(index, 0, key);
12418 this.fireEvent("add", index, o, key);
12423 * Removed an item from the collection.
12424 * @param {Object} o The item to remove.
12425 * @return {Object} The item removed.
12427 remove : function(o){
12428 return this.removeAt(this.indexOf(o));
12432 * Remove an item from a specified index in the collection.
12433 * @param {Number} index The index within the collection of the item to remove.
12435 removeAt : function(index){
12436 if(index < this.length && index >= 0){
12438 var o = this.items[index];
12439 this.items.splice(index, 1);
12440 var key = this.keys[index];
12441 if(typeof key != "undefined"){
12442 delete this.map[key];
12444 this.keys.splice(index, 1);
12445 this.fireEvent("remove", o, key);
12450 * Removed an item associated with the passed key fom the collection.
12451 * @param {String} key The key of the item to remove.
12453 removeKey : function(key){
12454 return this.removeAt(this.indexOfKey(key));
12458 * Returns the number of items in the collection.
12459 * @return {Number} the number of items in the collection.
12461 getCount : function(){
12462 return this.length;
12466 * Returns index within the collection of the passed Object.
12467 * @param {Object} o The item to find the index of.
12468 * @return {Number} index of the item.
12470 indexOf : function(o){
12471 if(!this.items.indexOf){
12472 for(var i = 0, len = this.items.length; i < len; i++){
12473 if(this.items[i] == o) return i;
12477 return this.items.indexOf(o);
12482 * Returns index within the collection of the passed key.
12483 * @param {String} key The key to find the index of.
12484 * @return {Number} index of the key.
12486 indexOfKey : function(key){
12487 if(!this.keys.indexOf){
12488 for(var i = 0, len = this.keys.length; i < len; i++){
12489 if(this.keys[i] == key) return i;
12493 return this.keys.indexOf(key);
12498 * Returns the item associated with the passed key OR index. Key has priority over index.
12499 * @param {String/Number} key The key or index of the item.
12500 * @return {Object} The item associated with the passed key.
12502 item : function(key){
12503 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12504 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12508 * Returns the item at the specified index.
12509 * @param {Number} index The index of the item.
12512 itemAt : function(index){
12513 return this.items[index];
12517 * Returns the item associated with the passed key.
12518 * @param {String/Number} key The key of the item.
12519 * @return {Object} The item associated with the passed key.
12521 key : function(key){
12522 return this.map[key];
12526 * Returns true if the collection contains the passed Object as an item.
12527 * @param {Object} o The Object to look for in the collection.
12528 * @return {Boolean} True if the collection contains the Object as an item.
12530 contains : function(o){
12531 return this.indexOf(o) != -1;
12535 * Returns true if the collection contains the passed Object as a key.
12536 * @param {String} key The key to look for in the collection.
12537 * @return {Boolean} True if the collection contains the Object as a key.
12539 containsKey : function(key){
12540 return typeof this.map[key] != "undefined";
12544 * Removes all items from the collection.
12546 clear : function(){
12551 this.fireEvent("clear");
12555 * Returns the first item in the collection.
12556 * @return {Object} the first item in the collection..
12558 first : function(){
12559 return this.items[0];
12563 * Returns the last item in the collection.
12564 * @return {Object} the last item in the collection..
12567 return this.items[this.length-1];
12570 _sort : function(property, dir, fn){
12571 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12572 fn = fn || function(a, b){
12575 var c = [], k = this.keys, items = this.items;
12576 for(var i = 0, len = items.length; i < len; i++){
12577 c[c.length] = {key: k[i], value: items[i], index: i};
12579 c.sort(function(a, b){
12580 var v = fn(a[property], b[property]) * dsc;
12582 v = (a.index < b.index ? -1 : 1);
12586 for(var i = 0, len = c.length; i < len; i++){
12587 items[i] = c[i].value;
12590 this.fireEvent("sort", this);
12594 * Sorts this collection with the passed comparison function
12595 * @param {String} direction (optional) "ASC" or "DESC"
12596 * @param {Function} fn (optional) comparison function
12598 sort : function(dir, fn){
12599 this._sort("value", dir, fn);
12603 * Sorts this collection by keys
12604 * @param {String} direction (optional) "ASC" or "DESC"
12605 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12607 keySort : function(dir, fn){
12608 this._sort("key", dir, fn || function(a, b){
12609 return String(a).toUpperCase()-String(b).toUpperCase();
12614 * Returns a range of items in this collection
12615 * @param {Number} startIndex (optional) defaults to 0
12616 * @param {Number} endIndex (optional) default to the last item
12617 * @return {Array} An array of items
12619 getRange : function(start, end){
12620 var items = this.items;
12621 if(items.length < 1){
12624 start = start || 0;
12625 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12628 for(var i = start; i <= end; i++) {
12629 r[r.length] = items[i];
12632 for(var i = start; i >= end; i--) {
12633 r[r.length] = items[i];
12640 * Filter the <i>objects</i> in this collection by a specific property.
12641 * Returns a new collection that has been filtered.
12642 * @param {String} property A property on your objects
12643 * @param {String/RegExp} value Either string that the property values
12644 * should start with or a RegExp to test against the property
12645 * @return {MixedCollection} The new filtered collection
12647 filter : function(property, value){
12648 if(!value.exec){ // not a regex
12649 value = String(value);
12650 if(value.length == 0){
12651 return this.clone();
12653 value = new RegExp("^" + Roo.escapeRe(value), "i");
12655 return this.filterBy(function(o){
12656 return o && value.test(o[property]);
12661 * Filter by a function. * Returns a new collection that has been filtered.
12662 * The passed function will be called with each
12663 * object in the collection. If the function returns true, the value is included
12664 * otherwise it is filtered.
12665 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12666 * @param {Object} scope (optional) The scope of the function (defaults to this)
12667 * @return {MixedCollection} The new filtered collection
12669 filterBy : function(fn, scope){
12670 var r = new Roo.util.MixedCollection();
12671 r.getKey = this.getKey;
12672 var k = this.keys, it = this.items;
12673 for(var i = 0, len = it.length; i < len; i++){
12674 if(fn.call(scope||this, it[i], k[i])){
12675 r.add(k[i], it[i]);
12682 * Creates a duplicate of this collection
12683 * @return {MixedCollection}
12685 clone : function(){
12686 var r = new Roo.util.MixedCollection();
12687 var k = this.keys, it = this.items;
12688 for(var i = 0, len = it.length; i < len; i++){
12689 r.add(k[i], it[i]);
12691 r.getKey = this.getKey;
12696 * Returns the item associated with the passed key or index.
12698 * @param {String/Number} key The key or index of the item.
12699 * @return {Object} The item associated with the passed key.
12701 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12703 * Ext JS Library 1.1.1
12704 * Copyright(c) 2006-2007, Ext JS, LLC.
12706 * Originally Released Under LGPL - original licence link has changed is not relivant.
12709 * <script type="text/javascript">
12712 * @class Roo.util.JSON
12713 * Modified version of Douglas Crockford"s json.js that doesn"t
12714 * mess with the Object prototype
12715 * http://www.json.org/js.html
12718 Roo.util.JSON = new (function(){
12719 var useHasOwn = {}.hasOwnProperty ? true : false;
12721 // crashes Safari in some instances
12722 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12724 var pad = function(n) {
12725 return n < 10 ? "0" + n : n;
12738 var encodeString = function(s){
12739 if (/["\\\x00-\x1f]/.test(s)) {
12740 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12745 c = b.charCodeAt();
12747 Math.floor(c / 16).toString(16) +
12748 (c % 16).toString(16);
12751 return '"' + s + '"';
12754 var encodeArray = function(o){
12755 var a = ["["], b, i, l = o.length, v;
12756 for (i = 0; i < l; i += 1) {
12758 switch (typeof v) {
12767 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12775 var encodeDate = function(o){
12776 return '"' + o.getFullYear() + "-" +
12777 pad(o.getMonth() + 1) + "-" +
12778 pad(o.getDate()) + "T" +
12779 pad(o.getHours()) + ":" +
12780 pad(o.getMinutes()) + ":" +
12781 pad(o.getSeconds()) + '"';
12785 * Encodes an Object, Array or other value
12786 * @param {Mixed} o The variable to encode
12787 * @return {String} The JSON string
12789 this.encode = function(o)
12791 // should this be extended to fully wrap stringify..
12793 if(typeof o == "undefined" || o === null){
12795 }else if(o instanceof Array){
12796 return encodeArray(o);
12797 }else if(o instanceof Date){
12798 return encodeDate(o);
12799 }else if(typeof o == "string"){
12800 return encodeString(o);
12801 }else if(typeof o == "number"){
12802 return isFinite(o) ? String(o) : "null";
12803 }else if(typeof o == "boolean"){
12806 var a = ["{"], b, i, v;
12808 if(!useHasOwn || o.hasOwnProperty(i)) {
12810 switch (typeof v) {
12819 a.push(this.encode(i), ":",
12820 v === null ? "null" : this.encode(v));
12831 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12832 * @param {String} json The JSON string
12833 * @return {Object} The resulting object
12835 this.decode = function(json){
12837 return /** eval:var:json */ eval("(" + json + ')');
12841 * Shorthand for {@link Roo.util.JSON#encode}
12842 * @member Roo encode
12844 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
12846 * Shorthand for {@link Roo.util.JSON#decode}
12847 * @member Roo decode
12849 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
12852 * Ext JS Library 1.1.1
12853 * Copyright(c) 2006-2007, Ext JS, LLC.
12855 * Originally Released Under LGPL - original licence link has changed is not relivant.
12858 * <script type="text/javascript">
12862 * @class Roo.util.Format
12863 * Reusable data formatting functions
12866 Roo.util.Format = function(){
12867 var trimRe = /^\s+|\s+$/g;
12870 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12871 * @param {String} value The string to truncate
12872 * @param {Number} length The maximum length to allow before truncating
12873 * @return {String} The converted text
12875 ellipsis : function(value, len){
12876 if(value && value.length > len){
12877 return value.substr(0, len-3)+"...";
12883 * Checks a reference and converts it to empty string if it is undefined
12884 * @param {Mixed} value Reference to check
12885 * @return {Mixed} Empty string if converted, otherwise the original value
12887 undef : function(value){
12888 return typeof value != "undefined" ? value : "";
12892 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12893 * @param {String} value The string to encode
12894 * @return {String} The encoded text
12896 htmlEncode : function(value){
12897 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12901 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12902 * @param {String} value The string to decode
12903 * @return {String} The decoded text
12905 htmlDecode : function(value){
12906 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12910 * Trims any whitespace from either side of a string
12911 * @param {String} value The text to trim
12912 * @return {String} The trimmed text
12914 trim : function(value){
12915 return String(value).replace(trimRe, "");
12919 * Returns a substring from within an original string
12920 * @param {String} value The original text
12921 * @param {Number} start The start index of the substring
12922 * @param {Number} length The length of the substring
12923 * @return {String} The substring
12925 substr : function(value, start, length){
12926 return String(value).substr(start, length);
12930 * Converts a string to all lower case letters
12931 * @param {String} value The text to convert
12932 * @return {String} The converted text
12934 lowercase : function(value){
12935 return String(value).toLowerCase();
12939 * Converts a string to all upper case letters
12940 * @param {String} value The text to convert
12941 * @return {String} The converted text
12943 uppercase : function(value){
12944 return String(value).toUpperCase();
12948 * Converts the first character only of a string to upper case
12949 * @param {String} value The text to convert
12950 * @return {String} The converted text
12952 capitalize : function(value){
12953 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
12957 call : function(value, fn){
12958 if(arguments.length > 2){
12959 var args = Array.prototype.slice.call(arguments, 2);
12960 args.unshift(value);
12962 return /** eval:var:value */ eval(fn).apply(window, args);
12964 /** eval:var:value */
12965 return /** eval:var:value */ eval(fn).call(window, value);
12971 * safer version of Math.toFixed..??/
12972 * @param {Number/String} value The numeric value to format
12973 * @param {Number/String} value Decimal places
12974 * @return {String} The formatted currency string
12976 toFixed : function(v, n)
12978 // why not use to fixed - precision is buggered???
12980 return Math.round(v-0);
12982 var fact = Math.pow(10,n+1);
12983 v = (Math.round((v-0)*fact))/fact;
12984 var z = (''+fact).substring(2);
12985 if (v == Math.floor(v)) {
12986 return Math.floor(v) + '.' + z;
12989 // now just padd decimals..
12990 var ps = String(v).split('.');
12991 var fd = (ps[1] + z);
12992 var r = fd.substring(0,n);
12993 var rm = fd.substring(n);
12995 return ps[0] + '.' + r;
12997 r*=1; // turn it into a number;
12999 if (String(r).length != n) {
13002 r = String(r).substring(1); // chop the end off.
13005 return ps[0] + '.' + r;
13010 * Format a number as US currency
13011 * @param {Number/String} value The numeric value to format
13012 * @return {String} The formatted currency string
13014 usMoney : function(v){
13015 v = (Math.round((v-0)*100))/100;
13016 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13018 var ps = v.split('.');
13020 var sub = ps[1] ? '.'+ ps[1] : '.00';
13021 var r = /(\d+)(\d{3})/;
13022 while (r.test(whole)) {
13023 whole = whole.replace(r, '$1' + ',' + '$2');
13025 return "$" + whole + sub ;
13029 * Parse a value into a formatted date using the specified format pattern.
13030 * @param {Mixed} value The value to format
13031 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13032 * @return {String} The formatted date string
13034 date : function(v, format){
13038 if(!(v instanceof Date)){
13039 v = new Date(Date.parse(v));
13041 return v.dateFormat(format || "m/d/Y");
13045 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13046 * @param {String} format Any valid date format string
13047 * @return {Function} The date formatting function
13049 dateRenderer : function(format){
13050 return function(v){
13051 return Roo.util.Format.date(v, format);
13056 stripTagsRE : /<\/?[^>]+>/gi,
13059 * Strips all HTML tags
13060 * @param {Mixed} value The text from which to strip tags
13061 * @return {String} The stripped text
13063 stripTags : function(v){
13064 return !v ? v : String(v).replace(this.stripTagsRE, "");
13069 * Ext JS Library 1.1.1
13070 * Copyright(c) 2006-2007, Ext JS, LLC.
13072 * Originally Released Under LGPL - original licence link has changed is not relivant.
13075 * <script type="text/javascript">
13082 * @class Roo.MasterTemplate
13083 * @extends Roo.Template
13084 * Provides a template that can have child templates. The syntax is:
13086 var t = new Roo.MasterTemplate(
13087 '<select name="{name}">',
13088 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13091 t.add('options', {value: 'foo', text: 'bar'});
13092 // or you can add multiple child elements in one shot
13093 t.addAll('options', [
13094 {value: 'foo', text: 'bar'},
13095 {value: 'foo2', text: 'bar2'},
13096 {value: 'foo3', text: 'bar3'}
13098 // then append, applying the master template values
13099 t.append('my-form', {name: 'my-select'});
13101 * A name attribute for the child template is not required if you have only one child
13102 * template or you want to refer to them by index.
13104 Roo.MasterTemplate = function(){
13105 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13106 this.originalHtml = this.html;
13108 var m, re = this.subTemplateRe;
13111 while(m = re.exec(this.html)){
13112 var name = m[1], content = m[2];
13117 tpl : new Roo.Template(content)
13120 st[name] = st[subIndex];
13122 st[subIndex].tpl.compile();
13123 st[subIndex].tpl.call = this.call.createDelegate(this);
13126 this.subCount = subIndex;
13129 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13131 * The regular expression used to match sub templates
13135 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13138 * Applies the passed values to a child template.
13139 * @param {String/Number} name (optional) The name or index of the child template
13140 * @param {Array/Object} values The values to be applied to the template
13141 * @return {MasterTemplate} this
13143 add : function(name, values){
13144 if(arguments.length == 1){
13145 values = arguments[0];
13148 var s = this.subs[name];
13149 s.buffer[s.buffer.length] = s.tpl.apply(values);
13154 * Applies all the passed values to a child template.
13155 * @param {String/Number} name (optional) The name or index of the child template
13156 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13157 * @param {Boolean} reset (optional) True to reset the template first
13158 * @return {MasterTemplate} this
13160 fill : function(name, values, reset){
13162 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13170 for(var i = 0, len = values.length; i < len; i++){
13171 this.add(name, values[i]);
13177 * Resets the template for reuse
13178 * @return {MasterTemplate} this
13180 reset : function(){
13182 for(var i = 0; i < this.subCount; i++){
13188 applyTemplate : function(values){
13190 var replaceIndex = -1;
13191 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13192 return s[++replaceIndex].buffer.join("");
13194 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13197 apply : function(){
13198 return this.applyTemplate.apply(this, arguments);
13201 compile : function(){return this;}
13205 * Alias for fill().
13208 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13210 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13211 * var tpl = Roo.MasterTemplate.from('element-id');
13212 * @param {String/HTMLElement} el
13213 * @param {Object} config
13216 Roo.MasterTemplate.from = function(el, config){
13217 el = Roo.getDom(el);
13218 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13221 * Ext JS Library 1.1.1
13222 * Copyright(c) 2006-2007, Ext JS, LLC.
13224 * Originally Released Under LGPL - original licence link has changed is not relivant.
13227 * <script type="text/javascript">
13232 * @class Roo.util.CSS
13233 * Utility class for manipulating CSS rules
13236 Roo.util.CSS = function(){
13238 var doc = document;
13240 var camelRe = /(-[a-z])/gi;
13241 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13245 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13246 * tag and appended to the HEAD of the document.
13247 * @param {String|Object} cssText The text containing the css rules
13248 * @param {String} id An id to add to the stylesheet for later removal
13249 * @return {StyleSheet}
13251 createStyleSheet : function(cssText, id){
13253 var head = doc.getElementsByTagName("head")[0];
13254 var nrules = doc.createElement("style");
13255 nrules.setAttribute("type", "text/css");
13257 nrules.setAttribute("id", id);
13259 if (typeof(cssText) != 'string') {
13260 // support object maps..
13261 // not sure if this a good idea..
13262 // perhaps it should be merged with the general css handling
13263 // and handle js style props.
13264 var cssTextNew = [];
13265 for(var n in cssText) {
13267 for(var k in cssText[n]) {
13268 citems.push( k + ' : ' +cssText[n][k] + ';' );
13270 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13273 cssText = cssTextNew.join("\n");
13279 head.appendChild(nrules);
13280 ss = nrules.styleSheet;
13281 ss.cssText = cssText;
13284 nrules.appendChild(doc.createTextNode(cssText));
13286 nrules.cssText = cssText;
13288 head.appendChild(nrules);
13289 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13291 this.cacheStyleSheet(ss);
13296 * Removes a style or link tag by id
13297 * @param {String} id The id of the tag
13299 removeStyleSheet : function(id){
13300 var existing = doc.getElementById(id);
13302 existing.parentNode.removeChild(existing);
13307 * Dynamically swaps an existing stylesheet reference for a new one
13308 * @param {String} id The id of an existing link tag to remove
13309 * @param {String} url The href of the new stylesheet to include
13311 swapStyleSheet : function(id, url){
13312 this.removeStyleSheet(id);
13313 var ss = doc.createElement("link");
13314 ss.setAttribute("rel", "stylesheet");
13315 ss.setAttribute("type", "text/css");
13316 ss.setAttribute("id", id);
13317 ss.setAttribute("href", url);
13318 doc.getElementsByTagName("head")[0].appendChild(ss);
13322 * Refresh the rule cache if you have dynamically added stylesheets
13323 * @return {Object} An object (hash) of rules indexed by selector
13325 refreshCache : function(){
13326 return this.getRules(true);
13330 cacheStyleSheet : function(stylesheet){
13334 try{// try catch for cross domain access issue
13335 var ssRules = stylesheet.cssRules || stylesheet.rules;
13336 for(var j = ssRules.length-1; j >= 0; --j){
13337 rules[ssRules[j].selectorText] = ssRules[j];
13343 * Gets all css rules for the document
13344 * @param {Boolean} refreshCache true to refresh the internal cache
13345 * @return {Object} An object (hash) of rules indexed by selector
13347 getRules : function(refreshCache){
13348 if(rules == null || refreshCache){
13350 var ds = doc.styleSheets;
13351 for(var i =0, len = ds.length; i < len; i++){
13353 this.cacheStyleSheet(ds[i]);
13361 * Gets an an individual CSS rule by selector(s)
13362 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13363 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13364 * @return {CSSRule} The CSS rule or null if one is not found
13366 getRule : function(selector, refreshCache){
13367 var rs = this.getRules(refreshCache);
13368 if(!(selector instanceof Array)){
13369 return rs[selector];
13371 for(var i = 0; i < selector.length; i++){
13372 if(rs[selector[i]]){
13373 return rs[selector[i]];
13381 * Updates a rule property
13382 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13383 * @param {String} property The css property
13384 * @param {String} value The new value for the property
13385 * @return {Boolean} true If a rule was found and updated
13387 updateRule : function(selector, property, value){
13388 if(!(selector instanceof Array)){
13389 var rule = this.getRule(selector);
13391 rule.style[property.replace(camelRe, camelFn)] = value;
13395 for(var i = 0; i < selector.length; i++){
13396 if(this.updateRule(selector[i], property, value)){
13406 * Ext JS Library 1.1.1
13407 * Copyright(c) 2006-2007, Ext JS, LLC.
13409 * Originally Released Under LGPL - original licence link has changed is not relivant.
13412 * <script type="text/javascript">
13418 * @class Roo.util.ClickRepeater
13419 * @extends Roo.util.Observable
13421 * A wrapper class which can be applied to any element. Fires a "click" event while the
13422 * mouse is pressed. The interval between firings may be specified in the config but
13423 * defaults to 10 milliseconds.
13425 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13427 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13428 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13429 * Similar to an autorepeat key delay.
13430 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13431 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13432 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13433 * "interval" and "delay" are ignored. "immediate" is honored.
13434 * @cfg {Boolean} preventDefault True to prevent the default click event
13435 * @cfg {Boolean} stopDefault True to stop the default click event
13438 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13439 * 2007-02-02 jvs Renamed to ClickRepeater
13440 * 2007-02-03 jvs Modifications for FF Mac and Safari
13443 * @param {String/HTMLElement/Element} el The element to listen on
13444 * @param {Object} config
13446 Roo.util.ClickRepeater = function(el, config)
13448 this.el = Roo.get(el);
13449 this.el.unselectable();
13451 Roo.apply(this, config);
13456 * Fires when the mouse button is depressed.
13457 * @param {Roo.util.ClickRepeater} this
13459 "mousedown" : true,
13462 * Fires on a specified interval during the time the element is pressed.
13463 * @param {Roo.util.ClickRepeater} this
13468 * Fires when the mouse key is released.
13469 * @param {Roo.util.ClickRepeater} this
13474 this.el.on("mousedown", this.handleMouseDown, this);
13475 if(this.preventDefault || this.stopDefault){
13476 this.el.on("click", function(e){
13477 if(this.preventDefault){
13478 e.preventDefault();
13480 if(this.stopDefault){
13486 // allow inline handler
13488 this.on("click", this.handler, this.scope || this);
13491 Roo.util.ClickRepeater.superclass.constructor.call(this);
13494 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13497 preventDefault : true,
13498 stopDefault : false,
13502 handleMouseDown : function(){
13503 clearTimeout(this.timer);
13505 if(this.pressClass){
13506 this.el.addClass(this.pressClass);
13508 this.mousedownTime = new Date();
13510 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13511 this.el.on("mouseout", this.handleMouseOut, this);
13513 this.fireEvent("mousedown", this);
13514 this.fireEvent("click", this);
13516 this.timer = this.click.defer(this.delay || this.interval, this);
13520 click : function(){
13521 this.fireEvent("click", this);
13522 this.timer = this.click.defer(this.getInterval(), this);
13526 getInterval: function(){
13527 if(!this.accelerate){
13528 return this.interval;
13530 var pressTime = this.mousedownTime.getElapsed();
13531 if(pressTime < 500){
13533 }else if(pressTime < 1700){
13535 }else if(pressTime < 2600){
13537 }else if(pressTime < 3500){
13539 }else if(pressTime < 4400){
13541 }else if(pressTime < 5300){
13543 }else if(pressTime < 6200){
13551 handleMouseOut : function(){
13552 clearTimeout(this.timer);
13553 if(this.pressClass){
13554 this.el.removeClass(this.pressClass);
13556 this.el.on("mouseover", this.handleMouseReturn, this);
13560 handleMouseReturn : function(){
13561 this.el.un("mouseover", this.handleMouseReturn);
13562 if(this.pressClass){
13563 this.el.addClass(this.pressClass);
13569 handleMouseUp : function(){
13570 clearTimeout(this.timer);
13571 this.el.un("mouseover", this.handleMouseReturn);
13572 this.el.un("mouseout", this.handleMouseOut);
13573 Roo.get(document).un("mouseup", this.handleMouseUp);
13574 this.el.removeClass(this.pressClass);
13575 this.fireEvent("mouseup", this);
13579 * Ext JS Library 1.1.1
13580 * Copyright(c) 2006-2007, Ext JS, LLC.
13582 * Originally Released Under LGPL - original licence link has changed is not relivant.
13585 * <script type="text/javascript">
13590 * @class Roo.KeyNav
13591 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13592 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13593 * way to implement custom navigation schemes for any UI component.</p>
13594 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13595 * pageUp, pageDown, del, home, end. Usage:</p>
13597 var nav = new Roo.KeyNav("my-element", {
13598 "left" : function(e){
13599 this.moveLeft(e.ctrlKey);
13601 "right" : function(e){
13602 this.moveRight(e.ctrlKey);
13604 "enter" : function(e){
13611 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13612 * @param {Object} config The config
13614 Roo.KeyNav = function(el, config){
13615 this.el = Roo.get(el);
13616 Roo.apply(this, config);
13617 if(!this.disabled){
13618 this.disabled = true;
13623 Roo.KeyNav.prototype = {
13625 * @cfg {Boolean} disabled
13626 * True to disable this KeyNav instance (defaults to false)
13630 * @cfg {String} defaultEventAction
13631 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13632 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13633 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13635 defaultEventAction: "stopEvent",
13637 * @cfg {Boolean} forceKeyDown
13638 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13639 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13640 * handle keydown instead of keypress.
13642 forceKeyDown : false,
13645 prepareEvent : function(e){
13646 var k = e.getKey();
13647 var h = this.keyToHandler[k];
13648 //if(h && this[h]){
13649 // e.stopPropagation();
13651 if(Roo.isSafari && h && k >= 37 && k <= 40){
13657 relay : function(e){
13658 var k = e.getKey();
13659 var h = this.keyToHandler[k];
13661 if(this.doRelay(e, this[h], h) !== true){
13662 e[this.defaultEventAction]();
13668 doRelay : function(e, h, hname){
13669 return h.call(this.scope || this, e);
13672 // possible handlers
13686 // quick lookup hash
13703 * Enable this KeyNav
13705 enable: function(){
13707 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13708 // the EventObject will normalize Safari automatically
13709 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13710 this.el.on("keydown", this.relay, this);
13712 this.el.on("keydown", this.prepareEvent, this);
13713 this.el.on("keypress", this.relay, this);
13715 this.disabled = false;
13720 * Disable this KeyNav
13722 disable: function(){
13723 if(!this.disabled){
13724 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13725 this.el.un("keydown", this.relay);
13727 this.el.un("keydown", this.prepareEvent);
13728 this.el.un("keypress", this.relay);
13730 this.disabled = true;
13735 * Ext JS Library 1.1.1
13736 * Copyright(c) 2006-2007, Ext JS, LLC.
13738 * Originally Released Under LGPL - original licence link has changed is not relivant.
13741 * <script type="text/javascript">
13746 * @class Roo.KeyMap
13747 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13748 * The constructor accepts the same config object as defined by {@link #addBinding}.
13749 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13750 * combination it will call the function with this signature (if the match is a multi-key
13751 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13752 * A KeyMap can also handle a string representation of keys.<br />
13755 // map one key by key code
13756 var map = new Roo.KeyMap("my-element", {
13757 key: 13, // or Roo.EventObject.ENTER
13762 // map multiple keys to one action by string
13763 var map = new Roo.KeyMap("my-element", {
13769 // map multiple keys to multiple actions by strings and array of codes
13770 var map = new Roo.KeyMap("my-element", [
13773 fn: function(){ alert("Return was pressed"); }
13776 fn: function(){ alert('a, b or c was pressed'); }
13781 fn: function(){ alert('Control + shift + tab was pressed.'); }
13785 * <b>Note: A KeyMap starts enabled</b>
13787 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13788 * @param {Object} config The config (see {@link #addBinding})
13789 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13791 Roo.KeyMap = function(el, config, eventName){
13792 this.el = Roo.get(el);
13793 this.eventName = eventName || "keydown";
13794 this.bindings = [];
13796 this.addBinding(config);
13801 Roo.KeyMap.prototype = {
13803 * True to stop the event from bubbling and prevent the default browser action if the
13804 * key was handled by the KeyMap (defaults to false)
13810 * Add a new binding to this KeyMap. The following config object properties are supported:
13812 Property Type Description
13813 ---------- --------------- ----------------------------------------------------------------------
13814 key String/Array A single keycode or an array of keycodes to handle
13815 shift Boolean True to handle key only when shift is pressed (defaults to false)
13816 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13817 alt Boolean True to handle key only when alt is pressed (defaults to false)
13818 fn Function The function to call when KeyMap finds the expected key combination
13819 scope Object The scope of the callback function
13825 var map = new Roo.KeyMap(document, {
13826 key: Roo.EventObject.ENTER,
13831 //Add a new binding to the existing KeyMap later
13839 * @param {Object/Array} config A single KeyMap config or an array of configs
13841 addBinding : function(config){
13842 if(config instanceof Array){
13843 for(var i = 0, len = config.length; i < len; i++){
13844 this.addBinding(config[i]);
13848 var keyCode = config.key,
13849 shift = config.shift,
13850 ctrl = config.ctrl,
13853 scope = config.scope;
13854 if(typeof keyCode == "string"){
13856 var keyString = keyCode.toUpperCase();
13857 for(var j = 0, len = keyString.length; j < len; j++){
13858 ks.push(keyString.charCodeAt(j));
13862 var keyArray = keyCode instanceof Array;
13863 var handler = function(e){
13864 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13865 var k = e.getKey();
13867 for(var i = 0, len = keyCode.length; i < len; i++){
13868 if(keyCode[i] == k){
13869 if(this.stopEvent){
13872 fn.call(scope || window, k, e);
13878 if(this.stopEvent){
13881 fn.call(scope || window, k, e);
13886 this.bindings.push(handler);
13890 * Shorthand for adding a single key listener
13891 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13892 * following options:
13893 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13894 * @param {Function} fn The function to call
13895 * @param {Object} scope (optional) The scope of the function
13897 on : function(key, fn, scope){
13898 var keyCode, shift, ctrl, alt;
13899 if(typeof key == "object" && !(key instanceof Array)){
13918 handleKeyDown : function(e){
13919 if(this.enabled){ //just in case
13920 var b = this.bindings;
13921 for(var i = 0, len = b.length; i < len; i++){
13922 b[i].call(this, e);
13928 * Returns true if this KeyMap is enabled
13929 * @return {Boolean}
13931 isEnabled : function(){
13932 return this.enabled;
13936 * Enables this KeyMap
13938 enable: function(){
13940 this.el.on(this.eventName, this.handleKeyDown, this);
13941 this.enabled = true;
13946 * Disable this KeyMap
13948 disable: function(){
13950 this.el.removeListener(this.eventName, this.handleKeyDown, this);
13951 this.enabled = false;
13956 * Ext JS Library 1.1.1
13957 * Copyright(c) 2006-2007, Ext JS, LLC.
13959 * Originally Released Under LGPL - original licence link has changed is not relivant.
13962 * <script type="text/javascript">
13967 * @class Roo.util.TextMetrics
13968 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
13969 * wide, in pixels, a given block of text will be.
13972 Roo.util.TextMetrics = function(){
13976 * Measures the size of the specified text
13977 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
13978 * that can affect the size of the rendered text
13979 * @param {String} text The text to measure
13980 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13981 * in order to accurately measure the text height
13982 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13984 measure : function(el, text, fixedWidth){
13986 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
13989 shared.setFixedWidth(fixedWidth || 'auto');
13990 return shared.getSize(text);
13994 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
13995 * the overhead of multiple calls to initialize the style properties on each measurement.
13996 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
13997 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13998 * in order to accurately measure the text height
13999 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14001 createInstance : function(el, fixedWidth){
14002 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14009 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14010 var ml = new Roo.Element(document.createElement('div'));
14011 document.body.appendChild(ml.dom);
14012 ml.position('absolute');
14013 ml.setLeftTop(-1000, -1000);
14017 ml.setWidth(fixedWidth);
14022 * Returns the size of the specified text based on the internal element's style and width properties
14023 * @memberOf Roo.util.TextMetrics.Instance#
14024 * @param {String} text The text to measure
14025 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14027 getSize : function(text){
14029 var s = ml.getSize();
14035 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14036 * that can affect the size of the rendered text
14037 * @memberOf Roo.util.TextMetrics.Instance#
14038 * @param {String/HTMLElement} el The element, dom node or id
14040 bind : function(el){
14042 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14047 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14048 * to set a fixed width in order to accurately measure the text height.
14049 * @memberOf Roo.util.TextMetrics.Instance#
14050 * @param {Number} width The width to set on the element
14052 setFixedWidth : function(width){
14053 ml.setWidth(width);
14057 * Returns the measured width of the specified text
14058 * @memberOf Roo.util.TextMetrics.Instance#
14059 * @param {String} text The text to measure
14060 * @return {Number} width The width in pixels
14062 getWidth : function(text){
14063 ml.dom.style.width = 'auto';
14064 return this.getSize(text).width;
14068 * Returns the measured height of the specified text. For multiline text, be sure to call
14069 * {@link #setFixedWidth} if necessary.
14070 * @memberOf Roo.util.TextMetrics.Instance#
14071 * @param {String} text The text to measure
14072 * @return {Number} height The height in pixels
14074 getHeight : function(text){
14075 return this.getSize(text).height;
14079 instance.bind(bindTo);
14084 // backwards compat
14085 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14087 * Ext JS Library 1.1.1
14088 * Copyright(c) 2006-2007, Ext JS, LLC.
14090 * Originally Released Under LGPL - original licence link has changed is not relivant.
14093 * <script type="text/javascript">
14097 * @class Roo.state.Provider
14098 * Abstract base class for state provider implementations. This class provides methods
14099 * for encoding and decoding <b>typed</b> variables including dates and defines the
14100 * Provider interface.
14102 Roo.state.Provider = function(){
14104 * @event statechange
14105 * Fires when a state change occurs.
14106 * @param {Provider} this This state provider
14107 * @param {String} key The state key which was changed
14108 * @param {String} value The encoded value for the state
14111 "statechange": true
14114 Roo.state.Provider.superclass.constructor.call(this);
14116 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14118 * Returns the current value for a key
14119 * @param {String} name The key name
14120 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14121 * @return {Mixed} The state data
14123 get : function(name, defaultValue){
14124 return typeof this.state[name] == "undefined" ?
14125 defaultValue : this.state[name];
14129 * Clears a value from the state
14130 * @param {String} name The key name
14132 clear : function(name){
14133 delete this.state[name];
14134 this.fireEvent("statechange", this, name, null);
14138 * Sets the value for a key
14139 * @param {String} name The key name
14140 * @param {Mixed} value The value to set
14142 set : function(name, value){
14143 this.state[name] = value;
14144 this.fireEvent("statechange", this, name, value);
14148 * Decodes a string previously encoded with {@link #encodeValue}.
14149 * @param {String} value The value to decode
14150 * @return {Mixed} The decoded value
14152 decodeValue : function(cookie){
14153 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14154 var matches = re.exec(unescape(cookie));
14155 if(!matches || !matches[1]) return; // non state cookie
14156 var type = matches[1];
14157 var v = matches[2];
14160 return parseFloat(v);
14162 return new Date(Date.parse(v));
14167 var values = v.split("^");
14168 for(var i = 0, len = values.length; i < len; i++){
14169 all.push(this.decodeValue(values[i]));
14174 var values = v.split("^");
14175 for(var i = 0, len = values.length; i < len; i++){
14176 var kv = values[i].split("=");
14177 all[kv[0]] = this.decodeValue(kv[1]);
14186 * Encodes a value including type information. Decode with {@link #decodeValue}.
14187 * @param {Mixed} value The value to encode
14188 * @return {String} The encoded value
14190 encodeValue : function(v){
14192 if(typeof v == "number"){
14194 }else if(typeof v == "boolean"){
14195 enc = "b:" + (v ? "1" : "0");
14196 }else if(v instanceof Date){
14197 enc = "d:" + v.toGMTString();
14198 }else if(v instanceof Array){
14200 for(var i = 0, len = v.length; i < len; i++){
14201 flat += this.encodeValue(v[i]);
14202 if(i != len-1) flat += "^";
14205 }else if(typeof v == "object"){
14208 if(typeof v[key] != "function"){
14209 flat += key + "=" + this.encodeValue(v[key]) + "^";
14212 enc = "o:" + flat.substring(0, flat.length-1);
14216 return escape(enc);
14222 * Ext JS Library 1.1.1
14223 * Copyright(c) 2006-2007, Ext JS, LLC.
14225 * Originally Released Under LGPL - original licence link has changed is not relivant.
14228 * <script type="text/javascript">
14231 * @class Roo.state.Manager
14232 * This is the global state manager. By default all components that are "state aware" check this class
14233 * for state information if you don't pass them a custom state provider. In order for this class
14234 * to be useful, it must be initialized with a provider when your application initializes.
14236 // in your initialization function
14238 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14240 // supposed you have a {@link Roo.BorderLayout}
14241 var layout = new Roo.BorderLayout(...);
14242 layout.restoreState();
14243 // or a {Roo.BasicDialog}
14244 var dialog = new Roo.BasicDialog(...);
14245 dialog.restoreState();
14249 Roo.state.Manager = function(){
14250 var provider = new Roo.state.Provider();
14254 * Configures the default state provider for your application
14255 * @param {Provider} stateProvider The state provider to set
14257 setProvider : function(stateProvider){
14258 provider = stateProvider;
14262 * Returns the current value for a key
14263 * @param {String} name The key name
14264 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14265 * @return {Mixed} The state data
14267 get : function(key, defaultValue){
14268 return provider.get(key, defaultValue);
14272 * Sets the value for a key
14273 * @param {String} name The key name
14274 * @param {Mixed} value The state data
14276 set : function(key, value){
14277 provider.set(key, value);
14281 * Clears a value from the state
14282 * @param {String} name The key name
14284 clear : function(key){
14285 provider.clear(key);
14289 * Gets the currently configured state provider
14290 * @return {Provider} The state provider
14292 getProvider : function(){
14299 * Ext JS Library 1.1.1
14300 * Copyright(c) 2006-2007, Ext JS, LLC.
14302 * Originally Released Under LGPL - original licence link has changed is not relivant.
14305 * <script type="text/javascript">
14308 * @class Roo.state.CookieProvider
14309 * @extends Roo.state.Provider
14310 * The default Provider implementation which saves state via cookies.
14313 var cp = new Roo.state.CookieProvider({
14315 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14316 domain: "roojs.com"
14318 Roo.state.Manager.setProvider(cp);
14320 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14321 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14322 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14323 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14324 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14325 * domain the page is running on including the 'www' like 'www.roojs.com')
14326 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14328 * Create a new CookieProvider
14329 * @param {Object} config The configuration object
14331 Roo.state.CookieProvider = function(config){
14332 Roo.state.CookieProvider.superclass.constructor.call(this);
14334 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14335 this.domain = null;
14336 this.secure = false;
14337 Roo.apply(this, config);
14338 this.state = this.readCookies();
14341 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14343 set : function(name, value){
14344 if(typeof value == "undefined" || value === null){
14348 this.setCookie(name, value);
14349 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14353 clear : function(name){
14354 this.clearCookie(name);
14355 Roo.state.CookieProvider.superclass.clear.call(this, name);
14359 readCookies : function(){
14361 var c = document.cookie + ";";
14362 var re = /\s?(.*?)=(.*?);/g;
14364 while((matches = re.exec(c)) != null){
14365 var name = matches[1];
14366 var value = matches[2];
14367 if(name && name.substring(0,3) == "ys-"){
14368 cookies[name.substr(3)] = this.decodeValue(value);
14375 setCookie : function(name, value){
14376 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14377 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14378 ((this.path == null) ? "" : ("; path=" + this.path)) +
14379 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14380 ((this.secure == true) ? "; secure" : "");
14384 clearCookie : function(name){
14385 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14386 ((this.path == null) ? "" : ("; path=" + this.path)) +
14387 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14388 ((this.secure == true) ? "; secure" : "");