4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
89 * Turn on debugging output (currently only the factory uses this)
96 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
99 enableGarbageCollector : true,
102 * True to automatically purge event listeners after uncaching an element (defaults to false).
103 * Note: this only happens if enableGarbageCollector is true.
106 enableListenerCollection:false,
109 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
110 * the IE insecure content warning (defaults to javascript:false).
113 SSL_SECURE_URL : "javascript:false",
116 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
117 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
120 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
122 emptyFn : function(){},
125 * Copies all the properties of config to obj if they don't already exist.
126 * @param {Object} obj The receiver of the properties
127 * @param {Object} config The source of the properties
128 * @return {Object} returns obj
130 applyIf : function(o, c){
133 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
140 * Applies event listeners to elements by selectors when the document is ready.
141 * The event name is specified with an @ suffix.
144 // add a listener for click on all anchors in element with id foo
145 '#foo a@click' : function(e, t){
149 // add the same listener to multiple selectors (separated by comma BEFORE the @)
150 '#foo a, #bar span.some-class@mouseover' : function(){
155 * @param {Object} obj The list of behaviors to apply
157 addBehaviors : function(o){
159 Roo.onReady(function(){
164 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
166 var parts = b.split('@');
167 if(parts[1]){ // for Object prototype breakers
170 cache[s] = Roo.select(s);
172 cache[s].on(parts[1], o[b]);
179 * Generates unique ids. If the element already has an id, it is unchanged
180 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
181 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
182 * @return {String} The generated Id.
184 id : function(el, prefix){
185 prefix = prefix || "roo-gen";
187 var id = prefix + (++idSeed);
188 return el ? (el.id ? el.id : (el.id = id)) : id;
193 * Extends one class with another class and optionally overrides members with the passed literal. This class
194 * also adds the function "override()" to the class that can be used to override
195 * members on an instance.
196 * @param {Object} subclass The class inheriting the functionality
197 * @param {Object} superclass The class being extended
198 * @param {Object} overrides (optional) A literal with members
203 var io = function(o){
208 return function(sb, sp, overrides){
209 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
212 sb = function(){sp.apply(this, arguments);};
214 var F = function(){}, sbp, spp = sp.prototype;
216 sbp = sb.prototype = new F();
220 if(spp.constructor == Object.prototype.constructor){
225 sb.override = function(o){
229 Roo.override(sb, overrides);
235 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
237 Roo.override(MyClass, {
238 newMethod1: function(){
241 newMethod2: function(foo){
246 * @param {Object} origclass The class to override
247 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
248 * containing one or more methods.
251 override : function(origclass, overrides){
253 var p = origclass.prototype;
254 for(var method in overrides){
255 p[method] = overrides[method];
260 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
262 Roo.namespace('Company', 'Company.data');
263 Company.Widget = function() { ... }
264 Company.data.CustomStore = function(config) { ... }
266 * @param {String} namespace1
267 * @param {String} namespace2
268 * @param {String} etc
271 namespace : function(){
272 var a=arguments, o=null, i, j, d, rt;
273 for (i=0; i<a.length; ++i) {
277 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
278 for (j=1; j<d.length; ++j) {
279 o[d[j]]=o[d[j]] || {};
285 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
287 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
288 Roo.factory(conf, Roo.data);
290 * @param {String} classname
291 * @param {String} namespace (optional)
295 factory : function(c, ns)
297 // no xtype, no ns or c.xns - or forced off by c.xns
298 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
301 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
302 if (c.constructor == ns[c.xtype]) {// already created...
306 if (Roo.debug) Roo.log("Roo.Factory(" + c.xtype + ")");
307 var ret = new ns[c.xtype](c);
311 c.xns = false; // prevent recursion..
315 * Logs to console if it can.
317 * @param {String|Object} string
322 if ((typeof(console) == 'undefined') || (typeof(console.log) == 'undefined')) {
329 * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2". Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
333 urlEncode : function(o){
339 var ov = o[key], k = encodeURIComponent(key);
340 var type = typeof ov;
341 if(type == 'undefined'){
343 }else if(type != "function" && type != "object"){
344 buf.push(k, "=", encodeURIComponent(ov), "&");
345 }else if(ov instanceof Array){
347 for(var i = 0, len = ov.length; i < len; i++) {
348 buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
360 * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
361 * @param {String} string
362 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
363 * @return {Object} A literal with members
365 urlDecode : function(string, overwrite){
366 if(!string || !string.length){
370 var pairs = string.split('&');
371 var pair, name, value;
372 for(var i = 0, len = pairs.length; i < len; i++){
373 pair = pairs[i].split('=');
374 name = decodeURIComponent(pair[0]);
375 value = decodeURIComponent(pair[1]);
376 if(overwrite !== true){
377 if(typeof obj[name] == "undefined"){
379 }else if(typeof obj[name] == "string"){
380 obj[name] = [obj[name]];
381 obj[name].push(value);
383 obj[name].push(value);
393 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
394 * passed array is not really an array, your function is called once with it.
395 * The supplied function is called with (Object item, Number index, Array allItems).
396 * @param {Array/NodeList/Mixed} array
397 * @param {Function} fn
398 * @param {Object} scope
400 each : function(array, fn, scope){
401 if(typeof array.length == "undefined" || typeof array == "string"){
404 for(var i = 0, len = array.length; i < len; i++){
405 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
410 combine : function(){
411 var as = arguments, l = as.length, r = [];
412 for(var i = 0; i < l; i++){
414 if(a instanceof Array){
416 }else if(a.length !== undefined && !a.substr){
417 r = r.concat(Array.prototype.slice.call(a, 0));
426 * Escapes the passed string for use in a regular expression
427 * @param {String} str
430 escapeRe : function(s) {
431 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
435 callback : function(cb, scope, args, delay){
436 if(typeof cb == "function"){
438 cb.defer(delay, scope, args || []);
440 cb.apply(scope, args || []);
446 * Return the dom node for the passed string (id), dom node, or Roo.Element
447 * @param {String/HTMLElement/Roo.Element} el
448 * @return HTMLElement
450 getDom : function(el){
454 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
458 * Shorthand for {@link Roo.ComponentMgr#get}
460 * @return Roo.Component
462 getCmp : function(id){
463 return Roo.ComponentMgr.get(id);
466 num : function(v, defaultValue){
467 if(typeof v != 'number'){
473 destroy : function(){
474 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
478 as.removeAllListeners();
482 if(typeof as.purgeListeners == 'function'){
485 if(typeof as.destroy == 'function'){
492 // inpired by a similar function in mootools library
494 * Returns the type of object that is passed in. If the object passed in is null or undefined it
495 * return false otherwise it returns one of the following values:<ul>
496 * <li><b>string</b>: If the object passed is a string</li>
497 * <li><b>number</b>: If the object passed is a number</li>
498 * <li><b>boolean</b>: If the object passed is a boolean value</li>
499 * <li><b>function</b>: If the object passed is a function reference</li>
500 * <li><b>object</b>: If the object passed is an object</li>
501 * <li><b>array</b>: If the object passed is an array</li>
502 * <li><b>regexp</b>: If the object passed is a regular expression</li>
503 * <li><b>element</b>: If the object passed is a DOM Element</li>
504 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
505 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
506 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
507 * @param {Mixed} object
511 if(o === undefined || o === null){
518 if(t == 'object' && o.nodeName) {
520 case 1: return 'element';
521 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
524 if(t == 'object' || t == 'function') {
525 switch(o.constructor) {
526 case Array: return 'array';
527 case RegExp: return 'regexp';
529 if(typeof o.length == 'number' && typeof o.item == 'function') {
537 * Returns true if the passed value is null, undefined or an empty string (optional).
538 * @param {Mixed} value The value to test
539 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
542 isEmpty : function(v, allowBlank){
543 return v === null || v === undefined || (!allowBlank ? v === '' : false);
557 isBorderBox : isBorderBox,
559 isWindows : isWindows,
566 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
567 * you may want to set this to true.
570 useShims : ((isIE && !isIE7) || (isGecko && isMac)),
575 * Selects a single element as a Roo Element
576 * This is about as close as you can get to jQuery's $('do crazy stuff')
577 * @param {String} selector The selector/xpath query
578 * @param {Node} root (optional) The start of the query (defaults to document).
579 * @return {Roo.Element}
581 selectNode : function(selector, root)
583 var node = Roo.DomQuery.selectNode(selector,root);
584 return node ? Roo.get(node) : new Roo.Element(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){
7825 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7830 * Removes an event handler from this element
7831 * @param {String} eventName the type of event to remove
7832 * @param {Function} fn the method the event invokes
7833 * @return {Roo.Element} this
7835 removeListener : function(eventName, fn){
7836 Roo.EventManager.removeListener(this.dom, eventName, fn);
7841 * Removes all previous added listeners from this element
7842 * @return {Roo.Element} this
7844 removeAllListeners : function(){
7845 E.purgeElement(this.dom);
7849 relayEvent : function(eventName, observable){
7850 this.on(eventName, function(e){
7851 observable.fireEvent(eventName, e);
7856 * Set the opacity of the element
7857 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7858 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7859 * @return {Roo.Element} this
7861 setOpacity : function(opacity, animate){
7863 var s = this.dom.style;
7866 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7867 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7869 s.opacity = opacity;
7872 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7878 * Gets the left X coordinate
7879 * @param {Boolean} local True to get the local css position instead of page coordinate
7882 getLeft : function(local){
7886 return parseInt(this.getStyle("left"), 10) || 0;
7891 * Gets the right X coordinate of the element (element X position + element width)
7892 * @param {Boolean} local True to get the local css position instead of page coordinate
7895 getRight : function(local){
7897 return this.getX() + this.getWidth();
7899 return (this.getLeft(true) + this.getWidth()) || 0;
7904 * Gets the top Y coordinate
7905 * @param {Boolean} local True to get the local css position instead of page coordinate
7908 getTop : function(local) {
7912 return parseInt(this.getStyle("top"), 10) || 0;
7917 * Gets the bottom Y coordinate of the element (element Y position + element height)
7918 * @param {Boolean} local True to get the local css position instead of page coordinate
7921 getBottom : function(local){
7923 return this.getY() + this.getHeight();
7925 return (this.getTop(true) + this.getHeight()) || 0;
7930 * Initializes positioning on this element. If a desired position is not passed, it will make the
7931 * the element positioned relative IF it is not already positioned.
7932 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7933 * @param {Number} zIndex (optional) The zIndex to apply
7934 * @param {Number} x (optional) Set the page X position
7935 * @param {Number} y (optional) Set the page Y position
7937 position : function(pos, zIndex, x, y){
7939 if(this.getStyle('position') == 'static'){
7940 this.setStyle('position', 'relative');
7943 this.setStyle("position", pos);
7946 this.setStyle("z-index", zIndex);
7948 if(x !== undefined && y !== undefined){
7950 }else if(x !== undefined){
7952 }else if(y !== undefined){
7958 * Clear positioning back to the default when the document was loaded
7959 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7960 * @return {Roo.Element} this
7962 clearPositioning : function(value){
7970 "position" : "static"
7976 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7977 * snapshot before performing an update and then restoring the element.
7980 getPositioning : function(){
7981 var l = this.getStyle("left");
7982 var t = this.getStyle("top");
7984 "position" : this.getStyle("position"),
7986 "right" : l ? "" : this.getStyle("right"),
7988 "bottom" : t ? "" : this.getStyle("bottom"),
7989 "z-index" : this.getStyle("z-index")
7994 * Gets the width of the border(s) for the specified side(s)
7995 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7996 * passing lr would get the border (l)eft width + the border (r)ight width.
7997 * @return {Number} The width of the sides passed added together
7999 getBorderWidth : function(side){
8000 return this.addStyles(side, El.borders);
8004 * Gets the width of the padding(s) for the specified side(s)
8005 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
8006 * passing lr would get the padding (l)eft + the padding (r)ight.
8007 * @return {Number} The padding of the sides passed added together
8009 getPadding : function(side){
8010 return this.addStyles(side, El.paddings);
8014 * Set positioning with an object returned by getPositioning().
8015 * @param {Object} posCfg
8016 * @return {Roo.Element} this
8018 setPositioning : function(pc){
8019 this.applyStyles(pc);
8020 if(pc.right == "auto"){
8021 this.dom.style.right = "";
8023 if(pc.bottom == "auto"){
8024 this.dom.style.bottom = "";
8030 fixDisplay : function(){
8031 if(this.getStyle("display") == "none"){
8032 this.setStyle("visibility", "hidden");
8033 this.setStyle("display", this.originalDisplay); // first try reverting to default
8034 if(this.getStyle("display") == "none"){ // if that fails, default to block
8035 this.setStyle("display", "block");
8041 * Quick set left and top adding default units
8042 * @param {String} left The left CSS property value
8043 * @param {String} top The top CSS property value
8044 * @return {Roo.Element} this
8046 setLeftTop : function(left, top){
8047 this.dom.style.left = this.addUnits(left);
8048 this.dom.style.top = this.addUnits(top);
8053 * Move this element relative to its current position.
8054 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
8055 * @param {Number} distance How far to move the element in pixels
8056 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8057 * @return {Roo.Element} this
8059 move : function(direction, distance, animate){
8060 var xy = this.getXY();
8061 direction = direction.toLowerCase();
8065 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8069 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8074 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8079 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8086 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8087 * @return {Roo.Element} this
8090 if(!this.isClipped){
8091 this.isClipped = true;
8092 this.originalClip = {
8093 "o": this.getStyle("overflow"),
8094 "x": this.getStyle("overflow-x"),
8095 "y": this.getStyle("overflow-y")
8097 this.setStyle("overflow", "hidden");
8098 this.setStyle("overflow-x", "hidden");
8099 this.setStyle("overflow-y", "hidden");
8105 * Return clipping (overflow) to original clipping before clip() was called
8106 * @return {Roo.Element} this
8108 unclip : function(){
8110 this.isClipped = false;
8111 var o = this.originalClip;
8112 if(o.o){this.setStyle("overflow", o.o);}
8113 if(o.x){this.setStyle("overflow-x", o.x);}
8114 if(o.y){this.setStyle("overflow-y", o.y);}
8121 * Gets the x,y coordinates specified by the anchor position on the element.
8122 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8123 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8124 * {width: (target width), height: (target height)} (defaults to the element's current size)
8125 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8126 * @return {Array} [x, y] An array containing the element's x and y coordinates
8128 getAnchorXY : function(anchor, local, s){
8129 //Passing a different size is useful for pre-calculating anchors,
8130 //especially for anchored animations that change the el size.
8132 var w, h, vp = false;
8135 if(d == document.body || d == document){
8137 w = D.getViewWidth(); h = D.getViewHeight();
8139 w = this.getWidth(); h = this.getHeight();
8142 w = s.width; h = s.height;
8144 var x = 0, y = 0, r = Math.round;
8145 switch((anchor || "tl").toLowerCase()){
8187 var sc = this.getScroll();
8188 return [x + sc.left, y + sc.top];
8190 //Add the element's offset xy
8191 var o = this.getXY();
8192 return [x+o[0], y+o[1]];
8196 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8197 * supported position values.
8198 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8199 * @param {String} position The position to align to.
8200 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8201 * @return {Array} [x, y]
8203 getAlignToXY : function(el, p, o){
8207 throw "Element.alignTo with an element that doesn't exist";
8209 var c = false; //constrain to viewport
8210 var p1 = "", p2 = "";
8217 }else if(p.indexOf("-") == -1){
8220 p = p.toLowerCase();
8221 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8223 throw "Element.alignTo with an invalid alignment " + p;
8225 p1 = m[1]; p2 = m[2]; c = !!m[3];
8227 //Subtract the aligned el's internal xy from the target's offset xy
8228 //plus custom offset to get the aligned el's new offset xy
8229 var a1 = this.getAnchorXY(p1, true);
8230 var a2 = el.getAnchorXY(p2, false);
8231 var x = a2[0] - a1[0] + o[0];
8232 var y = a2[1] - a1[1] + o[1];
8234 //constrain the aligned el to viewport if necessary
8235 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8236 // 5px of margin for ie
8237 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8239 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8240 //perpendicular to the vp border, allow the aligned el to slide on that border,
8241 //otherwise swap the aligned el to the opposite border of the target.
8242 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8243 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8244 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8245 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8248 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8249 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8251 if((x+w) > dw + scrollX){
8252 x = swapX ? r.left-w : dw+scrollX-w;
8255 x = swapX ? r.right : scrollX;
8257 if((y+h) > dh + scrollY){
8258 y = swapY ? r.top-h : dh+scrollY-h;
8261 y = swapY ? r.bottom : scrollY;
8268 getConstrainToXY : function(){
8269 var os = {top:0, left:0, bottom:0, right: 0};
8271 return function(el, local, offsets, proposedXY){
8273 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8275 var vw, vh, vx = 0, vy = 0;
8276 if(el.dom == document.body || el.dom == document){
8277 vw = Roo.lib.Dom.getViewWidth();
8278 vh = Roo.lib.Dom.getViewHeight();
8280 vw = el.dom.clientWidth;
8281 vh = el.dom.clientHeight;
8283 var vxy = el.getXY();
8289 var s = el.getScroll();
8291 vx += offsets.left + s.left;
8292 vy += offsets.top + s.top;
8294 vw -= offsets.right;
8295 vh -= offsets.bottom;
8300 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8301 var x = xy[0], y = xy[1];
8302 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8304 // only move it if it needs it
8307 // first validate right/bottom
8316 // then make sure top/left isn't negative
8325 return moved ? [x, y] : false;
8330 adjustForConstraints : function(xy, parent, offsets){
8331 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8335 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8336 * document it aligns it to the viewport.
8337 * The position parameter is optional, and can be specified in any one of the following formats:
8339 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8340 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8341 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8342 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8343 * <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
8344 * element's anchor point, and the second value is used as the target's anchor point.</li>
8346 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8347 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8348 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8349 * that specified in order to enforce the viewport constraints.
8350 * Following are all of the supported anchor positions:
8353 ----- -----------------------------
8354 tl The top left corner (default)
8355 t The center of the top edge
8356 tr The top right corner
8357 l The center of the left edge
8358 c In the center of the element
8359 r The center of the right edge
8360 bl The bottom left corner
8361 b The center of the bottom edge
8362 br The bottom right corner
8366 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8367 el.alignTo("other-el");
8369 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8370 el.alignTo("other-el", "tr?");
8372 // align the bottom right corner of el with the center left edge of other-el
8373 el.alignTo("other-el", "br-l?");
8375 // align the center of el with the bottom left corner of other-el and
8376 // adjust the x position by -6 pixels (and the y position by 0)
8377 el.alignTo("other-el", "c-bl", [-6, 0]);
8379 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8380 * @param {String} position The position to align to.
8381 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8382 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8383 * @return {Roo.Element} this
8385 alignTo : function(element, position, offsets, animate){
8386 var xy = this.getAlignToXY(element, position, offsets);
8387 this.setXY(xy, this.preanim(arguments, 3));
8392 * Anchors an element to another element and realigns it when the window is resized.
8393 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8394 * @param {String} position The position to align to.
8395 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8396 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8397 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8398 * is a number, it is used as the buffer delay (defaults to 50ms).
8399 * @param {Function} callback The function to call after the animation finishes
8400 * @return {Roo.Element} this
8402 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8403 var action = function(){
8404 this.alignTo(el, alignment, offsets, animate);
8405 Roo.callback(callback, this);
8407 Roo.EventManager.onWindowResize(action, this);
8408 var tm = typeof monitorScroll;
8409 if(tm != 'undefined'){
8410 Roo.EventManager.on(window, 'scroll', action, this,
8411 {buffer: tm == 'number' ? monitorScroll : 50});
8413 action.call(this); // align immediately
8417 * Clears any opacity settings from this element. Required in some cases for IE.
8418 * @return {Roo.Element} this
8420 clearOpacity : function(){
8421 if (window.ActiveXObject) {
8422 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8423 this.dom.style.filter = "";
8426 this.dom.style.opacity = "";
8427 this.dom.style["-moz-opacity"] = "";
8428 this.dom.style["-khtml-opacity"] = "";
8434 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8435 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8436 * @return {Roo.Element} this
8438 hide : function(animate){
8439 this.setVisible(false, this.preanim(arguments, 0));
8444 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8445 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8446 * @return {Roo.Element} this
8448 show : function(animate){
8449 this.setVisible(true, this.preanim(arguments, 0));
8454 * @private Test if size has a unit, otherwise appends the default
8456 addUnits : function(size){
8457 return Roo.Element.addUnits(size, this.defaultUnit);
8461 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8462 * @return {Roo.Element} this
8464 beginMeasure : function(){
8466 if(el.offsetWidth || el.offsetHeight){
8467 return this; // offsets work already
8470 var p = this.dom, b = document.body; // start with this element
8471 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8472 var pe = Roo.get(p);
8473 if(pe.getStyle('display') == 'none'){
8474 changed.push({el: p, visibility: pe.getStyle("visibility")});
8475 p.style.visibility = "hidden";
8476 p.style.display = "block";
8480 this._measureChanged = changed;
8486 * Restores displays to before beginMeasure was called
8487 * @return {Roo.Element} this
8489 endMeasure : function(){
8490 var changed = this._measureChanged;
8492 for(var i = 0, len = changed.length; i < len; i++) {
8494 r.el.style.visibility = r.visibility;
8495 r.el.style.display = "none";
8497 this._measureChanged = null;
8503 * Update the innerHTML of this element, optionally searching for and processing scripts
8504 * @param {String} html The new HTML
8505 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8506 * @param {Function} callback For async script loading you can be noticed when the update completes
8507 * @return {Roo.Element} this
8509 update : function(html, loadScripts, callback){
8510 if(typeof html == "undefined"){
8513 if(loadScripts !== true){
8514 this.dom.innerHTML = html;
8515 if(typeof callback == "function"){
8523 html += '<span id="' + id + '"></span>';
8525 E.onAvailable(id, function(){
8526 var hd = document.getElementsByTagName("head")[0];
8527 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8528 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8529 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8532 while(match = re.exec(html)){
8533 var attrs = match[1];
8534 var srcMatch = attrs ? attrs.match(srcRe) : false;
8535 if(srcMatch && srcMatch[2]){
8536 var s = document.createElement("script");
8537 s.src = srcMatch[2];
8538 var typeMatch = attrs.match(typeRe);
8539 if(typeMatch && typeMatch[2]){
8540 s.type = typeMatch[2];
8543 }else if(match[2] && match[2].length > 0){
8544 if(window.execScript) {
8545 window.execScript(match[2]);
8553 window.eval(match[2]);
8557 var el = document.getElementById(id);
8558 if(el){el.parentNode.removeChild(el);}
8559 if(typeof callback == "function"){
8563 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8568 * Direct access to the UpdateManager update() method (takes the same parameters).
8569 * @param {String/Function} url The url for this request or a function to call to get the url
8570 * @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}
8571 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8572 * @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.
8573 * @return {Roo.Element} this
8576 var um = this.getUpdateManager();
8577 um.update.apply(um, arguments);
8582 * Gets this element's UpdateManager
8583 * @return {Roo.UpdateManager} The UpdateManager
8585 getUpdateManager : function(){
8586 if(!this.updateManager){
8587 this.updateManager = new Roo.UpdateManager(this);
8589 return this.updateManager;
8593 * Disables text selection for this element (normalized across browsers)
8594 * @return {Roo.Element} this
8596 unselectable : function(){
8597 this.dom.unselectable = "on";
8598 this.swallowEvent("selectstart", true);
8599 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8600 this.addClass("x-unselectable");
8605 * Calculates the x, y to center this element on the screen
8606 * @return {Array} The x, y values [x, y]
8608 getCenterXY : function(){
8609 return this.getAlignToXY(document, 'c-c');
8613 * Centers the Element in either the viewport, or another Element.
8614 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8616 center : function(centerIn){
8617 this.alignTo(centerIn || document, 'c-c');
8622 * Tests various css rules/browsers to determine if this element uses a border box
8625 isBorderBox : function(){
8626 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8630 * Return a box {x, y, width, height} that can be used to set another elements
8631 * size/location to match this element.
8632 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8633 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8634 * @return {Object} box An object in the format {x, y, width, height}
8636 getBox : function(contentBox, local){
8641 var left = parseInt(this.getStyle("left"), 10) || 0;
8642 var top = parseInt(this.getStyle("top"), 10) || 0;
8645 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8647 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8649 var l = this.getBorderWidth("l")+this.getPadding("l");
8650 var r = this.getBorderWidth("r")+this.getPadding("r");
8651 var t = this.getBorderWidth("t")+this.getPadding("t");
8652 var b = this.getBorderWidth("b")+this.getPadding("b");
8653 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)};
8655 bx.right = bx.x + bx.width;
8656 bx.bottom = bx.y + bx.height;
8661 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8662 for more information about the sides.
8663 * @param {String} sides
8666 getFrameWidth : function(sides, onlyContentBox){
8667 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8671 * 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.
8672 * @param {Object} box The box to fill {x, y, width, height}
8673 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8674 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8675 * @return {Roo.Element} this
8677 setBox : function(box, adjust, animate){
8678 var w = box.width, h = box.height;
8679 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8680 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8681 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8683 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8688 * Forces the browser to repaint this element
8689 * @return {Roo.Element} this
8691 repaint : function(){
8693 this.addClass("x-repaint");
8694 setTimeout(function(){
8695 Roo.get(dom).removeClass("x-repaint");
8701 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8702 * then it returns the calculated width of the sides (see getPadding)
8703 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8704 * @return {Object/Number}
8706 getMargins : function(side){
8709 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8710 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8711 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8712 right: parseInt(this.getStyle("margin-right"), 10) || 0
8715 return this.addStyles(side, El.margins);
8720 addStyles : function(sides, styles){
8722 for(var i = 0, len = sides.length; i < len; i++){
8723 v = this.getStyle(styles[sides.charAt(i)]);
8725 w = parseInt(v, 10);
8733 * Creates a proxy element of this element
8734 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8735 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8736 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8737 * @return {Roo.Element} The new proxy element
8739 createProxy : function(config, renderTo, matchBox){
8741 renderTo = Roo.getDom(renderTo);
8743 renderTo = document.body;
8745 config = typeof config == "object" ?
8746 config : {tag : "div", cls: config};
8747 var proxy = Roo.DomHelper.append(renderTo, config, true);
8749 proxy.setBox(this.getBox());
8755 * Puts a mask over this element to disable user interaction. Requires core.css.
8756 * This method can only be applied to elements which accept child nodes.
8757 * @param {String} msg (optional) A message to display in the mask
8758 * @param {String} msgCls (optional) A css class to apply to the msg element
8759 * @return {Element} The mask element
8761 mask : function(msg, msgCls){
8762 if(this.getStyle("position") == "static"){
8763 this.setStyle("position", "relative");
8766 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8768 this.addClass("x-masked");
8769 this._mask.setDisplayed(true);
8770 if(typeof msg == 'string'){
8772 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8774 var mm = this._maskMsg;
8775 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8776 mm.dom.firstChild.innerHTML = msg;
8777 mm.setDisplayed(true);
8780 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8781 this._mask.setHeight(this.getHeight());
8787 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8788 * it is cached for reuse.
8790 unmask : function(removeEl){
8792 if(removeEl === true){
8793 this._mask.remove();
8796 this._maskMsg.remove();
8797 delete this._maskMsg;
8800 this._mask.setDisplayed(false);
8802 this._maskMsg.setDisplayed(false);
8806 this.removeClass("x-masked");
8810 * Returns true if this element is masked
8813 isMasked : function(){
8814 return this._mask && this._mask.isVisible();
8818 * Creates an iframe shim for this element to keep selects and other windowed objects from
8820 * @return {Roo.Element} The new shim element
8822 createShim : function(){
8823 var el = document.createElement('iframe');
8824 el.frameBorder = 'no';
8825 el.className = 'roo-shim';
8826 if(Roo.isIE && Roo.isSecure){
8827 el.src = Roo.SSL_SECURE_URL;
8829 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8830 shim.autoBoxAdjust = false;
8835 * Removes this element from the DOM and deletes it from the cache
8837 remove : function(){
8838 if(this.dom.parentNode){
8839 this.dom.parentNode.removeChild(this.dom);
8841 delete El.cache[this.dom.id];
8845 * Sets up event handlers to add and remove a css class when the mouse is over this element
8846 * @param {String} className
8847 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8848 * mouseout events for children elements
8849 * @return {Roo.Element} this
8851 addClassOnOver : function(className, preventFlicker){
8852 this.on("mouseover", function(){
8853 Roo.fly(this, '_internal').addClass(className);
8855 var removeFn = function(e){
8856 if(preventFlicker !== true || !e.within(this, true)){
8857 Roo.fly(this, '_internal').removeClass(className);
8860 this.on("mouseout", removeFn, this.dom);
8865 * Sets up event handlers to add and remove a css class when this element has the focus
8866 * @param {String} className
8867 * @return {Roo.Element} this
8869 addClassOnFocus : function(className){
8870 this.on("focus", function(){
8871 Roo.fly(this, '_internal').addClass(className);
8873 this.on("blur", function(){
8874 Roo.fly(this, '_internal').removeClass(className);
8879 * 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)
8880 * @param {String} className
8881 * @return {Roo.Element} this
8883 addClassOnClick : function(className){
8885 this.on("mousedown", function(){
8886 Roo.fly(dom, '_internal').addClass(className);
8887 var d = Roo.get(document);
8888 var fn = function(){
8889 Roo.fly(dom, '_internal').removeClass(className);
8890 d.removeListener("mouseup", fn);
8892 d.on("mouseup", fn);
8898 * Stops the specified event from bubbling and optionally prevents the default action
8899 * @param {String} eventName
8900 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8901 * @return {Roo.Element} this
8903 swallowEvent : function(eventName, preventDefault){
8904 var fn = function(e){
8905 e.stopPropagation();
8910 if(eventName instanceof Array){
8911 for(var i = 0, len = eventName.length; i < len; i++){
8912 this.on(eventName[i], fn);
8916 this.on(eventName, fn);
8923 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8926 * Sizes this element to its parent element's dimensions performing
8927 * neccessary box adjustments.
8928 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8929 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8930 * @return {Roo.Element} this
8932 fitToParent : function(monitorResize, targetParent) {
8933 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8934 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8935 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8938 var p = Roo.get(targetParent || this.dom.parentNode);
8939 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8940 if (monitorResize === true) {
8941 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8942 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8948 * Gets the next sibling, skipping text nodes
8949 * @return {HTMLElement} The next sibling or null
8951 getNextSibling : function(){
8952 var n = this.dom.nextSibling;
8953 while(n && n.nodeType != 1){
8960 * Gets the previous sibling, skipping text nodes
8961 * @return {HTMLElement} The previous sibling or null
8963 getPrevSibling : function(){
8964 var n = this.dom.previousSibling;
8965 while(n && n.nodeType != 1){
8966 n = n.previousSibling;
8973 * Appends the passed element(s) to this element
8974 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8975 * @return {Roo.Element} this
8977 appendChild: function(el){
8984 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8985 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8986 * automatically generated with the specified attributes.
8987 * @param {HTMLElement} insertBefore (optional) a child element of this element
8988 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8989 * @return {Roo.Element} The new child element
8991 createChild: function(config, insertBefore, returnDom){
8992 config = config || {tag:'div'};
8994 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8996 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
9000 * Appends this element to the passed element
9001 * @param {String/HTMLElement/Element} el The new parent element
9002 * @return {Roo.Element} this
9004 appendTo: function(el){
9005 el = Roo.getDom(el);
9006 el.appendChild(this.dom);
9011 * Inserts this element before the passed element in the DOM
9012 * @param {String/HTMLElement/Element} el The element to insert before
9013 * @return {Roo.Element} this
9015 insertBefore: function(el){
9016 el = Roo.getDom(el);
9017 el.parentNode.insertBefore(this.dom, el);
9022 * Inserts this element after the passed element in the DOM
9023 * @param {String/HTMLElement/Element} el The element to insert after
9024 * @return {Roo.Element} this
9026 insertAfter: function(el){
9027 el = Roo.getDom(el);
9028 el.parentNode.insertBefore(this.dom, el.nextSibling);
9033 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
9034 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9035 * @return {Roo.Element} The new child
9037 insertFirst: function(el, returnDom){
9039 if(typeof el == 'object' && !el.nodeType){ // dh config
9040 return this.createChild(el, this.dom.firstChild, returnDom);
9042 el = Roo.getDom(el);
9043 this.dom.insertBefore(el, this.dom.firstChild);
9044 return !returnDom ? Roo.get(el) : el;
9049 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
9050 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
9051 * @param {String} where (optional) 'before' or 'after' defaults to before
9052 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9053 * @return {Roo.Element} the inserted Element
9055 insertSibling: function(el, where, returnDom){
9056 where = where ? where.toLowerCase() : 'before';
9058 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
9060 if(typeof el == 'object' && !el.nodeType){ // dh config
9061 if(where == 'after' && !this.dom.nextSibling){
9062 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
9064 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9068 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9069 where == 'before' ? this.dom : this.dom.nextSibling);
9078 * Creates and wraps this element with another element
9079 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9080 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9081 * @return {HTMLElement/Element} The newly created wrapper element
9083 wrap: function(config, returnDom){
9085 config = {tag: "div"};
9087 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9088 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9093 * Replaces the passed element with this element
9094 * @param {String/HTMLElement/Element} el The element to replace
9095 * @return {Roo.Element} this
9097 replace: function(el){
9099 this.insertBefore(el);
9105 * Inserts an html fragment into this element
9106 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9107 * @param {String} html The HTML fragment
9108 * @param {Boolean} returnEl True to return an Roo.Element
9109 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9111 insertHtml : function(where, html, returnEl){
9112 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9113 return returnEl ? Roo.get(el) : el;
9117 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9118 * @param {Object} o The object with the attributes
9119 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9120 * @return {Roo.Element} this
9122 set : function(o, useSet){
9124 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9126 if(attr == "style" || typeof o[attr] == "function") continue;
9128 el.className = o["cls"];
9130 if(useSet) el.setAttribute(attr, o[attr]);
9131 else el[attr] = o[attr];
9135 Roo.DomHelper.applyStyles(el, o.style);
9141 * Convenience method for constructing a KeyMap
9142 * @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:
9143 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9144 * @param {Function} fn The function to call
9145 * @param {Object} scope (optional) The scope of the function
9146 * @return {Roo.KeyMap} The KeyMap created
9148 addKeyListener : function(key, fn, scope){
9150 if(typeof key != "object" || key instanceof Array){
9166 return new Roo.KeyMap(this, config);
9170 * Creates a KeyMap for this element
9171 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9172 * @return {Roo.KeyMap} The KeyMap created
9174 addKeyMap : function(config){
9175 return new Roo.KeyMap(this, config);
9179 * Returns true if this element is scrollable.
9182 isScrollable : function(){
9184 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9188 * 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().
9189 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9190 * @param {Number} value The new scroll value
9191 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9192 * @return {Element} this
9195 scrollTo : function(side, value, animate){
9196 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9198 this.dom[prop] = value;
9200 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9201 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9207 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9208 * within this element's scrollable range.
9209 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9210 * @param {Number} distance How far to scroll the element in pixels
9211 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9212 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9213 * was scrolled as far as it could go.
9215 scroll : function(direction, distance, animate){
9216 if(!this.isScrollable()){
9220 var l = el.scrollLeft, t = el.scrollTop;
9221 var w = el.scrollWidth, h = el.scrollHeight;
9222 var cw = el.clientWidth, ch = el.clientHeight;
9223 direction = direction.toLowerCase();
9224 var scrolled = false;
9225 var a = this.preanim(arguments, 2);
9230 var v = Math.min(l + distance, w-cw);
9231 this.scrollTo("left", v, a);
9238 var v = Math.max(l - distance, 0);
9239 this.scrollTo("left", v, a);
9247 var v = Math.max(t - distance, 0);
9248 this.scrollTo("top", v, a);
9256 var v = Math.min(t + distance, h-ch);
9257 this.scrollTo("top", v, a);
9266 * Translates the passed page coordinates into left/top css values for this element
9267 * @param {Number/Array} x The page x or an array containing [x, y]
9268 * @param {Number} y The page y
9269 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9271 translatePoints : function(x, y){
9272 if(typeof x == 'object' || x instanceof Array){
9275 var p = this.getStyle('position');
9276 var o = this.getXY();
9278 var l = parseInt(this.getStyle('left'), 10);
9279 var t = parseInt(this.getStyle('top'), 10);
9282 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9285 t = (p == "relative") ? 0 : this.dom.offsetTop;
9288 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9292 * Returns the current scroll position of the element.
9293 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9295 getScroll : function(){
9296 var d = this.dom, doc = document;
9297 if(d == doc || d == doc.body){
9298 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9299 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9300 return {left: l, top: t};
9302 return {left: d.scrollLeft, top: d.scrollTop};
9307 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9308 * are convert to standard 6 digit hex color.
9309 * @param {String} attr The css attribute
9310 * @param {String} defaultValue The default value to use when a valid color isn't found
9311 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9314 getColor : function(attr, defaultValue, prefix){
9315 var v = this.getStyle(attr);
9316 if(!v || v == "transparent" || v == "inherit") {
9317 return defaultValue;
9319 var color = typeof prefix == "undefined" ? "#" : prefix;
9320 if(v.substr(0, 4) == "rgb("){
9321 var rvs = v.slice(4, v.length -1).split(",");
9322 for(var i = 0; i < 3; i++){
9323 var h = parseInt(rvs[i]).toString(16);
9330 if(v.substr(0, 1) == "#"){
9332 for(var i = 1; i < 4; i++){
9333 var c = v.charAt(i);
9336 }else if(v.length == 7){
9337 color += v.substr(1);
9341 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9345 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9346 * gradient background, rounded corners and a 4-way shadow.
9347 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9348 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9349 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9350 * @return {Roo.Element} this
9352 boxWrap : function(cls){
9353 cls = cls || 'x-box';
9354 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9355 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9360 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9361 * @param {String} namespace The namespace in which to look for the attribute
9362 * @param {String} name The attribute name
9363 * @return {String} The attribute value
9365 getAttributeNS : Roo.isIE ? function(ns, name){
9367 var type = typeof d[ns+":"+name];
9368 if(type != 'undefined' && type != 'unknown'){
9369 return d[ns+":"+name];
9372 } : function(ns, name){
9374 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9378 var ep = El.prototype;
9381 * Appends an event handler (Shorthand for addListener)
9382 * @param {String} eventName The type of event to append
9383 * @param {Function} fn The method the event invokes
9384 * @param {Object} scope (optional) The scope (this object) of the fn
9385 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9388 ep.on = ep.addListener;
9390 ep.mon = ep.addListener;
9393 * Removes an event handler from this element (shorthand for removeListener)
9394 * @param {String} eventName the type of event to remove
9395 * @param {Function} fn the method the event invokes
9396 * @return {Roo.Element} this
9399 ep.un = ep.removeListener;
9402 * true to automatically adjust width and height settings for box-model issues (default to true)
9404 ep.autoBoxAdjust = true;
9407 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9410 El.addUnits = function(v, defaultUnit){
9411 if(v === "" || v == "auto"){
9414 if(v === undefined){
9417 if(typeof v == "number" || !El.unitPattern.test(v)){
9418 return v + (defaultUnit || 'px');
9423 // special markup used throughout Roo when box wrapping elements
9424 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>';
9426 * Visibility mode constant - Use visibility to hide element
9432 * Visibility mode constant - Use display to hide element
9438 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9439 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9440 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9452 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9453 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9454 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9455 * @return {Element} The Element object
9458 El.get = function(el){
9460 if(!el){ return null; }
9461 if(typeof el == "string"){ // element id
9462 if(!(elm = document.getElementById(el))){
9465 if(ex = El.cache[el]){
9468 ex = El.cache[el] = new El(elm);
9471 }else if(el.tagName){ // dom element
9475 if(ex = El.cache[id]){
9478 ex = El.cache[id] = new El(el);
9481 }else if(el instanceof El){
9483 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9484 // catch case where it hasn't been appended
9485 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9488 }else if(el.isComposite){
9490 }else if(el instanceof Array){
9491 return El.select(el);
9492 }else if(el == document){
9493 // create a bogus element object representing the document object
9495 var f = function(){};
9496 f.prototype = El.prototype;
9498 docEl.dom = document;
9506 El.uncache = function(el){
9507 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9509 delete El.cache[a[i].id || a[i]];
9515 // Garbage collection - uncache elements/purge listeners on orphaned elements
9516 // so we don't hold a reference and cause the browser to retain them
9517 El.garbageCollect = function(){
9518 if(!Roo.enableGarbageCollector){
9519 clearInterval(El.collectorThread);
9522 for(var eid in El.cache){
9523 var el = El.cache[eid], d = el.dom;
9524 // -------------------------------------------------------
9525 // Determining what is garbage:
9526 // -------------------------------------------------------
9528 // dom node is null, definitely garbage
9529 // -------------------------------------------------------
9531 // no parentNode == direct orphan, definitely garbage
9532 // -------------------------------------------------------
9533 // !d.offsetParent && !document.getElementById(eid)
9534 // display none elements have no offsetParent so we will
9535 // also try to look it up by it's id. However, check
9536 // offsetParent first so we don't do unneeded lookups.
9537 // This enables collection of elements that are not orphans
9538 // directly, but somewhere up the line they have an orphan
9540 // -------------------------------------------------------
9541 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9542 delete El.cache[eid];
9543 if(d && Roo.enableListenerCollection){
9549 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9553 El.Flyweight = function(dom){
9556 El.Flyweight.prototype = El.prototype;
9558 El._flyweights = {};
9560 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9561 * the dom node can be overwritten by other code.
9562 * @param {String/HTMLElement} el The dom node or id
9563 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9564 * prevent conflicts (e.g. internally Roo uses "_internal")
9566 * @return {Element} The shared Element object
9568 El.fly = function(el, named){
9569 named = named || '_global';
9570 el = Roo.getDom(el);
9574 if(!El._flyweights[named]){
9575 El._flyweights[named] = new El.Flyweight();
9577 El._flyweights[named].dom = el;
9578 return El._flyweights[named];
9582 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9583 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9584 * Shorthand of {@link Roo.Element#get}
9585 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9586 * @return {Element} The Element object
9592 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9593 * the dom node can be overwritten by other code.
9594 * Shorthand of {@link Roo.Element#fly}
9595 * @param {String/HTMLElement} el The dom node or id
9596 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9597 * prevent conflicts (e.g. internally Roo uses "_internal")
9599 * @return {Element} The shared Element object
9605 // speedy lookup for elements never to box adjust
9606 var noBoxAdjust = Roo.isStrict ? {
9609 input:1, select:1, textarea:1
9611 if(Roo.isIE || Roo.isGecko){
9612 noBoxAdjust['button'] = 1;
9616 Roo.EventManager.on(window, 'unload', function(){
9618 delete El._flyweights;
9626 Roo.Element.selectorFunction = Roo.DomQuery.select;
9629 Roo.Element.select = function(selector, unique, root){
9631 if(typeof selector == "string"){
9632 els = Roo.Element.selectorFunction(selector, root);
9633 }else if(selector.length !== undefined){
9636 throw "Invalid selector";
9638 if(unique === true){
9639 return new Roo.CompositeElement(els);
9641 return new Roo.CompositeElementLite(els);
9645 * Selects elements based on the passed CSS selector to enable working on them as 1.
9646 * @param {String/Array} selector The CSS selector or an array of elements
9647 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9648 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9649 * @return {CompositeElementLite/CompositeElement}
9653 Roo.select = Roo.Element.select;
9670 * Ext JS Library 1.1.1
9671 * Copyright(c) 2006-2007, Ext JS, LLC.
9673 * Originally Released Under LGPL - original licence link has changed is not relivant.
9676 * <script type="text/javascript">
9681 //Notifies Element that fx methods are available
9682 Roo.enableFx = true;
9686 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9687 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9688 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9689 * Element effects to work.</p><br/>
9691 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9692 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9693 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9694 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9695 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9696 * expected results and should be done with care.</p><br/>
9698 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9699 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9702 ----- -----------------------------
9703 tl The top left corner
9704 t The center of the top edge
9705 tr The top right corner
9706 l The center of the left edge
9707 r The center of the right edge
9708 bl The bottom left corner
9709 b The center of the bottom edge
9710 br The bottom right corner
9712 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9713 * below are common options that can be passed to any Fx method.</b>
9714 * @cfg {Function} callback A function called when the effect is finished
9715 * @cfg {Object} scope The scope of the effect function
9716 * @cfg {String} easing A valid Easing value for the effect
9717 * @cfg {String} afterCls A css class to apply after the effect
9718 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9719 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9720 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9721 * effects that end with the element being visually hidden, ignored otherwise)
9722 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9723 * a function which returns such a specification that will be applied to the Element after the effect finishes
9724 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9725 * @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
9726 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9730 * Slides the element into view. An anchor point can be optionally passed to set the point of
9731 * origin for the slide effect. This function automatically handles wrapping the element with
9732 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9735 // default: slide the element in from the top
9738 // custom: slide the element in from the right with a 2-second duration
9739 el.slideIn('r', { duration: 2 });
9741 // common config options shown with default values
9747 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9748 * @param {Object} options (optional) Object literal with any of the Fx config options
9749 * @return {Roo.Element} The Element
9751 slideIn : function(anchor, o){
9752 var el = this.getFxEl();
9755 el.queueFx(o, function(){
9757 anchor = anchor || "t";
9759 // fix display to visibility
9762 // restore values after effect
9763 var r = this.getFxRestore();
9764 var b = this.getBox();
9765 // fixed size for slide
9769 var wrap = this.fxWrap(r.pos, o, "hidden");
9771 var st = this.dom.style;
9772 st.visibility = "visible";
9773 st.position = "absolute";
9775 // clear out temp styles after slide and unwrap
9776 var after = function(){
9777 el.fxUnwrap(wrap, r.pos, o);
9779 st.height = r.height;
9782 // time to calc the positions
9783 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9785 switch(anchor.toLowerCase()){
9787 wrap.setSize(b.width, 0);
9788 st.left = st.bottom = "0";
9792 wrap.setSize(0, b.height);
9793 st.right = st.top = "0";
9797 wrap.setSize(0, b.height);
9799 st.left = st.top = "0";
9800 a = {width: bw, points: pt};
9803 wrap.setSize(b.width, 0);
9804 wrap.setY(b.bottom);
9805 st.left = st.top = "0";
9806 a = {height: bh, points: pt};
9810 st.right = st.bottom = "0";
9811 a = {width: bw, height: bh};
9815 wrap.setY(b.y+b.height);
9816 st.right = st.top = "0";
9817 a = {width: bw, height: bh, points: pt};
9821 wrap.setXY([b.right, b.bottom]);
9822 st.left = st.top = "0";
9823 a = {width: bw, height: bh, points: pt};
9827 wrap.setX(b.x+b.width);
9828 st.left = st.bottom = "0";
9829 a = {width: bw, height: bh, points: pt};
9832 this.dom.style.visibility = "visible";
9835 arguments.callee.anim = wrap.fxanim(a,
9845 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9846 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9847 * 'hidden') but block elements will still take up space in the document. The element must be removed
9848 * from the DOM using the 'remove' config option if desired. This function automatically handles
9849 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9852 // default: slide the element out to the top
9855 // custom: slide the element out to the right with a 2-second duration
9856 el.slideOut('r', { duration: 2 });
9858 // common config options shown with default values
9866 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9867 * @param {Object} options (optional) Object literal with any of the Fx config options
9868 * @return {Roo.Element} The Element
9870 slideOut : function(anchor, o){
9871 var el = this.getFxEl();
9874 el.queueFx(o, function(){
9876 anchor = anchor || "t";
9878 // restore values after effect
9879 var r = this.getFxRestore();
9881 var b = this.getBox();
9882 // fixed size for slide
9886 var wrap = this.fxWrap(r.pos, o, "visible");
9888 var st = this.dom.style;
9889 st.visibility = "visible";
9890 st.position = "absolute";
9894 var after = function(){
9896 el.setDisplayed(false);
9901 el.fxUnwrap(wrap, r.pos, o);
9904 st.height = r.height;
9909 var a, zero = {to: 0};
9910 switch(anchor.toLowerCase()){
9912 st.left = st.bottom = "0";
9916 st.right = st.top = "0";
9920 st.left = st.top = "0";
9921 a = {width: zero, points: {to:[b.right, b.y]}};
9924 st.left = st.top = "0";
9925 a = {height: zero, points: {to:[b.x, b.bottom]}};
9928 st.right = st.bottom = "0";
9929 a = {width: zero, height: zero};
9932 st.right = st.top = "0";
9933 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9936 st.left = st.top = "0";
9937 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9940 st.left = st.bottom = "0";
9941 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9945 arguments.callee.anim = wrap.fxanim(a,
9955 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
9956 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
9957 * The element must be removed from the DOM using the 'remove' config option if desired.
9963 // common config options shown with default values
9971 * @param {Object} options (optional) Object literal with any of the Fx config options
9972 * @return {Roo.Element} The Element
9975 var el = this.getFxEl();
9978 el.queueFx(o, function(){
9979 this.clearOpacity();
9982 // restore values after effect
9983 var r = this.getFxRestore();
9984 var st = this.dom.style;
9986 var after = function(){
9988 el.setDisplayed(false);
9995 el.setPositioning(r.pos);
9997 st.height = r.height;
10002 var width = this.getWidth();
10003 var height = this.getHeight();
10005 arguments.callee.anim = this.fxanim({
10006 width : {to: this.adjustWidth(width * 2)},
10007 height : {to: this.adjustHeight(height * 2)},
10008 points : {by: [-(width * .5), -(height * .5)]},
10010 fontSize: {to:200, unit: "%"}
10021 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
10022 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
10023 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
10029 // all config options shown with default values
10037 * @param {Object} options (optional) Object literal with any of the Fx config options
10038 * @return {Roo.Element} The Element
10040 switchOff : function(o){
10041 var el = this.getFxEl();
10044 el.queueFx(o, function(){
10045 this.clearOpacity();
10048 // restore values after effect
10049 var r = this.getFxRestore();
10050 var st = this.dom.style;
10052 var after = function(){
10054 el.setDisplayed(false);
10060 el.setPositioning(r.pos);
10061 st.width = r.width;
10062 st.height = r.height;
10067 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10068 this.clearOpacity();
10072 points:{by:[0, this.getHeight() * .5]}
10073 }, o, 'motion', 0.3, 'easeIn', after);
10074 }).defer(100, this);
10081 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10082 * changed using the "attr" config option) and then fading back to the original color. If no original
10083 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10086 // default: highlight background to yellow
10089 // custom: highlight foreground text to blue for 2 seconds
10090 el.highlight("0000ff", { attr: 'color', duration: 2 });
10092 // common config options shown with default values
10093 el.highlight("ffff9c", {
10094 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10095 endColor: (current color) or "ffffff",
10100 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10101 * @param {Object} options (optional) Object literal with any of the Fx config options
10102 * @return {Roo.Element} The Element
10104 highlight : function(color, o){
10105 var el = this.getFxEl();
10108 el.queueFx(o, function(){
10109 color = color || "ffff9c";
10110 attr = o.attr || "backgroundColor";
10112 this.clearOpacity();
10115 var origColor = this.getColor(attr);
10116 var restoreColor = this.dom.style[attr];
10117 endColor = (o.endColor || origColor) || "ffffff";
10119 var after = function(){
10120 el.dom.style[attr] = restoreColor;
10125 a[attr] = {from: color, to: endColor};
10126 arguments.callee.anim = this.fxanim(a,
10136 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10139 // default: a single light blue ripple
10142 // custom: 3 red ripples lasting 3 seconds total
10143 el.frame("ff0000", 3, { duration: 3 });
10145 // common config options shown with default values
10146 el.frame("C3DAF9", 1, {
10147 duration: 1 //duration of entire animation (not each individual ripple)
10148 // Note: Easing is not configurable and will be ignored if included
10151 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10152 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10153 * @param {Object} options (optional) Object literal with any of the Fx config options
10154 * @return {Roo.Element} The Element
10156 frame : function(color, count, o){
10157 var el = this.getFxEl();
10160 el.queueFx(o, function(){
10161 color = color || "#C3DAF9";
10162 if(color.length == 6){
10163 color = "#" + color;
10165 count = count || 1;
10166 duration = o.duration || 1;
10169 var b = this.getBox();
10170 var animFn = function(){
10171 var proxy = this.createProxy({
10174 visbility:"hidden",
10175 position:"absolute",
10176 "z-index":"35000", // yee haw
10177 border:"0px solid " + color
10180 var scale = Roo.isBorderBox ? 2 : 1;
10182 top:{from:b.y, to:b.y - 20},
10183 left:{from:b.x, to:b.x - 20},
10184 borderWidth:{from:0, to:10},
10185 opacity:{from:1, to:0},
10186 height:{from:b.height, to:(b.height + (20*scale))},
10187 width:{from:b.width, to:(b.width + (20*scale))}
10188 }, duration, function(){
10192 animFn.defer((duration/2)*1000, this);
10203 * Creates a pause before any subsequent queued effects begin. If there are
10204 * no effects queued after the pause it will have no effect.
10209 * @param {Number} seconds The length of time to pause (in seconds)
10210 * @return {Roo.Element} The Element
10212 pause : function(seconds){
10213 var el = this.getFxEl();
10216 el.queueFx(o, function(){
10217 setTimeout(function(){
10219 }, seconds * 1000);
10225 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10226 * using the "endOpacity" config option.
10229 // default: fade in from opacity 0 to 100%
10232 // custom: fade in from opacity 0 to 75% over 2 seconds
10233 el.fadeIn({ endOpacity: .75, duration: 2});
10235 // common config options shown with default values
10237 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10242 * @param {Object} options (optional) Object literal with any of the Fx config options
10243 * @return {Roo.Element} The Element
10245 fadeIn : function(o){
10246 var el = this.getFxEl();
10248 el.queueFx(o, function(){
10249 this.setOpacity(0);
10251 this.dom.style.visibility = 'visible';
10252 var to = o.endOpacity || 1;
10253 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10254 o, null, .5, "easeOut", function(){
10256 this.clearOpacity();
10265 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10266 * using the "endOpacity" config option.
10269 // default: fade out from the element's current opacity to 0
10272 // custom: fade out from the element's current opacity to 25% over 2 seconds
10273 el.fadeOut({ endOpacity: .25, duration: 2});
10275 // common config options shown with default values
10277 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10284 * @param {Object} options (optional) Object literal with any of the Fx config options
10285 * @return {Roo.Element} The Element
10287 fadeOut : function(o){
10288 var el = this.getFxEl();
10290 el.queueFx(o, function(){
10291 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10292 o, null, .5, "easeOut", function(){
10293 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10294 this.dom.style.display = "none";
10296 this.dom.style.visibility = "hidden";
10298 this.clearOpacity();
10306 * Animates the transition of an element's dimensions from a starting height/width
10307 * to an ending height/width.
10310 // change height and width to 100x100 pixels
10311 el.scale(100, 100);
10313 // common config options shown with default values. The height and width will default to
10314 // the element's existing values if passed as null.
10317 [element's height], {
10322 * @param {Number} width The new width (pass undefined to keep the original width)
10323 * @param {Number} height The new height (pass undefined to keep the original height)
10324 * @param {Object} options (optional) Object literal with any of the Fx config options
10325 * @return {Roo.Element} The Element
10327 scale : function(w, h, o){
10328 this.shift(Roo.apply({}, o, {
10336 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10337 * Any of these properties not specified in the config object will not be changed. This effect
10338 * requires that at least one new dimension, position or opacity setting must be passed in on
10339 * the config object in order for the function to have any effect.
10342 // slide the element horizontally to x position 200 while changing the height and opacity
10343 el.shift({ x: 200, height: 50, opacity: .8 });
10345 // common config options shown with default values.
10347 width: [element's width],
10348 height: [element's height],
10349 x: [element's x position],
10350 y: [element's y position],
10351 opacity: [element's opacity],
10356 * @param {Object} options Object literal with any of the Fx config options
10357 * @return {Roo.Element} The Element
10359 shift : function(o){
10360 var el = this.getFxEl();
10362 el.queueFx(o, function(){
10363 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10364 if(w !== undefined){
10365 a.width = {to: this.adjustWidth(w)};
10367 if(h !== undefined){
10368 a.height = {to: this.adjustHeight(h)};
10370 if(x !== undefined || y !== undefined){
10372 x !== undefined ? x : this.getX(),
10373 y !== undefined ? y : this.getY()
10376 if(op !== undefined){
10377 a.opacity = {to: op};
10379 if(o.xy !== undefined){
10380 a.points = {to: o.xy};
10382 arguments.callee.anim = this.fxanim(a,
10383 o, 'motion', .35, "easeOut", function(){
10391 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10392 * ending point of the effect.
10395 // default: slide the element downward while fading out
10398 // custom: slide the element out to the right with a 2-second duration
10399 el.ghost('r', { duration: 2 });
10401 // common config options shown with default values
10409 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10410 * @param {Object} options (optional) Object literal with any of the Fx config options
10411 * @return {Roo.Element} The Element
10413 ghost : function(anchor, o){
10414 var el = this.getFxEl();
10417 el.queueFx(o, function(){
10418 anchor = anchor || "b";
10420 // restore values after effect
10421 var r = this.getFxRestore();
10422 var w = this.getWidth(),
10423 h = this.getHeight();
10425 var st = this.dom.style;
10427 var after = function(){
10429 el.setDisplayed(false);
10435 el.setPositioning(r.pos);
10436 st.width = r.width;
10437 st.height = r.height;
10442 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10443 switch(anchor.toLowerCase()){
10470 arguments.callee.anim = this.fxanim(a,
10480 * Ensures that all effects queued after syncFx is called on the element are
10481 * run concurrently. This is the opposite of {@link #sequenceFx}.
10482 * @return {Roo.Element} The Element
10484 syncFx : function(){
10485 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10494 * Ensures that all effects queued after sequenceFx is called on the element are
10495 * run in sequence. This is the opposite of {@link #syncFx}.
10496 * @return {Roo.Element} The Element
10498 sequenceFx : function(){
10499 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10501 concurrent : false,
10508 nextFx : function(){
10509 var ef = this.fxQueue[0];
10516 * Returns true if the element has any effects actively running or queued, else returns false.
10517 * @return {Boolean} True if element has active effects, else false
10519 hasActiveFx : function(){
10520 return this.fxQueue && this.fxQueue[0];
10524 * Stops any running effects and clears the element's internal effects queue if it contains
10525 * any additional effects that haven't started yet.
10526 * @return {Roo.Element} The Element
10528 stopFx : function(){
10529 if(this.hasActiveFx()){
10530 var cur = this.fxQueue[0];
10531 if(cur && cur.anim && cur.anim.isAnimated()){
10532 this.fxQueue = [cur]; // clear out others
10533 cur.anim.stop(true);
10540 beforeFx : function(o){
10541 if(this.hasActiveFx() && !o.concurrent){
10552 * Returns true if the element is currently blocking so that no other effect can be queued
10553 * until this effect is finished, else returns false if blocking is not set. This is commonly
10554 * used to ensure that an effect initiated by a user action runs to completion prior to the
10555 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10556 * @return {Boolean} True if blocking, else false
10558 hasFxBlock : function(){
10559 var q = this.fxQueue;
10560 return q && q[0] && q[0].block;
10564 queueFx : function(o, fn){
10568 if(!this.hasFxBlock()){
10569 Roo.applyIf(o, this.fxDefaults);
10571 var run = this.beforeFx(o);
10572 fn.block = o.block;
10573 this.fxQueue.push(fn);
10585 fxWrap : function(pos, o, vis){
10587 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10590 wrapXY = this.getXY();
10592 var div = document.createElement("div");
10593 div.style.visibility = vis;
10594 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10595 wrap.setPositioning(pos);
10596 if(wrap.getStyle("position") == "static"){
10597 wrap.position("relative");
10599 this.clearPositioning('auto');
10601 wrap.dom.appendChild(this.dom);
10603 wrap.setXY(wrapXY);
10610 fxUnwrap : function(wrap, pos, o){
10611 this.clearPositioning();
10612 this.setPositioning(pos);
10614 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10620 getFxRestore : function(){
10621 var st = this.dom.style;
10622 return {pos: this.getPositioning(), width: st.width, height : st.height};
10626 afterFx : function(o){
10628 this.applyStyles(o.afterStyle);
10631 this.addClass(o.afterCls);
10633 if(o.remove === true){
10636 Roo.callback(o.callback, o.scope, [this]);
10638 this.fxQueue.shift();
10644 getFxEl : function(){ // support for composite element fx
10645 return Roo.get(this.dom);
10649 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10650 animType = animType || 'run';
10652 var anim = Roo.lib.Anim[animType](
10654 (opt.duration || defaultDur) || .35,
10655 (opt.easing || defaultEase) || 'easeOut',
10657 Roo.callback(cb, this);
10666 // backwords compat
10667 Roo.Fx.resize = Roo.Fx.scale;
10669 //When included, Roo.Fx is automatically applied to Element so that all basic
10670 //effects are available directly via the Element API
10671 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10673 * Ext JS Library 1.1.1
10674 * Copyright(c) 2006-2007, Ext JS, LLC.
10676 * Originally Released Under LGPL - original licence link has changed is not relivant.
10679 * <script type="text/javascript">
10684 * @class Roo.CompositeElement
10685 * Standard composite class. Creates a Roo.Element for every element in the collection.
10687 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10688 * actions will be performed on all the elements in this collection.</b>
10690 * All methods return <i>this</i> and can be chained.
10692 var els = Roo.select("#some-el div.some-class", true);
10693 // or select directly from an existing element
10694 var el = Roo.get('some-el');
10695 el.select('div.some-class', true);
10697 els.setWidth(100); // all elements become 100 width
10698 els.hide(true); // all elements fade out and hide
10700 els.setWidth(100).hide(true);
10703 Roo.CompositeElement = function(els){
10704 this.elements = [];
10705 this.addElements(els);
10707 Roo.CompositeElement.prototype = {
10709 addElements : function(els){
10710 if(!els) return this;
10711 if(typeof els == "string"){
10712 els = Roo.Element.selectorFunction(els);
10714 var yels = this.elements;
10715 var index = yels.length-1;
10716 for(var i = 0, len = els.length; i < len; i++) {
10717 yels[++index] = Roo.get(els[i]);
10723 * Clears this composite and adds the elements returned by the passed selector.
10724 * @param {String/Array} els A string CSS selector, an array of elements or an element
10725 * @return {CompositeElement} this
10727 fill : function(els){
10728 this.elements = [];
10734 * Filters this composite to only elements that match the passed selector.
10735 * @param {String} selector A string CSS selector
10736 * @return {CompositeElement} this
10738 filter : function(selector){
10740 this.each(function(el){
10741 if(el.is(selector)){
10742 els[els.length] = el.dom;
10749 invoke : function(fn, args){
10750 var els = this.elements;
10751 for(var i = 0, len = els.length; i < len; i++) {
10752 Roo.Element.prototype[fn].apply(els[i], args);
10757 * Adds elements to this composite.
10758 * @param {String/Array} els A string CSS selector, an array of elements or an element
10759 * @return {CompositeElement} this
10761 add : function(els){
10762 if(typeof els == "string"){
10763 this.addElements(Roo.Element.selectorFunction(els));
10764 }else if(els.length !== undefined){
10765 this.addElements(els);
10767 this.addElements([els]);
10772 * Calls the passed function passing (el, this, index) for each element in this composite.
10773 * @param {Function} fn The function to call
10774 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10775 * @return {CompositeElement} this
10777 each : function(fn, scope){
10778 var els = this.elements;
10779 for(var i = 0, len = els.length; i < len; i++){
10780 if(fn.call(scope || els[i], els[i], this, i) === false) {
10788 * Returns the Element object at the specified index
10789 * @param {Number} index
10790 * @return {Roo.Element}
10792 item : function(index){
10793 return this.elements[index] || null;
10797 * Returns the first Element
10798 * @return {Roo.Element}
10800 first : function(){
10801 return this.item(0);
10805 * Returns the last Element
10806 * @return {Roo.Element}
10809 return this.item(this.elements.length-1);
10813 * Returns the number of elements in this composite
10816 getCount : function(){
10817 return this.elements.length;
10821 * Returns true if this composite contains the passed element
10824 contains : function(el){
10825 return this.indexOf(el) !== -1;
10829 * Returns true if this composite contains the passed element
10832 indexOf : function(el){
10833 return this.elements.indexOf(Roo.get(el));
10838 * Removes the specified element(s).
10839 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10840 * or an array of any of those.
10841 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10842 * @return {CompositeElement} this
10844 removeElement : function(el, removeDom){
10845 if(el instanceof Array){
10846 for(var i = 0, len = el.length; i < len; i++){
10847 this.removeElement(el[i]);
10851 var index = typeof el == 'number' ? el : this.indexOf(el);
10854 var d = this.elements[index];
10858 d.parentNode.removeChild(d);
10861 this.elements.splice(index, 1);
10867 * Replaces the specified element with the passed element.
10868 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10870 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10871 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10872 * @return {CompositeElement} this
10874 replaceElement : function(el, replacement, domReplace){
10875 var index = typeof el == 'number' ? el : this.indexOf(el);
10878 this.elements[index].replaceWith(replacement);
10880 this.elements.splice(index, 1, Roo.get(replacement))
10887 * Removes all elements.
10889 clear : function(){
10890 this.elements = [];
10894 Roo.CompositeElement.createCall = function(proto, fnName){
10895 if(!proto[fnName]){
10896 proto[fnName] = function(){
10897 return this.invoke(fnName, arguments);
10901 for(var fnName in Roo.Element.prototype){
10902 if(typeof Roo.Element.prototype[fnName] == "function"){
10903 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10909 * Ext JS Library 1.1.1
10910 * Copyright(c) 2006-2007, Ext JS, LLC.
10912 * Originally Released Under LGPL - original licence link has changed is not relivant.
10915 * <script type="text/javascript">
10919 * @class Roo.CompositeElementLite
10920 * @extends Roo.CompositeElement
10921 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10923 var els = Roo.select("#some-el div.some-class");
10924 // or select directly from an existing element
10925 var el = Roo.get('some-el');
10926 el.select('div.some-class');
10928 els.setWidth(100); // all elements become 100 width
10929 els.hide(true); // all elements fade out and hide
10931 els.setWidth(100).hide(true);
10932 </code></pre><br><br>
10933 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10934 * actions will be performed on all the elements in this collection.</b>
10936 Roo.CompositeElementLite = function(els){
10937 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10938 this.el = new Roo.Element.Flyweight();
10940 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10941 addElements : function(els){
10943 if(els instanceof Array){
10944 this.elements = this.elements.concat(els);
10946 var yels = this.elements;
10947 var index = yels.length-1;
10948 for(var i = 0, len = els.length; i < len; i++) {
10949 yels[++index] = els[i];
10955 invoke : function(fn, args){
10956 var els = this.elements;
10958 for(var i = 0, len = els.length; i < len; i++) {
10960 Roo.Element.prototype[fn].apply(el, args);
10965 * Returns a flyweight Element of the dom element object at the specified index
10966 * @param {Number} index
10967 * @return {Roo.Element}
10969 item : function(index){
10970 if(!this.elements[index]){
10973 this.el.dom = this.elements[index];
10977 // fixes scope with flyweight
10978 addListener : function(eventName, handler, scope, opt){
10979 var els = this.elements;
10980 for(var i = 0, len = els.length; i < len; i++) {
10981 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
10987 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
10988 * passed is the flyweight (shared) Roo.Element instance, so if you require a
10989 * a reference to the dom node, use el.dom.</b>
10990 * @param {Function} fn The function to call
10991 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10992 * @return {CompositeElement} this
10994 each : function(fn, scope){
10995 var els = this.elements;
10997 for(var i = 0, len = els.length; i < len; i++){
10999 if(fn.call(scope || el, el, this, i) === false){
11006 indexOf : function(el){
11007 return this.elements.indexOf(Roo.getDom(el));
11010 replaceElement : function(el, replacement, domReplace){
11011 var index = typeof el == 'number' ? el : this.indexOf(el);
11013 replacement = Roo.getDom(replacement);
11015 var d = this.elements[index];
11016 d.parentNode.insertBefore(replacement, d);
11017 d.parentNode.removeChild(d);
11019 this.elements.splice(index, 1, replacement);
11024 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
11028 * Ext JS Library 1.1.1
11029 * Copyright(c) 2006-2007, Ext JS, LLC.
11031 * Originally Released Under LGPL - original licence link has changed is not relivant.
11034 * <script type="text/javascript">
11040 * @class Roo.data.Connection
11041 * @extends Roo.util.Observable
11042 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
11043 * either to a configured URL, or to a URL specified at request time.<br><br>
11045 * Requests made by this class are asynchronous, and will return immediately. No data from
11046 * the server will be available to the statement immediately following the {@link #request} call.
11047 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
11049 * Note: If you are doing a file upload, you will not get a normal response object sent back to
11050 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
11051 * The response object is created using the innerHTML of the IFRAME's document as the responseText
11052 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
11053 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
11054 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
11055 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
11056 * standard DOM methods.
11058 * @param {Object} config a configuration object.
11060 Roo.data.Connection = function(config){
11061 Roo.apply(this, config);
11064 * @event beforerequest
11065 * Fires before a network request is made to retrieve a data object.
11066 * @param {Connection} conn This Connection object.
11067 * @param {Object} options The options config object passed to the {@link #request} method.
11069 "beforerequest" : true,
11071 * @event requestcomplete
11072 * Fires if the request was successfully completed.
11073 * @param {Connection} conn This Connection object.
11074 * @param {Object} response The XHR object containing the response data.
11075 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11076 * @param {Object} options The options config object passed to the {@link #request} method.
11078 "requestcomplete" : true,
11080 * @event requestexception
11081 * Fires if an error HTTP status was returned from the server.
11082 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11083 * @param {Connection} conn This Connection object.
11084 * @param {Object} response The XHR object containing the response data.
11085 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11086 * @param {Object} options The options config object passed to the {@link #request} method.
11088 "requestexception" : true
11090 Roo.data.Connection.superclass.constructor.call(this);
11093 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11095 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11098 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11099 * extra parameters to each request made by this object. (defaults to undefined)
11102 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11103 * to each request made by this object. (defaults to undefined)
11106 * @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)
11109 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11113 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11119 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11122 disableCaching: true,
11125 * Sends an HTTP request to a remote server.
11126 * @param {Object} options An object which may contain the following properties:<ul>
11127 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11128 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11129 * request, a url encoded string or a function to call to get either.</li>
11130 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11131 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11132 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11133 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11134 * <li>options {Object} The parameter to the request call.</li>
11135 * <li>success {Boolean} True if the request succeeded.</li>
11136 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11138 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11139 * The callback is passed the following parameters:<ul>
11140 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11141 * <li>options {Object} The parameter to the request call.</li>
11143 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11144 * The callback is passed the following parameters:<ul>
11145 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11146 * <li>options {Object} The parameter to the request call.</li>
11148 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11149 * for the callback function. Defaults to the browser window.</li>
11150 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11151 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11152 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11153 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11154 * params for the post data. Any params will be appended to the URL.</li>
11155 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11157 * @return {Number} transactionId
11159 request : function(o){
11160 if(this.fireEvent("beforerequest", this, o) !== false){
11163 if(typeof p == "function"){
11164 p = p.call(o.scope||window, o);
11166 if(typeof p == "object"){
11167 p = Roo.urlEncode(o.params);
11169 if(this.extraParams){
11170 var extras = Roo.urlEncode(this.extraParams);
11171 p = p ? (p + '&' + extras) : extras;
11174 var url = o.url || this.url;
11175 if(typeof url == 'function'){
11176 url = url.call(o.scope||window, o);
11180 var form = Roo.getDom(o.form);
11181 url = url || form.action;
11183 var enctype = form.getAttribute("enctype");
11184 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11185 return this.doFormUpload(o, p, url);
11187 var f = Roo.lib.Ajax.serializeForm(form);
11188 p = p ? (p + '&' + f) : f;
11191 var hs = o.headers;
11192 if(this.defaultHeaders){
11193 hs = Roo.apply(hs || {}, this.defaultHeaders);
11200 success: this.handleResponse,
11201 failure: this.handleFailure,
11203 argument: {options: o},
11204 timeout : this.timeout
11207 var method = o.method||this.method||(p ? "POST" : "GET");
11209 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11210 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11213 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11217 }else if(this.autoAbort !== false){
11221 if((method == 'GET' && p) || o.xmlData){
11222 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11225 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11226 return this.transId;
11228 Roo.callback(o.callback, o.scope, [o, null, null]);
11234 * Determine whether this object has a request outstanding.
11235 * @param {Number} transactionId (Optional) defaults to the last transaction
11236 * @return {Boolean} True if there is an outstanding request.
11238 isLoading : function(transId){
11240 return Roo.lib.Ajax.isCallInProgress(transId);
11242 return this.transId ? true : false;
11247 * Aborts any outstanding request.
11248 * @param {Number} transactionId (Optional) defaults to the last transaction
11250 abort : function(transId){
11251 if(transId || this.isLoading()){
11252 Roo.lib.Ajax.abort(transId || this.transId);
11257 handleResponse : function(response){
11258 this.transId = false;
11259 var options = response.argument.options;
11260 response.argument = options ? options.argument : null;
11261 this.fireEvent("requestcomplete", this, response, options);
11262 Roo.callback(options.success, options.scope, [response, options]);
11263 Roo.callback(options.callback, options.scope, [options, true, response]);
11267 handleFailure : function(response, e){
11268 this.transId = false;
11269 var options = response.argument.options;
11270 response.argument = options ? options.argument : null;
11271 this.fireEvent("requestexception", this, response, options, e);
11272 Roo.callback(options.failure, options.scope, [response, options]);
11273 Roo.callback(options.callback, options.scope, [options, false, response]);
11277 doFormUpload : function(o, ps, url){
11279 var frame = document.createElement('iframe');
11282 frame.className = 'x-hidden';
11284 frame.src = Roo.SSL_SECURE_URL;
11286 document.body.appendChild(frame);
11289 document.frames[id].name = id;
11292 var form = Roo.getDom(o.form);
11294 form.method = 'POST';
11295 form.enctype = form.encoding = 'multipart/form-data';
11301 if(ps){ // add dynamic params
11303 ps = Roo.urlDecode(ps, false);
11305 if(ps.hasOwnProperty(k)){
11306 hd = document.createElement('input');
11307 hd.type = 'hidden';
11310 form.appendChild(hd);
11317 var r = { // bogus response object
11322 r.argument = o ? o.argument : null;
11327 doc = frame.contentWindow.document;
11329 doc = (frame.contentDocument || window.frames[id].document);
11331 if(doc && doc.body){
11332 r.responseText = doc.body.innerHTML;
11334 if(doc && doc.XMLDocument){
11335 r.responseXML = doc.XMLDocument;
11337 r.responseXML = doc;
11344 Roo.EventManager.removeListener(frame, 'load', cb, this);
11346 this.fireEvent("requestcomplete", this, r, o);
11347 Roo.callback(o.success, o.scope, [r, o]);
11348 Roo.callback(o.callback, o.scope, [o, true, r]);
11350 setTimeout(function(){document.body.removeChild(frame);}, 100);
11353 Roo.EventManager.on(frame, 'load', cb, this);
11356 if(hiddens){ // remove dynamic params
11357 for(var i = 0, len = hiddens.length; i < len; i++){
11358 form.removeChild(hiddens[i]);
11366 * @extends Roo.data.Connection
11367 * Global Ajax request class.
11371 Roo.Ajax = new Roo.data.Connection({
11374 * @cfg {String} url @hide
11377 * @cfg {Object} extraParams @hide
11380 * @cfg {Object} defaultHeaders @hide
11383 * @cfg {String} method (Optional) @hide
11386 * @cfg {Number} timeout (Optional) @hide
11389 * @cfg {Boolean} autoAbort (Optional) @hide
11393 * @cfg {Boolean} disableCaching (Optional) @hide
11397 * @property disableCaching
11398 * True to add a unique cache-buster param to GET requests. (defaults to true)
11403 * The default URL to be used for requests to the server. (defaults to undefined)
11407 * @property extraParams
11408 * An object containing properties which are used as
11409 * extra parameters to each request made by this object. (defaults to undefined)
11413 * @property defaultHeaders
11414 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11419 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11423 * @property timeout
11424 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11429 * @property autoAbort
11430 * Whether a new request should abort any pending requests. (defaults to false)
11436 * Serialize the passed form into a url encoded string
11437 * @param {String/HTMLElement} form
11440 serializeForm : function(form){
11441 return Roo.lib.Ajax.serializeForm(form);
11445 * Ext JS Library 1.1.1
11446 * Copyright(c) 2006-2007, Ext JS, LLC.
11448 * Originally Released Under LGPL - original licence link has changed is not relivant.
11451 * <script type="text/javascript">
11456 * @extends Roo.data.Connection
11457 * Global Ajax request class.
11459 * @instanceOf Roo.data.Connection
11461 Roo.Ajax = new Roo.data.Connection({
11470 * @cfg {String} url @hide
11473 * @cfg {Object} extraParams @hide
11476 * @cfg {Object} defaultHeaders @hide
11479 * @cfg {String} method (Optional) @hide
11482 * @cfg {Number} timeout (Optional) @hide
11485 * @cfg {Boolean} autoAbort (Optional) @hide
11489 * @cfg {Boolean} disableCaching (Optional) @hide
11493 * @property disableCaching
11494 * True to add a unique cache-buster param to GET requests. (defaults to true)
11499 * The default URL to be used for requests to the server. (defaults to undefined)
11503 * @property extraParams
11504 * An object containing properties which are used as
11505 * extra parameters to each request made by this object. (defaults to undefined)
11509 * @property defaultHeaders
11510 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11515 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11519 * @property timeout
11520 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11525 * @property autoAbort
11526 * Whether a new request should abort any pending requests. (defaults to false)
11532 * Serialize the passed form into a url encoded string
11533 * @param {String/HTMLElement} form
11536 serializeForm : function(form){
11537 return Roo.lib.Ajax.serializeForm(form);
11541 * Ext JS Library 1.1.1
11542 * Copyright(c) 2006-2007, Ext JS, LLC.
11544 * Originally Released Under LGPL - original licence link has changed is not relivant.
11547 * <script type="text/javascript">
11552 * @class Roo.UpdateManager
11553 * @extends Roo.util.Observable
11554 * Provides AJAX-style update for Element object.<br><br>
11557 * // Get it from a Roo.Element object
11558 * var el = Roo.get("foo");
11559 * var mgr = el.getUpdateManager();
11560 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11562 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11564 * // or directly (returns the same UpdateManager instance)
11565 * var mgr = new Roo.UpdateManager("myElementId");
11566 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11567 * mgr.on("update", myFcnNeedsToKnow);
11569 // short handed call directly from the element object
11570 Roo.get("foo").load({
11574 text: "Loading Foo..."
11578 * Create new UpdateManager directly.
11579 * @param {String/HTMLElement/Roo.Element} el The element to update
11580 * @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).
11582 Roo.UpdateManager = function(el, forceNew){
11584 if(!forceNew && el.updateManager){
11585 return el.updateManager;
11588 * The Element object
11589 * @type Roo.Element
11593 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11596 this.defaultUrl = null;
11600 * @event beforeupdate
11601 * Fired before an update is made, return false from your handler and the update is cancelled.
11602 * @param {Roo.Element} el
11603 * @param {String/Object/Function} url
11604 * @param {String/Object} params
11606 "beforeupdate": true,
11609 * Fired after successful update is made.
11610 * @param {Roo.Element} el
11611 * @param {Object} oResponseObject The response Object
11616 * Fired on update failure.
11617 * @param {Roo.Element} el
11618 * @param {Object} oResponseObject The response Object
11622 var d = Roo.UpdateManager.defaults;
11624 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11627 this.sslBlankUrl = d.sslBlankUrl;
11629 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11632 this.disableCaching = d.disableCaching;
11634 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11637 this.indicatorText = d.indicatorText;
11639 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11642 this.showLoadIndicator = d.showLoadIndicator;
11644 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11647 this.timeout = d.timeout;
11650 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11653 this.loadScripts = d.loadScripts;
11656 * Transaction object of current executing transaction
11658 this.transaction = null;
11663 this.autoRefreshProcId = null;
11665 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11668 this.refreshDelegate = this.refresh.createDelegate(this);
11670 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11673 this.updateDelegate = this.update.createDelegate(this);
11675 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11678 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11682 this.successDelegate = this.processSuccess.createDelegate(this);
11686 this.failureDelegate = this.processFailure.createDelegate(this);
11688 if(!this.renderer){
11690 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11692 this.renderer = new Roo.UpdateManager.BasicRenderer();
11695 Roo.UpdateManager.superclass.constructor.call(this);
11698 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11700 * Get the Element this UpdateManager is bound to
11701 * @return {Roo.Element} The element
11703 getEl : function(){
11707 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11708 * @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:
11711 url: "your-url.php",<br/>
11712 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11713 callback: yourFunction,<br/>
11714 scope: yourObject, //(optional scope) <br/>
11715 discardUrl: false, <br/>
11716 nocache: false,<br/>
11717 text: "Loading...",<br/>
11719 scripts: false<br/>
11722 * The only required property is url. The optional properties nocache, text and scripts
11723 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11724 * @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}
11725 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11726 * @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.
11728 update : function(url, params, callback, discardUrl){
11729 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11730 var method = this.method, cfg;
11731 if(typeof url == "object"){ // must be config object
11734 params = params || cfg.params;
11735 callback = callback || cfg.callback;
11736 discardUrl = discardUrl || cfg.discardUrl;
11737 if(callback && cfg.scope){
11738 callback = callback.createDelegate(cfg.scope);
11740 if(typeof cfg.method != "undefined"){method = cfg.method;};
11741 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11742 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11743 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11744 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11746 this.showLoading();
11748 this.defaultUrl = url;
11750 if(typeof url == "function"){
11751 url = url.call(this);
11754 method = method || (params ? "POST" : "GET");
11755 if(method == "GET"){
11756 url = this.prepareUrl(url);
11759 var o = Roo.apply(cfg ||{}, {
11762 success: this.successDelegate,
11763 failure: this.failureDelegate,
11764 callback: undefined,
11765 timeout: (this.timeout*1000),
11766 argument: {"url": url, "form": null, "callback": callback, "params": params}
11769 this.transaction = Roo.Ajax.request(o);
11774 * 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.
11775 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11776 * @param {String/HTMLElement} form The form Id or form element
11777 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11778 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11779 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11781 formUpdate : function(form, url, reset, callback){
11782 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11783 if(typeof url == "function"){
11784 url = url.call(this);
11786 form = Roo.getDom(form);
11787 this.transaction = Roo.Ajax.request({
11790 success: this.successDelegate,
11791 failure: this.failureDelegate,
11792 timeout: (this.timeout*1000),
11793 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11795 this.showLoading.defer(1, this);
11800 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11801 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11803 refresh : function(callback){
11804 if(this.defaultUrl == null){
11807 this.update(this.defaultUrl, null, callback, true);
11811 * Set this element to auto refresh.
11812 * @param {Number} interval How often to update (in seconds).
11813 * @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)
11814 * @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}
11815 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11816 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11818 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11820 this.update(url || this.defaultUrl, params, callback, true);
11822 if(this.autoRefreshProcId){
11823 clearInterval(this.autoRefreshProcId);
11825 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11829 * Stop auto refresh on this element.
11831 stopAutoRefresh : function(){
11832 if(this.autoRefreshProcId){
11833 clearInterval(this.autoRefreshProcId);
11834 delete this.autoRefreshProcId;
11838 isAutoRefreshing : function(){
11839 return this.autoRefreshProcId ? true : false;
11842 * Called to update the element to "Loading" state. Override to perform custom action.
11844 showLoading : function(){
11845 if(this.showLoadIndicator){
11846 this.el.update(this.indicatorText);
11851 * Adds unique parameter to query string if disableCaching = true
11854 prepareUrl : function(url){
11855 if(this.disableCaching){
11856 var append = "_dc=" + (new Date().getTime());
11857 if(url.indexOf("?") !== -1){
11858 url += "&" + append;
11860 url += "?" + append;
11869 processSuccess : function(response){
11870 this.transaction = null;
11871 if(response.argument.form && response.argument.reset){
11872 try{ // put in try/catch since some older FF releases had problems with this
11873 response.argument.form.reset();
11876 if(this.loadScripts){
11877 this.renderer.render(this.el, response, this,
11878 this.updateComplete.createDelegate(this, [response]));
11880 this.renderer.render(this.el, response, this);
11881 this.updateComplete(response);
11885 updateComplete : function(response){
11886 this.fireEvent("update", this.el, response);
11887 if(typeof response.argument.callback == "function"){
11888 response.argument.callback(this.el, true, response);
11895 processFailure : function(response){
11896 this.transaction = null;
11897 this.fireEvent("failure", this.el, response);
11898 if(typeof response.argument.callback == "function"){
11899 response.argument.callback(this.el, false, response);
11904 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11905 * @param {Object} renderer The object implementing the render() method
11907 setRenderer : function(renderer){
11908 this.renderer = renderer;
11911 getRenderer : function(){
11912 return this.renderer;
11916 * Set the defaultUrl used for updates
11917 * @param {String/Function} defaultUrl The url or a function to call to get the url
11919 setDefaultUrl : function(defaultUrl){
11920 this.defaultUrl = defaultUrl;
11924 * Aborts the executing transaction
11926 abort : function(){
11927 if(this.transaction){
11928 Roo.Ajax.abort(this.transaction);
11933 * Returns true if an update is in progress
11934 * @return {Boolean}
11936 isUpdating : function(){
11937 if(this.transaction){
11938 return Roo.Ajax.isLoading(this.transaction);
11945 * @class Roo.UpdateManager.defaults
11946 * @static (not really - but it helps the doc tool)
11947 * The defaults collection enables customizing the default properties of UpdateManager
11949 Roo.UpdateManager.defaults = {
11951 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
11957 * True to process scripts by default (Defaults to false).
11960 loadScripts : false,
11963 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
11966 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
11968 * Whether to append unique parameter on get request to disable caching (Defaults to false).
11971 disableCaching : false,
11973 * Whether to show indicatorText when loading (Defaults to true).
11976 showLoadIndicator : true,
11978 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
11981 indicatorText : '<div class="loading-indicator">Loading...</div>'
11985 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
11987 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
11988 * @param {String/HTMLElement/Roo.Element} el The element to update
11989 * @param {String} url The url
11990 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
11991 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
11994 * @member Roo.UpdateManager
11996 Roo.UpdateManager.updateElement = function(el, url, params, options){
11997 var um = Roo.get(el, true).getUpdateManager();
11998 Roo.apply(um, options);
11999 um.update(url, params, options ? options.callback : null);
12001 // alias for backwards compat
12002 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
12004 * @class Roo.UpdateManager.BasicRenderer
12005 * Default Content renderer. Updates the elements innerHTML with the responseText.
12007 Roo.UpdateManager.BasicRenderer = function(){};
12009 Roo.UpdateManager.BasicRenderer.prototype = {
12011 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
12012 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
12013 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
12014 * @param {Roo.Element} el The element being rendered
12015 * @param {Object} response The YUI Connect response object
12016 * @param {UpdateManager} updateManager The calling update manager
12017 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
12019 render : function(el, response, updateManager, callback){
12020 el.update(response.responseText, updateManager.loadScripts, callback);
12025 * Ext JS Library 1.1.1
12026 * Copyright(c) 2006-2007, Ext JS, LLC.
12028 * Originally Released Under LGPL - original licence link has changed is not relivant.
12031 * <script type="text/javascript">
12035 * @class Roo.util.DelayedTask
12036 * Provides a convenient method of performing setTimeout where a new
12037 * timeout cancels the old timeout. An example would be performing validation on a keypress.
12038 * You can use this class to buffer
12039 * the keypress events for a certain number of milliseconds, and perform only if they stop
12040 * for that amount of time.
12041 * @constructor The parameters to this constructor serve as defaults and are not required.
12042 * @param {Function} fn (optional) The default function to timeout
12043 * @param {Object} scope (optional) The default scope of that timeout
12044 * @param {Array} args (optional) The default Array of arguments
12046 Roo.util.DelayedTask = function(fn, scope, args){
12047 var id = null, d, t;
12049 var call = function(){
12050 var now = new Date().getTime();
12054 fn.apply(scope, args || []);
12058 * Cancels any pending timeout and queues a new one
12059 * @param {Number} delay The milliseconds to delay
12060 * @param {Function} newFn (optional) Overrides function passed to constructor
12061 * @param {Object} newScope (optional) Overrides scope passed to constructor
12062 * @param {Array} newArgs (optional) Overrides args passed to constructor
12064 this.delay = function(delay, newFn, newScope, newArgs){
12065 if(id && delay != d){
12069 t = new Date().getTime();
12071 scope = newScope || scope;
12072 args = newArgs || args;
12074 id = setInterval(call, d);
12079 * Cancel the last queued timeout
12081 this.cancel = function(){
12089 * Ext JS Library 1.1.1
12090 * Copyright(c) 2006-2007, Ext JS, LLC.
12092 * Originally Released Under LGPL - original licence link has changed is not relivant.
12095 * <script type="text/javascript">
12099 Roo.util.TaskRunner = function(interval){
12100 interval = interval || 10;
12101 var tasks = [], removeQueue = [];
12103 var running = false;
12105 var stopThread = function(){
12111 var startThread = function(){
12114 id = setInterval(runTasks, interval);
12118 var removeTask = function(task){
12119 removeQueue.push(task);
12125 var runTasks = function(){
12126 if(removeQueue.length > 0){
12127 for(var i = 0, len = removeQueue.length; i < len; i++){
12128 tasks.remove(removeQueue[i]);
12131 if(tasks.length < 1){
12136 var now = new Date().getTime();
12137 for(var i = 0, len = tasks.length; i < len; ++i){
12139 var itime = now - t.taskRunTime;
12140 if(t.interval <= itime){
12141 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12142 t.taskRunTime = now;
12143 if(rt === false || t.taskRunCount === t.repeat){
12148 if(t.duration && t.duration <= (now - t.taskStartTime)){
12155 * Queues a new task.
12156 * @param {Object} task
12158 this.start = function(task){
12160 task.taskStartTime = new Date().getTime();
12161 task.taskRunTime = 0;
12162 task.taskRunCount = 0;
12167 this.stop = function(task){
12172 this.stopAll = function(){
12174 for(var i = 0, len = tasks.length; i < len; i++){
12175 if(tasks[i].onStop){
12184 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12186 * Ext JS Library 1.1.1
12187 * Copyright(c) 2006-2007, Ext JS, LLC.
12189 * Originally Released Under LGPL - original licence link has changed is not relivant.
12192 * <script type="text/javascript">
12197 * @class Roo.util.MixedCollection
12198 * @extends Roo.util.Observable
12199 * A Collection class that maintains both numeric indexes and keys and exposes events.
12201 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12202 * collection (defaults to false)
12203 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12204 * and return the key value for that item. This is used when available to look up the key on items that
12205 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12206 * equivalent to providing an implementation for the {@link #getKey} method.
12208 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12216 * Fires when the collection is cleared.
12221 * Fires when an item is added to the collection.
12222 * @param {Number} index The index at which the item was added.
12223 * @param {Object} o The item added.
12224 * @param {String} key The key associated with the added item.
12229 * Fires when an item is replaced in the collection.
12230 * @param {String} key he key associated with the new added.
12231 * @param {Object} old The item being replaced.
12232 * @param {Object} new The new item.
12237 * Fires when an item is removed from the collection.
12238 * @param {Object} o The item being removed.
12239 * @param {String} key (optional) The key associated with the removed item.
12244 this.allowFunctions = allowFunctions === true;
12246 this.getKey = keyFn;
12248 Roo.util.MixedCollection.superclass.constructor.call(this);
12251 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12252 allowFunctions : false,
12255 * Adds an item to the collection.
12256 * @param {String} key The key to associate with the item
12257 * @param {Object} o The item to add.
12258 * @return {Object} The item added.
12260 add : function(key, o){
12261 if(arguments.length == 1){
12263 key = this.getKey(o);
12265 if(typeof key == "undefined" || key === null){
12267 this.items.push(o);
12268 this.keys.push(null);
12270 var old = this.map[key];
12272 return this.replace(key, o);
12275 this.items.push(o);
12277 this.keys.push(key);
12279 this.fireEvent("add", this.length-1, o, key);
12284 * MixedCollection has a generic way to fetch keys if you implement getKey.
12287 var mc = new Roo.util.MixedCollection();
12288 mc.add(someEl.dom.id, someEl);
12289 mc.add(otherEl.dom.id, otherEl);
12293 var mc = new Roo.util.MixedCollection();
12294 mc.getKey = function(el){
12300 // or via the constructor
12301 var mc = new Roo.util.MixedCollection(false, function(el){
12307 * @param o {Object} The item for which to find the key.
12308 * @return {Object} The key for the passed item.
12310 getKey : function(o){
12315 * Replaces an item in the collection.
12316 * @param {String} key The key associated with the item to replace, or the item to replace.
12317 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12318 * @return {Object} The new item.
12320 replace : function(key, o){
12321 if(arguments.length == 1){
12323 key = this.getKey(o);
12325 var old = this.item(key);
12326 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12327 return this.add(key, o);
12329 var index = this.indexOfKey(key);
12330 this.items[index] = o;
12332 this.fireEvent("replace", key, old, o);
12337 * Adds all elements of an Array or an Object to the collection.
12338 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12339 * an Array of values, each of which are added to the collection.
12341 addAll : function(objs){
12342 if(arguments.length > 1 || objs instanceof Array){
12343 var args = arguments.length > 1 ? arguments : objs;
12344 for(var i = 0, len = args.length; i < len; i++){
12348 for(var key in objs){
12349 if(this.allowFunctions || typeof objs[key] != "function"){
12350 this.add(key, objs[key]);
12357 * Executes the specified function once for every item in the collection, passing each
12358 * item as the first and only parameter. returning false from the function will stop the iteration.
12359 * @param {Function} fn The function to execute for each item.
12360 * @param {Object} scope (optional) The scope in which to execute the function.
12362 each : function(fn, scope){
12363 var items = [].concat(this.items); // each safe for removal
12364 for(var i = 0, len = items.length; i < len; i++){
12365 if(fn.call(scope || items[i], items[i], i, len) === false){
12372 * Executes the specified function once for every key in the collection, passing each
12373 * key, and its associated item as the first two parameters.
12374 * @param {Function} fn The function to execute for each item.
12375 * @param {Object} scope (optional) The scope in which to execute the function.
12377 eachKey : function(fn, scope){
12378 for(var i = 0, len = this.keys.length; i < len; i++){
12379 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12384 * Returns the first item in the collection which elicits a true return value from the
12385 * passed selection function.
12386 * @param {Function} fn The selection function to execute for each item.
12387 * @param {Object} scope (optional) The scope in which to execute the function.
12388 * @return {Object} The first item in the collection which returned true from the selection function.
12390 find : function(fn, scope){
12391 for(var i = 0, len = this.items.length; i < len; i++){
12392 if(fn.call(scope || window, this.items[i], this.keys[i])){
12393 return this.items[i];
12400 * Inserts an item at the specified index in the collection.
12401 * @param {Number} index The index to insert the item at.
12402 * @param {String} key The key to associate with the new item, or the item itself.
12403 * @param {Object} o (optional) If the second parameter was a key, the new item.
12404 * @return {Object} The item inserted.
12406 insert : function(index, key, o){
12407 if(arguments.length == 2){
12409 key = this.getKey(o);
12411 if(index >= this.length){
12412 return this.add(key, o);
12415 this.items.splice(index, 0, o);
12416 if(typeof key != "undefined" && key != null){
12419 this.keys.splice(index, 0, key);
12420 this.fireEvent("add", index, o, key);
12425 * Removed an item from the collection.
12426 * @param {Object} o The item to remove.
12427 * @return {Object} The item removed.
12429 remove : function(o){
12430 return this.removeAt(this.indexOf(o));
12434 * Remove an item from a specified index in the collection.
12435 * @param {Number} index The index within the collection of the item to remove.
12437 removeAt : function(index){
12438 if(index < this.length && index >= 0){
12440 var o = this.items[index];
12441 this.items.splice(index, 1);
12442 var key = this.keys[index];
12443 if(typeof key != "undefined"){
12444 delete this.map[key];
12446 this.keys.splice(index, 1);
12447 this.fireEvent("remove", o, key);
12452 * Removed an item associated with the passed key fom the collection.
12453 * @param {String} key The key of the item to remove.
12455 removeKey : function(key){
12456 return this.removeAt(this.indexOfKey(key));
12460 * Returns the number of items in the collection.
12461 * @return {Number} the number of items in the collection.
12463 getCount : function(){
12464 return this.length;
12468 * Returns index within the collection of the passed Object.
12469 * @param {Object} o The item to find the index of.
12470 * @return {Number} index of the item.
12472 indexOf : function(o){
12473 if(!this.items.indexOf){
12474 for(var i = 0, len = this.items.length; i < len; i++){
12475 if(this.items[i] == o) return i;
12479 return this.items.indexOf(o);
12484 * Returns index within the collection of the passed key.
12485 * @param {String} key The key to find the index of.
12486 * @return {Number} index of the key.
12488 indexOfKey : function(key){
12489 if(!this.keys.indexOf){
12490 for(var i = 0, len = this.keys.length; i < len; i++){
12491 if(this.keys[i] == key) return i;
12495 return this.keys.indexOf(key);
12500 * Returns the item associated with the passed key OR index. Key has priority over index.
12501 * @param {String/Number} key The key or index of the item.
12502 * @return {Object} The item associated with the passed key.
12504 item : function(key){
12505 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12506 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12510 * Returns the item at the specified index.
12511 * @param {Number} index The index of the item.
12514 itemAt : function(index){
12515 return this.items[index];
12519 * Returns the item associated with the passed key.
12520 * @param {String/Number} key The key of the item.
12521 * @return {Object} The item associated with the passed key.
12523 key : function(key){
12524 return this.map[key];
12528 * Returns true if the collection contains the passed Object as an item.
12529 * @param {Object} o The Object to look for in the collection.
12530 * @return {Boolean} True if the collection contains the Object as an item.
12532 contains : function(o){
12533 return this.indexOf(o) != -1;
12537 * Returns true if the collection contains the passed Object as a key.
12538 * @param {String} key The key to look for in the collection.
12539 * @return {Boolean} True if the collection contains the Object as a key.
12541 containsKey : function(key){
12542 return typeof this.map[key] != "undefined";
12546 * Removes all items from the collection.
12548 clear : function(){
12553 this.fireEvent("clear");
12557 * Returns the first item in the collection.
12558 * @return {Object} the first item in the collection..
12560 first : function(){
12561 return this.items[0];
12565 * Returns the last item in the collection.
12566 * @return {Object} the last item in the collection..
12569 return this.items[this.length-1];
12572 _sort : function(property, dir, fn){
12573 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12574 fn = fn || function(a, b){
12577 var c = [], k = this.keys, items = this.items;
12578 for(var i = 0, len = items.length; i < len; i++){
12579 c[c.length] = {key: k[i], value: items[i], index: i};
12581 c.sort(function(a, b){
12582 var v = fn(a[property], b[property]) * dsc;
12584 v = (a.index < b.index ? -1 : 1);
12588 for(var i = 0, len = c.length; i < len; i++){
12589 items[i] = c[i].value;
12592 this.fireEvent("sort", this);
12596 * Sorts this collection with the passed comparison function
12597 * @param {String} direction (optional) "ASC" or "DESC"
12598 * @param {Function} fn (optional) comparison function
12600 sort : function(dir, fn){
12601 this._sort("value", dir, fn);
12605 * Sorts this collection by keys
12606 * @param {String} direction (optional) "ASC" or "DESC"
12607 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12609 keySort : function(dir, fn){
12610 this._sort("key", dir, fn || function(a, b){
12611 return String(a).toUpperCase()-String(b).toUpperCase();
12616 * Returns a range of items in this collection
12617 * @param {Number} startIndex (optional) defaults to 0
12618 * @param {Number} endIndex (optional) default to the last item
12619 * @return {Array} An array of items
12621 getRange : function(start, end){
12622 var items = this.items;
12623 if(items.length < 1){
12626 start = start || 0;
12627 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12630 for(var i = start; i <= end; i++) {
12631 r[r.length] = items[i];
12634 for(var i = start; i >= end; i--) {
12635 r[r.length] = items[i];
12642 * Filter the <i>objects</i> in this collection by a specific property.
12643 * Returns a new collection that has been filtered.
12644 * @param {String} property A property on your objects
12645 * @param {String/RegExp} value Either string that the property values
12646 * should start with or a RegExp to test against the property
12647 * @return {MixedCollection} The new filtered collection
12649 filter : function(property, value){
12650 if(!value.exec){ // not a regex
12651 value = String(value);
12652 if(value.length == 0){
12653 return this.clone();
12655 value = new RegExp("^" + Roo.escapeRe(value), "i");
12657 return this.filterBy(function(o){
12658 return o && value.test(o[property]);
12663 * Filter by a function. * Returns a new collection that has been filtered.
12664 * The passed function will be called with each
12665 * object in the collection. If the function returns true, the value is included
12666 * otherwise it is filtered.
12667 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12668 * @param {Object} scope (optional) The scope of the function (defaults to this)
12669 * @return {MixedCollection} The new filtered collection
12671 filterBy : function(fn, scope){
12672 var r = new Roo.util.MixedCollection();
12673 r.getKey = this.getKey;
12674 var k = this.keys, it = this.items;
12675 for(var i = 0, len = it.length; i < len; i++){
12676 if(fn.call(scope||this, it[i], k[i])){
12677 r.add(k[i], it[i]);
12684 * Creates a duplicate of this collection
12685 * @return {MixedCollection}
12687 clone : function(){
12688 var r = new Roo.util.MixedCollection();
12689 var k = this.keys, it = this.items;
12690 for(var i = 0, len = it.length; i < len; i++){
12691 r.add(k[i], it[i]);
12693 r.getKey = this.getKey;
12698 * Returns the item associated with the passed key or index.
12700 * @param {String/Number} key The key or index of the item.
12701 * @return {Object} The item associated with the passed key.
12703 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12705 * Ext JS Library 1.1.1
12706 * Copyright(c) 2006-2007, Ext JS, LLC.
12708 * Originally Released Under LGPL - original licence link has changed is not relivant.
12711 * <script type="text/javascript">
12714 * @class Roo.util.JSON
12715 * Modified version of Douglas Crockford"s json.js that doesn"t
12716 * mess with the Object prototype
12717 * http://www.json.org/js.html
12720 Roo.util.JSON = new (function(){
12721 var useHasOwn = {}.hasOwnProperty ? true : false;
12723 // crashes Safari in some instances
12724 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12726 var pad = function(n) {
12727 return n < 10 ? "0" + n : n;
12740 var encodeString = function(s){
12741 if (/["\\\x00-\x1f]/.test(s)) {
12742 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12747 c = b.charCodeAt();
12749 Math.floor(c / 16).toString(16) +
12750 (c % 16).toString(16);
12753 return '"' + s + '"';
12756 var encodeArray = function(o){
12757 var a = ["["], b, i, l = o.length, v;
12758 for (i = 0; i < l; i += 1) {
12760 switch (typeof v) {
12769 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12777 var encodeDate = function(o){
12778 return '"' + o.getFullYear() + "-" +
12779 pad(o.getMonth() + 1) + "-" +
12780 pad(o.getDate()) + "T" +
12781 pad(o.getHours()) + ":" +
12782 pad(o.getMinutes()) + ":" +
12783 pad(o.getSeconds()) + '"';
12787 * Encodes an Object, Array or other value
12788 * @param {Mixed} o The variable to encode
12789 * @return {String} The JSON string
12791 this.encode = function(o)
12793 // should this be extended to fully wrap stringify..
12795 if(typeof o == "undefined" || o === null){
12797 }else if(o instanceof Array){
12798 return encodeArray(o);
12799 }else if(o instanceof Date){
12800 return encodeDate(o);
12801 }else if(typeof o == "string"){
12802 return encodeString(o);
12803 }else if(typeof o == "number"){
12804 return isFinite(o) ? String(o) : "null";
12805 }else if(typeof o == "boolean"){
12808 var a = ["{"], b, i, v;
12810 if(!useHasOwn || o.hasOwnProperty(i)) {
12812 switch (typeof v) {
12821 a.push(this.encode(i), ":",
12822 v === null ? "null" : this.encode(v));
12833 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12834 * @param {String} json The JSON string
12835 * @return {Object} The resulting object
12837 this.decode = function(json){
12839 return /** eval:var:json */ eval("(" + json + ')');
12843 * Shorthand for {@link Roo.util.JSON#encode}
12844 * @member Roo encode
12846 Roo.encode = typeof(JSON) != 'undefined' && JSON.stringify ? JSON.stringify : Roo.util.JSON.encode;
12848 * Shorthand for {@link Roo.util.JSON#decode}
12849 * @member Roo decode
12851 Roo.decode = typeof(JSON) != 'undefined' && JSON.parse ? JSON.parse : Roo.util.JSON.decode;
12854 * Ext JS Library 1.1.1
12855 * Copyright(c) 2006-2007, Ext JS, LLC.
12857 * Originally Released Under LGPL - original licence link has changed is not relivant.
12860 * <script type="text/javascript">
12864 * @class Roo.util.Format
12865 * Reusable data formatting functions
12868 Roo.util.Format = function(){
12869 var trimRe = /^\s+|\s+$/g;
12872 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12873 * @param {String} value The string to truncate
12874 * @param {Number} length The maximum length to allow before truncating
12875 * @return {String} The converted text
12877 ellipsis : function(value, len){
12878 if(value && value.length > len){
12879 return value.substr(0, len-3)+"...";
12885 * Checks a reference and converts it to empty string if it is undefined
12886 * @param {Mixed} value Reference to check
12887 * @return {Mixed} Empty string if converted, otherwise the original value
12889 undef : function(value){
12890 return typeof value != "undefined" ? value : "";
12894 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12895 * @param {String} value The string to encode
12896 * @return {String} The encoded text
12898 htmlEncode : function(value){
12899 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12903 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12904 * @param {String} value The string to decode
12905 * @return {String} The decoded text
12907 htmlDecode : function(value){
12908 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12912 * Trims any whitespace from either side of a string
12913 * @param {String} value The text to trim
12914 * @return {String} The trimmed text
12916 trim : function(value){
12917 return String(value).replace(trimRe, "");
12921 * Returns a substring from within an original string
12922 * @param {String} value The original text
12923 * @param {Number} start The start index of the substring
12924 * @param {Number} length The length of the substring
12925 * @return {String} The substring
12927 substr : function(value, start, length){
12928 return String(value).substr(start, length);
12932 * Converts a string to all lower case letters
12933 * @param {String} value The text to convert
12934 * @return {String} The converted text
12936 lowercase : function(value){
12937 return String(value).toLowerCase();
12941 * Converts a string to all upper case letters
12942 * @param {String} value The text to convert
12943 * @return {String} The converted text
12945 uppercase : function(value){
12946 return String(value).toUpperCase();
12950 * Converts the first character only of a string to upper case
12951 * @param {String} value The text to convert
12952 * @return {String} The converted text
12954 capitalize : function(value){
12955 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
12959 call : function(value, fn){
12960 if(arguments.length > 2){
12961 var args = Array.prototype.slice.call(arguments, 2);
12962 args.unshift(value);
12964 return /** eval:var:value */ eval(fn).apply(window, args);
12966 /** eval:var:value */
12967 return /** eval:var:value */ eval(fn).call(window, value);
12973 * safer version of Math.toFixed..??/
12974 * @param {Number/String} value The numeric value to format
12975 * @param {Number/String} value Decimal places
12976 * @return {String} The formatted currency string
12978 toFixed : function(v, n)
12980 // why not use to fixed - precision is buggered???
12982 return Math.round(v-0);
12984 var fact = Math.pow(10,n+1);
12985 v = (Math.round((v-0)*fact))/fact;
12986 var z = (''+fact).substring(2);
12987 if (v == Math.floor(v)) {
12988 return Math.floor(v) + '.' + z;
12991 // now just padd decimals..
12992 var ps = String(v).split('.');
12993 var fd = (ps[1] + z);
12994 var r = fd.substring(0,n);
12995 var rm = fd.substring(n);
12997 return ps[0] + '.' + r;
12999 r*=1; // turn it into a number;
13001 if (String(r).length != n) {
13004 r = String(r).substring(1); // chop the end off.
13007 return ps[0] + '.' + r;
13012 * Format a number as US currency
13013 * @param {Number/String} value The numeric value to format
13014 * @return {String} The formatted currency string
13016 usMoney : function(v){
13017 v = (Math.round((v-0)*100))/100;
13018 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
13020 var ps = v.split('.');
13022 var sub = ps[1] ? '.'+ ps[1] : '.00';
13023 var r = /(\d+)(\d{3})/;
13024 while (r.test(whole)) {
13025 whole = whole.replace(r, '$1' + ',' + '$2');
13027 return "$" + whole + sub ;
13031 * Parse a value into a formatted date using the specified format pattern.
13032 * @param {Mixed} value The value to format
13033 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
13034 * @return {String} The formatted date string
13036 date : function(v, format){
13040 if(!(v instanceof Date)){
13041 v = new Date(Date.parse(v));
13043 return v.dateFormat(format || "m/d/Y");
13047 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
13048 * @param {String} format Any valid date format string
13049 * @return {Function} The date formatting function
13051 dateRenderer : function(format){
13052 return function(v){
13053 return Roo.util.Format.date(v, format);
13058 stripTagsRE : /<\/?[^>]+>/gi,
13061 * Strips all HTML tags
13062 * @param {Mixed} value The text from which to strip tags
13063 * @return {String} The stripped text
13065 stripTags : function(v){
13066 return !v ? v : String(v).replace(this.stripTagsRE, "");
13071 * Ext JS Library 1.1.1
13072 * Copyright(c) 2006-2007, Ext JS, LLC.
13074 * Originally Released Under LGPL - original licence link has changed is not relivant.
13077 * <script type="text/javascript">
13084 * @class Roo.MasterTemplate
13085 * @extends Roo.Template
13086 * Provides a template that can have child templates. The syntax is:
13088 var t = new Roo.MasterTemplate(
13089 '<select name="{name}">',
13090 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
13093 t.add('options', {value: 'foo', text: 'bar'});
13094 // or you can add multiple child elements in one shot
13095 t.addAll('options', [
13096 {value: 'foo', text: 'bar'},
13097 {value: 'foo2', text: 'bar2'},
13098 {value: 'foo3', text: 'bar3'}
13100 // then append, applying the master template values
13101 t.append('my-form', {name: 'my-select'});
13103 * A name attribute for the child template is not required if you have only one child
13104 * template or you want to refer to them by index.
13106 Roo.MasterTemplate = function(){
13107 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13108 this.originalHtml = this.html;
13110 var m, re = this.subTemplateRe;
13113 while(m = re.exec(this.html)){
13114 var name = m[1], content = m[2];
13119 tpl : new Roo.Template(content)
13122 st[name] = st[subIndex];
13124 st[subIndex].tpl.compile();
13125 st[subIndex].tpl.call = this.call.createDelegate(this);
13128 this.subCount = subIndex;
13131 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13133 * The regular expression used to match sub templates
13137 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13140 * Applies the passed values to a child template.
13141 * @param {String/Number} name (optional) The name or index of the child template
13142 * @param {Array/Object} values The values to be applied to the template
13143 * @return {MasterTemplate} this
13145 add : function(name, values){
13146 if(arguments.length == 1){
13147 values = arguments[0];
13150 var s = this.subs[name];
13151 s.buffer[s.buffer.length] = s.tpl.apply(values);
13156 * Applies all the passed values to a child template.
13157 * @param {String/Number} name (optional) The name or index of the child template
13158 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13159 * @param {Boolean} reset (optional) True to reset the template first
13160 * @return {MasterTemplate} this
13162 fill : function(name, values, reset){
13164 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13172 for(var i = 0, len = values.length; i < len; i++){
13173 this.add(name, values[i]);
13179 * Resets the template for reuse
13180 * @return {MasterTemplate} this
13182 reset : function(){
13184 for(var i = 0; i < this.subCount; i++){
13190 applyTemplate : function(values){
13192 var replaceIndex = -1;
13193 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13194 return s[++replaceIndex].buffer.join("");
13196 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13199 apply : function(){
13200 return this.applyTemplate.apply(this, arguments);
13203 compile : function(){return this;}
13207 * Alias for fill().
13210 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13212 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13213 * var tpl = Roo.MasterTemplate.from('element-id');
13214 * @param {String/HTMLElement} el
13215 * @param {Object} config
13218 Roo.MasterTemplate.from = function(el, config){
13219 el = Roo.getDom(el);
13220 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13223 * Ext JS Library 1.1.1
13224 * Copyright(c) 2006-2007, Ext JS, LLC.
13226 * Originally Released Under LGPL - original licence link has changed is not relivant.
13229 * <script type="text/javascript">
13234 * @class Roo.util.CSS
13235 * Utility class for manipulating CSS rules
13238 Roo.util.CSS = function(){
13240 var doc = document;
13242 var camelRe = /(-[a-z])/gi;
13243 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13247 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13248 * tag and appended to the HEAD of the document.
13249 * @param {String|Object} cssText The text containing the css rules
13250 * @param {String} id An id to add to the stylesheet for later removal
13251 * @return {StyleSheet}
13253 createStyleSheet : function(cssText, id){
13255 var head = doc.getElementsByTagName("head")[0];
13256 var nrules = doc.createElement("style");
13257 nrules.setAttribute("type", "text/css");
13259 nrules.setAttribute("id", id);
13261 if (typeof(cssText) != 'string') {
13262 // support object maps..
13263 // not sure if this a good idea..
13264 // perhaps it should be merged with the general css handling
13265 // and handle js style props.
13266 var cssTextNew = [];
13267 for(var n in cssText) {
13269 for(var k in cssText[n]) {
13270 citems.push( k + ' : ' +cssText[n][k] + ';' );
13272 cssTextNew.push( n + ' { ' + citems.join(' ') + '} ');
13275 cssText = cssTextNew.join("\n");
13281 head.appendChild(nrules);
13282 ss = nrules.styleSheet;
13283 ss.cssText = cssText;
13286 nrules.appendChild(doc.createTextNode(cssText));
13288 nrules.cssText = cssText;
13290 head.appendChild(nrules);
13291 ss = nrules.styleSheet ? nrules.styleSheet : (nrules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13293 this.cacheStyleSheet(ss);
13298 * Removes a style or link tag by id
13299 * @param {String} id The id of the tag
13301 removeStyleSheet : function(id){
13302 var existing = doc.getElementById(id);
13304 existing.parentNode.removeChild(existing);
13309 * Dynamically swaps an existing stylesheet reference for a new one
13310 * @param {String} id The id of an existing link tag to remove
13311 * @param {String} url The href of the new stylesheet to include
13313 swapStyleSheet : function(id, url){
13314 this.removeStyleSheet(id);
13315 var ss = doc.createElement("link");
13316 ss.setAttribute("rel", "stylesheet");
13317 ss.setAttribute("type", "text/css");
13318 ss.setAttribute("id", id);
13319 ss.setAttribute("href", url);
13320 doc.getElementsByTagName("head")[0].appendChild(ss);
13324 * Refresh the rule cache if you have dynamically added stylesheets
13325 * @return {Object} An object (hash) of rules indexed by selector
13327 refreshCache : function(){
13328 return this.getRules(true);
13332 cacheStyleSheet : function(stylesheet){
13336 try{// try catch for cross domain access issue
13337 var ssRules = stylesheet.cssRules || stylesheet.rules;
13338 for(var j = ssRules.length-1; j >= 0; --j){
13339 rules[ssRules[j].selectorText] = ssRules[j];
13345 * Gets all css rules for the document
13346 * @param {Boolean} refreshCache true to refresh the internal cache
13347 * @return {Object} An object (hash) of rules indexed by selector
13349 getRules : function(refreshCache){
13350 if(rules == null || refreshCache){
13352 var ds = doc.styleSheets;
13353 for(var i =0, len = ds.length; i < len; i++){
13355 this.cacheStyleSheet(ds[i]);
13363 * Gets an an individual CSS rule by selector(s)
13364 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13365 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13366 * @return {CSSRule} The CSS rule or null if one is not found
13368 getRule : function(selector, refreshCache){
13369 var rs = this.getRules(refreshCache);
13370 if(!(selector instanceof Array)){
13371 return rs[selector];
13373 for(var i = 0; i < selector.length; i++){
13374 if(rs[selector[i]]){
13375 return rs[selector[i]];
13383 * Updates a rule property
13384 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13385 * @param {String} property The css property
13386 * @param {String} value The new value for the property
13387 * @return {Boolean} true If a rule was found and updated
13389 updateRule : function(selector, property, value){
13390 if(!(selector instanceof Array)){
13391 var rule = this.getRule(selector);
13393 rule.style[property.replace(camelRe, camelFn)] = value;
13397 for(var i = 0; i < selector.length; i++){
13398 if(this.updateRule(selector[i], property, value)){
13408 * Ext JS Library 1.1.1
13409 * Copyright(c) 2006-2007, Ext JS, LLC.
13411 * Originally Released Under LGPL - original licence link has changed is not relivant.
13414 * <script type="text/javascript">
13420 * @class Roo.util.ClickRepeater
13421 * @extends Roo.util.Observable
13423 * A wrapper class which can be applied to any element. Fires a "click" event while the
13424 * mouse is pressed. The interval between firings may be specified in the config but
13425 * defaults to 10 milliseconds.
13427 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13429 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13430 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13431 * Similar to an autorepeat key delay.
13432 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13433 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13434 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13435 * "interval" and "delay" are ignored. "immediate" is honored.
13436 * @cfg {Boolean} preventDefault True to prevent the default click event
13437 * @cfg {Boolean} stopDefault True to stop the default click event
13440 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13441 * 2007-02-02 jvs Renamed to ClickRepeater
13442 * 2007-02-03 jvs Modifications for FF Mac and Safari
13445 * @param {String/HTMLElement/Element} el The element to listen on
13446 * @param {Object} config
13448 Roo.util.ClickRepeater = function(el, config)
13450 this.el = Roo.get(el);
13451 this.el.unselectable();
13453 Roo.apply(this, config);
13458 * Fires when the mouse button is depressed.
13459 * @param {Roo.util.ClickRepeater} this
13461 "mousedown" : true,
13464 * Fires on a specified interval during the time the element is pressed.
13465 * @param {Roo.util.ClickRepeater} this
13470 * Fires when the mouse key is released.
13471 * @param {Roo.util.ClickRepeater} this
13476 this.el.on("mousedown", this.handleMouseDown, this);
13477 if(this.preventDefault || this.stopDefault){
13478 this.el.on("click", function(e){
13479 if(this.preventDefault){
13480 e.preventDefault();
13482 if(this.stopDefault){
13488 // allow inline handler
13490 this.on("click", this.handler, this.scope || this);
13493 Roo.util.ClickRepeater.superclass.constructor.call(this);
13496 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13499 preventDefault : true,
13500 stopDefault : false,
13504 handleMouseDown : function(){
13505 clearTimeout(this.timer);
13507 if(this.pressClass){
13508 this.el.addClass(this.pressClass);
13510 this.mousedownTime = new Date();
13512 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13513 this.el.on("mouseout", this.handleMouseOut, this);
13515 this.fireEvent("mousedown", this);
13516 this.fireEvent("click", this);
13518 this.timer = this.click.defer(this.delay || this.interval, this);
13522 click : function(){
13523 this.fireEvent("click", this);
13524 this.timer = this.click.defer(this.getInterval(), this);
13528 getInterval: function(){
13529 if(!this.accelerate){
13530 return this.interval;
13532 var pressTime = this.mousedownTime.getElapsed();
13533 if(pressTime < 500){
13535 }else if(pressTime < 1700){
13537 }else if(pressTime < 2600){
13539 }else if(pressTime < 3500){
13541 }else if(pressTime < 4400){
13543 }else if(pressTime < 5300){
13545 }else if(pressTime < 6200){
13553 handleMouseOut : function(){
13554 clearTimeout(this.timer);
13555 if(this.pressClass){
13556 this.el.removeClass(this.pressClass);
13558 this.el.on("mouseover", this.handleMouseReturn, this);
13562 handleMouseReturn : function(){
13563 this.el.un("mouseover", this.handleMouseReturn);
13564 if(this.pressClass){
13565 this.el.addClass(this.pressClass);
13571 handleMouseUp : function(){
13572 clearTimeout(this.timer);
13573 this.el.un("mouseover", this.handleMouseReturn);
13574 this.el.un("mouseout", this.handleMouseOut);
13575 Roo.get(document).un("mouseup", this.handleMouseUp);
13576 this.el.removeClass(this.pressClass);
13577 this.fireEvent("mouseup", this);
13581 * Ext JS Library 1.1.1
13582 * Copyright(c) 2006-2007, Ext JS, LLC.
13584 * Originally Released Under LGPL - original licence link has changed is not relivant.
13587 * <script type="text/javascript">
13592 * @class Roo.KeyNav
13593 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13594 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13595 * way to implement custom navigation schemes for any UI component.</p>
13596 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13597 * pageUp, pageDown, del, home, end. Usage:</p>
13599 var nav = new Roo.KeyNav("my-element", {
13600 "left" : function(e){
13601 this.moveLeft(e.ctrlKey);
13603 "right" : function(e){
13604 this.moveRight(e.ctrlKey);
13606 "enter" : function(e){
13613 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13614 * @param {Object} config The config
13616 Roo.KeyNav = function(el, config){
13617 this.el = Roo.get(el);
13618 Roo.apply(this, config);
13619 if(!this.disabled){
13620 this.disabled = true;
13625 Roo.KeyNav.prototype = {
13627 * @cfg {Boolean} disabled
13628 * True to disable this KeyNav instance (defaults to false)
13632 * @cfg {String} defaultEventAction
13633 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13634 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13635 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13637 defaultEventAction: "stopEvent",
13639 * @cfg {Boolean} forceKeyDown
13640 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13641 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13642 * handle keydown instead of keypress.
13644 forceKeyDown : false,
13647 prepareEvent : function(e){
13648 var k = e.getKey();
13649 var h = this.keyToHandler[k];
13650 //if(h && this[h]){
13651 // e.stopPropagation();
13653 if(Roo.isSafari && h && k >= 37 && k <= 40){
13659 relay : function(e){
13660 var k = e.getKey();
13661 var h = this.keyToHandler[k];
13663 if(this.doRelay(e, this[h], h) !== true){
13664 e[this.defaultEventAction]();
13670 doRelay : function(e, h, hname){
13671 return h.call(this.scope || this, e);
13674 // possible handlers
13688 // quick lookup hash
13705 * Enable this KeyNav
13707 enable: function(){
13709 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13710 // the EventObject will normalize Safari automatically
13711 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13712 this.el.on("keydown", this.relay, this);
13714 this.el.on("keydown", this.prepareEvent, this);
13715 this.el.on("keypress", this.relay, this);
13717 this.disabled = false;
13722 * Disable this KeyNav
13724 disable: function(){
13725 if(!this.disabled){
13726 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13727 this.el.un("keydown", this.relay);
13729 this.el.un("keydown", this.prepareEvent);
13730 this.el.un("keypress", this.relay);
13732 this.disabled = true;
13737 * Ext JS Library 1.1.1
13738 * Copyright(c) 2006-2007, Ext JS, LLC.
13740 * Originally Released Under LGPL - original licence link has changed is not relivant.
13743 * <script type="text/javascript">
13748 * @class Roo.KeyMap
13749 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13750 * The constructor accepts the same config object as defined by {@link #addBinding}.
13751 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13752 * combination it will call the function with this signature (if the match is a multi-key
13753 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13754 * A KeyMap can also handle a string representation of keys.<br />
13757 // map one key by key code
13758 var map = new Roo.KeyMap("my-element", {
13759 key: 13, // or Roo.EventObject.ENTER
13764 // map multiple keys to one action by string
13765 var map = new Roo.KeyMap("my-element", {
13771 // map multiple keys to multiple actions by strings and array of codes
13772 var map = new Roo.KeyMap("my-element", [
13775 fn: function(){ alert("Return was pressed"); }
13778 fn: function(){ alert('a, b or c was pressed'); }
13783 fn: function(){ alert('Control + shift + tab was pressed.'); }
13787 * <b>Note: A KeyMap starts enabled</b>
13789 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13790 * @param {Object} config The config (see {@link #addBinding})
13791 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13793 Roo.KeyMap = function(el, config, eventName){
13794 this.el = Roo.get(el);
13795 this.eventName = eventName || "keydown";
13796 this.bindings = [];
13798 this.addBinding(config);
13803 Roo.KeyMap.prototype = {
13805 * True to stop the event from bubbling and prevent the default browser action if the
13806 * key was handled by the KeyMap (defaults to false)
13812 * Add a new binding to this KeyMap. The following config object properties are supported:
13814 Property Type Description
13815 ---------- --------------- ----------------------------------------------------------------------
13816 key String/Array A single keycode or an array of keycodes to handle
13817 shift Boolean True to handle key only when shift is pressed (defaults to false)
13818 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13819 alt Boolean True to handle key only when alt is pressed (defaults to false)
13820 fn Function The function to call when KeyMap finds the expected key combination
13821 scope Object The scope of the callback function
13827 var map = new Roo.KeyMap(document, {
13828 key: Roo.EventObject.ENTER,
13833 //Add a new binding to the existing KeyMap later
13841 * @param {Object/Array} config A single KeyMap config or an array of configs
13843 addBinding : function(config){
13844 if(config instanceof Array){
13845 for(var i = 0, len = config.length; i < len; i++){
13846 this.addBinding(config[i]);
13850 var keyCode = config.key,
13851 shift = config.shift,
13852 ctrl = config.ctrl,
13855 scope = config.scope;
13856 if(typeof keyCode == "string"){
13858 var keyString = keyCode.toUpperCase();
13859 for(var j = 0, len = keyString.length; j < len; j++){
13860 ks.push(keyString.charCodeAt(j));
13864 var keyArray = keyCode instanceof Array;
13865 var handler = function(e){
13866 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13867 var k = e.getKey();
13869 for(var i = 0, len = keyCode.length; i < len; i++){
13870 if(keyCode[i] == k){
13871 if(this.stopEvent){
13874 fn.call(scope || window, k, e);
13880 if(this.stopEvent){
13883 fn.call(scope || window, k, e);
13888 this.bindings.push(handler);
13892 * Shorthand for adding a single key listener
13893 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13894 * following options:
13895 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13896 * @param {Function} fn The function to call
13897 * @param {Object} scope (optional) The scope of the function
13899 on : function(key, fn, scope){
13900 var keyCode, shift, ctrl, alt;
13901 if(typeof key == "object" && !(key instanceof Array)){
13920 handleKeyDown : function(e){
13921 if(this.enabled){ //just in case
13922 var b = this.bindings;
13923 for(var i = 0, len = b.length; i < len; i++){
13924 b[i].call(this, e);
13930 * Returns true if this KeyMap is enabled
13931 * @return {Boolean}
13933 isEnabled : function(){
13934 return this.enabled;
13938 * Enables this KeyMap
13940 enable: function(){
13942 this.el.on(this.eventName, this.handleKeyDown, this);
13943 this.enabled = true;
13948 * Disable this KeyMap
13950 disable: function(){
13952 this.el.removeListener(this.eventName, this.handleKeyDown, this);
13953 this.enabled = false;
13958 * Ext JS Library 1.1.1
13959 * Copyright(c) 2006-2007, Ext JS, LLC.
13961 * Originally Released Under LGPL - original licence link has changed is not relivant.
13964 * <script type="text/javascript">
13969 * @class Roo.util.TextMetrics
13970 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
13971 * wide, in pixels, a given block of text will be.
13974 Roo.util.TextMetrics = function(){
13978 * Measures the size of the specified text
13979 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
13980 * that can affect the size of the rendered text
13981 * @param {String} text The text to measure
13982 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13983 * in order to accurately measure the text height
13984 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13986 measure : function(el, text, fixedWidth){
13988 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
13991 shared.setFixedWidth(fixedWidth || 'auto');
13992 return shared.getSize(text);
13996 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
13997 * the overhead of multiple calls to initialize the style properties on each measurement.
13998 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
13999 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
14000 * in order to accurately measure the text height
14001 * @return {Roo.util.TextMetrics.Instance} instance The new instance
14003 createInstance : function(el, fixedWidth){
14004 return Roo.util.TextMetrics.Instance(el, fixedWidth);
14011 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
14012 var ml = new Roo.Element(document.createElement('div'));
14013 document.body.appendChild(ml.dom);
14014 ml.position('absolute');
14015 ml.setLeftTop(-1000, -1000);
14019 ml.setWidth(fixedWidth);
14024 * Returns the size of the specified text based on the internal element's style and width properties
14025 * @memberOf Roo.util.TextMetrics.Instance#
14026 * @param {String} text The text to measure
14027 * @return {Object} An object containing the text's size {width: (width), height: (height)}
14029 getSize : function(text){
14031 var s = ml.getSize();
14037 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
14038 * that can affect the size of the rendered text
14039 * @memberOf Roo.util.TextMetrics.Instance#
14040 * @param {String/HTMLElement} el The element, dom node or id
14042 bind : function(el){
14044 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
14049 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
14050 * to set a fixed width in order to accurately measure the text height.
14051 * @memberOf Roo.util.TextMetrics.Instance#
14052 * @param {Number} width The width to set on the element
14054 setFixedWidth : function(width){
14055 ml.setWidth(width);
14059 * Returns the measured width of the specified text
14060 * @memberOf Roo.util.TextMetrics.Instance#
14061 * @param {String} text The text to measure
14062 * @return {Number} width The width in pixels
14064 getWidth : function(text){
14065 ml.dom.style.width = 'auto';
14066 return this.getSize(text).width;
14070 * Returns the measured height of the specified text. For multiline text, be sure to call
14071 * {@link #setFixedWidth} if necessary.
14072 * @memberOf Roo.util.TextMetrics.Instance#
14073 * @param {String} text The text to measure
14074 * @return {Number} height The height in pixels
14076 getHeight : function(text){
14077 return this.getSize(text).height;
14081 instance.bind(bindTo);
14086 // backwards compat
14087 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
14089 * Ext JS Library 1.1.1
14090 * Copyright(c) 2006-2007, Ext JS, LLC.
14092 * Originally Released Under LGPL - original licence link has changed is not relivant.
14095 * <script type="text/javascript">
14099 * @class Roo.state.Provider
14100 * Abstract base class for state provider implementations. This class provides methods
14101 * for encoding and decoding <b>typed</b> variables including dates and defines the
14102 * Provider interface.
14104 Roo.state.Provider = function(){
14106 * @event statechange
14107 * Fires when a state change occurs.
14108 * @param {Provider} this This state provider
14109 * @param {String} key The state key which was changed
14110 * @param {String} value The encoded value for the state
14113 "statechange": true
14116 Roo.state.Provider.superclass.constructor.call(this);
14118 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
14120 * Returns the current value for a key
14121 * @param {String} name The key name
14122 * @param {Mixed} defaultValue A default value to return if the key's value is not found
14123 * @return {Mixed} The state data
14125 get : function(name, defaultValue){
14126 return typeof this.state[name] == "undefined" ?
14127 defaultValue : this.state[name];
14131 * Clears a value from the state
14132 * @param {String} name The key name
14134 clear : function(name){
14135 delete this.state[name];
14136 this.fireEvent("statechange", this, name, null);
14140 * Sets the value for a key
14141 * @param {String} name The key name
14142 * @param {Mixed} value The value to set
14144 set : function(name, value){
14145 this.state[name] = value;
14146 this.fireEvent("statechange", this, name, value);
14150 * Decodes a string previously encoded with {@link #encodeValue}.
14151 * @param {String} value The value to decode
14152 * @return {Mixed} The decoded value
14154 decodeValue : function(cookie){
14155 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14156 var matches = re.exec(unescape(cookie));
14157 if(!matches || !matches[1]) return; // non state cookie
14158 var type = matches[1];
14159 var v = matches[2];
14162 return parseFloat(v);
14164 return new Date(Date.parse(v));
14169 var values = v.split("^");
14170 for(var i = 0, len = values.length; i < len; i++){
14171 all.push(this.decodeValue(values[i]));
14176 var values = v.split("^");
14177 for(var i = 0, len = values.length; i < len; i++){
14178 var kv = values[i].split("=");
14179 all[kv[0]] = this.decodeValue(kv[1]);
14188 * Encodes a value including type information. Decode with {@link #decodeValue}.
14189 * @param {Mixed} value The value to encode
14190 * @return {String} The encoded value
14192 encodeValue : function(v){
14194 if(typeof v == "number"){
14196 }else if(typeof v == "boolean"){
14197 enc = "b:" + (v ? "1" : "0");
14198 }else if(v instanceof Date){
14199 enc = "d:" + v.toGMTString();
14200 }else if(v instanceof Array){
14202 for(var i = 0, len = v.length; i < len; i++){
14203 flat += this.encodeValue(v[i]);
14204 if(i != len-1) flat += "^";
14207 }else if(typeof v == "object"){
14210 if(typeof v[key] != "function"){
14211 flat += key + "=" + this.encodeValue(v[key]) + "^";
14214 enc = "o:" + flat.substring(0, flat.length-1);
14218 return escape(enc);
14224 * Ext JS Library 1.1.1
14225 * Copyright(c) 2006-2007, Ext JS, LLC.
14227 * Originally Released Under LGPL - original licence link has changed is not relivant.
14230 * <script type="text/javascript">
14233 * @class Roo.state.Manager
14234 * This is the global state manager. By default all components that are "state aware" check this class
14235 * for state information if you don't pass them a custom state provider. In order for this class
14236 * to be useful, it must be initialized with a provider when your application initializes.
14238 // in your initialization function
14240 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14242 // supposed you have a {@link Roo.BorderLayout}
14243 var layout = new Roo.BorderLayout(...);
14244 layout.restoreState();
14245 // or a {Roo.BasicDialog}
14246 var dialog = new Roo.BasicDialog(...);
14247 dialog.restoreState();
14251 Roo.state.Manager = function(){
14252 var provider = new Roo.state.Provider();
14256 * Configures the default state provider for your application
14257 * @param {Provider} stateProvider The state provider to set
14259 setProvider : function(stateProvider){
14260 provider = stateProvider;
14264 * Returns the current value for a key
14265 * @param {String} name The key name
14266 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14267 * @return {Mixed} The state data
14269 get : function(key, defaultValue){
14270 return provider.get(key, defaultValue);
14274 * Sets the value for a key
14275 * @param {String} name The key name
14276 * @param {Mixed} value The state data
14278 set : function(key, value){
14279 provider.set(key, value);
14283 * Clears a value from the state
14284 * @param {String} name The key name
14286 clear : function(key){
14287 provider.clear(key);
14291 * Gets the currently configured state provider
14292 * @return {Provider} The state provider
14294 getProvider : function(){
14301 * Ext JS Library 1.1.1
14302 * Copyright(c) 2006-2007, Ext JS, LLC.
14304 * Originally Released Under LGPL - original licence link has changed is not relivant.
14307 * <script type="text/javascript">
14310 * @class Roo.state.CookieProvider
14311 * @extends Roo.state.Provider
14312 * The default Provider implementation which saves state via cookies.
14315 var cp = new Roo.state.CookieProvider({
14317 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14318 domain: "roojs.com"
14320 Roo.state.Manager.setProvider(cp);
14322 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14323 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14324 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14325 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14326 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14327 * domain the page is running on including the 'www' like 'www.roojs.com')
14328 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14330 * Create a new CookieProvider
14331 * @param {Object} config The configuration object
14333 Roo.state.CookieProvider = function(config){
14334 Roo.state.CookieProvider.superclass.constructor.call(this);
14336 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14337 this.domain = null;
14338 this.secure = false;
14339 Roo.apply(this, config);
14340 this.state = this.readCookies();
14343 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14345 set : function(name, value){
14346 if(typeof value == "undefined" || value === null){
14350 this.setCookie(name, value);
14351 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14355 clear : function(name){
14356 this.clearCookie(name);
14357 Roo.state.CookieProvider.superclass.clear.call(this, name);
14361 readCookies : function(){
14363 var c = document.cookie + ";";
14364 var re = /\s?(.*?)=(.*?);/g;
14366 while((matches = re.exec(c)) != null){
14367 var name = matches[1];
14368 var value = matches[2];
14369 if(name && name.substring(0,3) == "ys-"){
14370 cookies[name.substr(3)] = this.decodeValue(value);
14377 setCookie : function(name, value){
14378 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14379 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14380 ((this.path == null) ? "" : ("; path=" + this.path)) +
14381 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14382 ((this.secure == true) ? "; secure" : "");
14386 clearCookie : function(name){
14387 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14388 ((this.path == null) ? "" : ("; path=" + this.path)) +
14389 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14390 ((this.secure == true) ? "; secure" : "");