4 * Copyright(c) 2006-2007, Ext JS, LLC.
6 * Originally Released Under LGPL - original licence link has changed is not relivant.
9 * <script type="text/javascript">
17 window["undefined"] = window["undefined"];
21 * Roo core utilities and functions.
26 * Copies all the properties of config to obj.
27 * @param {Object} obj The receiver of the properties
28 * @param {Object} config The source of the properties
29 * @param {Object} defaults A different object that will also be applied for default values
30 * @return {Object} returns obj
35 Roo.apply = function(o, c, defaults){
37 // no "this" reference for friendly out of scope calls
38 Roo.apply(o, defaults);
40 if(o && c && typeof c == 'object'){
51 var ua = navigator.userAgent.toLowerCase();
53 var isStrict = document.compatMode == "CSS1Compat",
54 isOpera = ua.indexOf("opera") > -1,
55 isSafari = (/webkit|khtml/).test(ua),
56 isIE = ua.indexOf("msie") > -1,
57 isIE7 = ua.indexOf("msie 7") > -1,
58 isGecko = !isSafari && ua.indexOf("gecko") > -1,
59 isBorderBox = isIE && !isStrict,
60 isWindows = (ua.indexOf("windows") != -1 || ua.indexOf("win32") != -1),
61 isMac = (ua.indexOf("macintosh") != -1 || ua.indexOf("mac os x") != -1),
62 isLinux = (ua.indexOf("linux") != -1),
63 isSecure = window.location.href.toLowerCase().indexOf("https") === 0;
65 // remove css image flicker
68 document.execCommand("BackgroundImageCache", false, true);
74 * True if the browser is in strict mode
79 * True if the page is running over SSL
84 * True when the document is fully initialized and ready for action
90 * True to automatically uncache orphaned Roo.Elements periodically (defaults to true)
93 enableGarbageCollector : true,
96 * True to automatically purge event listeners after uncaching an element (defaults to false).
97 * Note: this only happens if enableGarbageCollector is true.
100 enableListenerCollection:false,
103 * URL to a blank file used by Roo when in secure mode for iframe src and onReady src to prevent
104 * the IE insecure content warning (defaults to javascript:false).
107 SSL_SECURE_URL : "javascript:false",
110 * URL to a 1x1 transparent gif image used by Roo to create inline icons with CSS background images. (Defaults to
111 * "http://Roojs.com/s.gif" and you should change this to a URL on your server).
114 BLANK_IMAGE_URL : "http:/"+"/localhost/s.gif",
116 emptyFn : function(){},
119 * Copies all the properties of config to obj if they don't already exist.
120 * @param {Object} obj The receiver of the properties
121 * @param {Object} config The source of the properties
122 * @return {Object} returns obj
124 applyIf : function(o, c){
127 if(typeof o[p] == "undefined"){ o[p] = c[p]; }
134 * Applies event listeners to elements by selectors when the document is ready.
135 * The event name is specified with an @ suffix.
138 // add a listener for click on all anchors in element with id foo
139 '#foo a@click' : function(e, t){
143 // add the same listener to multiple selectors (separated by comma BEFORE the @)
144 '#foo a, #bar span.some-class@mouseover' : function(){
149 * @param {Object} obj The list of behaviors to apply
151 addBehaviors : function(o){
153 Roo.onReady(function(){
158 var cache = {}; // simple cache for applying multiple behaviors to same selector does query multiple times
160 var parts = b.split('@');
161 if(parts[1]){ // for Object prototype breakers
164 cache[s] = Roo.select(s);
166 cache[s].on(parts[1], o[b]);
173 * Generates unique ids. If the element already has an id, it is unchanged
174 * @param {String/HTMLElement/Element} el (optional) The element to generate an id for
175 * @param {String} prefix (optional) Id prefix (defaults "Roo-gen")
176 * @return {String} The generated Id.
178 id : function(el, prefix){
179 prefix = prefix || "roo-gen";
181 var id = prefix + (++idSeed);
182 return el ? (el.id ? el.id : (el.id = id)) : id;
187 * Extends one class with another class and optionally overrides members with the passed literal. This class
188 * also adds the function "override()" to the class that can be used to override
189 * members on an instance.
190 * @param {Object} subclass The class inheriting the functionality
191 * @param {Object} superclass The class being extended
192 * @param {Object} overrides (optional) A literal with members
197 var io = function(o){
202 return function(sb, sp, overrides){
203 if(typeof sp == 'object'){ // eg. prototype, rather than function constructor..
206 sb = function(){sp.apply(this, arguments);};
208 var F = function(){}, sbp, spp = sp.prototype;
210 sbp = sb.prototype = new F();
214 if(spp.constructor == Object.prototype.constructor){
219 sb.override = function(o){
223 Roo.override(sb, overrides);
229 * Adds a list of functions to the prototype of an existing class, overwriting any existing methods with the same name.
231 Roo.override(MyClass, {
232 newMethod1: function(){
235 newMethod2: function(foo){
240 * @param {Object} origclass The class to override
241 * @param {Object} overrides The list of functions to add to origClass. This should be specified as an object literal
242 * containing one or more methods.
245 override : function(origclass, overrides){
247 var p = origclass.prototype;
248 for(var method in overrides){
249 p[method] = overrides[method];
254 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
256 Roo.namespace('Company', 'Company.data');
257 Company.Widget = function() { ... }
258 Company.data.CustomStore = function(config) { ... }
260 * @param {String} namespace1
261 * @param {String} namespace2
262 * @param {String} etc
265 namespace : function(){
266 var a=arguments, o=null, i, j, d, rt;
267 for (i=0; i<a.length; ++i) {
271 eval('if (typeof ' + rt + ' == "undefined"){' + rt + ' = {};} o = ' + rt + ';');
272 for (j=1; j<d.length; ++j) {
273 o[d[j]]=o[d[j]] || {};
279 * Creates namespaces to be used for scoping variables and classes so that they are not global. Usage:
281 Roo.factory({ xns: Roo.data, xtype : 'Store', .....});
282 Roo.factory(conf, Roo.data);
284 * @param {String} classname
285 * @param {String} namespace (optional)
289 factory : function(c, ns)
291 // no xtype, no ns or c.xns - or forced off by c.xns
292 if (!c.xtype || (!ns && !c.xns) || (c.xns === false)) { // not enough info...
295 ns = c.xns ? c.xns : ns; // if c.xns is set, then use that..
296 if (c.constructor == ns[c.xtype]) {// already created...
300 console.log("Roo.Factory(" + c.xtype + ")");
301 var ret = new ns[c.xtype](c);
305 c.xns = false; // prevent recursion..
310 * Takes an object and converts it to an encoded URL. e.g. Roo.urlEncode({foo: 1, bar: 2}); would return "foo=1&bar=2". Optionally, property values can be arrays, instead of keys and the resulting string that's returned will contain a name/value pair for each array value.
314 urlEncode : function(o){
320 var ov = o[key], k = encodeURIComponent(key);
321 var type = typeof ov;
322 if(type == 'undefined'){
324 }else if(type != "function" && type != "object"){
325 buf.push(k, "=", encodeURIComponent(ov), "&");
326 }else if(ov instanceof Array){
328 for(var i = 0, len = ov.length; i < len; i++) {
329 buf.push(k, "=", encodeURIComponent(ov[i] === undefined ? '' : ov[i]), "&");
341 * Takes an encoded URL and and converts it to an object. e.g. Roo.urlDecode("foo=1&bar=2"); would return {foo: 1, bar: 2} or Roo.urlDecode("foo=1&bar=2&bar=3&bar=4", true); would return {foo: 1, bar: [2, 3, 4]}.
342 * @param {String} string
343 * @param {Boolean} overwrite (optional) Items of the same name will overwrite previous values instead of creating an an array (Defaults to false).
344 * @return {Object} A literal with members
346 urlDecode : function(string, overwrite){
347 if(!string || !string.length){
351 var pairs = string.split('&');
352 var pair, name, value;
353 for(var i = 0, len = pairs.length; i < len; i++){
354 pair = pairs[i].split('=');
355 name = decodeURIComponent(pair[0]);
356 value = decodeURIComponent(pair[1]);
357 if(overwrite !== true){
358 if(typeof obj[name] == "undefined"){
360 }else if(typeof obj[name] == "string"){
361 obj[name] = [obj[name]];
362 obj[name].push(value);
364 obj[name].push(value);
374 * Iterates an array calling the passed function with each item, stopping if your function returns false. If the
375 * passed array is not really an array, your function is called once with it.
376 * The supplied function is called with (Object item, Number index, Array allItems).
377 * @param {Array/NodeList/Mixed} array
378 * @param {Function} fn
379 * @param {Object} scope
381 each : function(array, fn, scope){
382 if(typeof array.length == "undefined" || typeof array == "string"){
385 for(var i = 0, len = array.length; i < len; i++){
386 if(fn.call(scope || array[i], array[i], i, array) === false){ return i; };
391 combine : function(){
392 var as = arguments, l = as.length, r = [];
393 for(var i = 0; i < l; i++){
395 if(a instanceof Array){
397 }else if(a.length !== undefined && !a.substr){
398 r = r.concat(Array.prototype.slice.call(a, 0));
407 * Escapes the passed string for use in a regular expression
408 * @param {String} str
411 escapeRe : function(s) {
412 return s.replace(/([.*+?^${}()|[\]\/\\])/g, "\\$1");
416 callback : function(cb, scope, args, delay){
417 if(typeof cb == "function"){
419 cb.defer(delay, scope, args || []);
421 cb.apply(scope, args || []);
427 * Return the dom node for the passed string (id), dom node, or Roo.Element
428 * @param {String/HTMLElement/Roo.Element} el
429 * @return HTMLElement
431 getDom : function(el){
435 return el.dom ? el.dom : (typeof el == 'string' ? document.getElementById(el) : el);
439 * Shorthand for {@link Roo.ComponentMgr#get}
441 * @return Roo.Component
443 getCmp : function(id){
444 return Roo.ComponentMgr.get(id);
447 num : function(v, defaultValue){
448 if(typeof v != 'number'){
454 destroy : function(){
455 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
459 as.removeAllListeners();
463 if(typeof as.purgeListeners == 'function'){
466 if(typeof as.destroy == 'function'){
473 // inpired by a similar function in mootools library
475 * Returns the type of object that is passed in. If the object passed in is null or undefined it
476 * return false otherwise it returns one of the following values:<ul>
477 * <li><b>string</b>: If the object passed is a string</li>
478 * <li><b>number</b>: If the object passed is a number</li>
479 * <li><b>boolean</b>: If the object passed is a boolean value</li>
480 * <li><b>function</b>: If the object passed is a function reference</li>
481 * <li><b>object</b>: If the object passed is an object</li>
482 * <li><b>array</b>: If the object passed is an array</li>
483 * <li><b>regexp</b>: If the object passed is a regular expression</li>
484 * <li><b>element</b>: If the object passed is a DOM Element</li>
485 * <li><b>nodelist</b>: If the object passed is a DOM NodeList</li>
486 * <li><b>textnode</b>: If the object passed is a DOM text node and contains something other than whitespace</li>
487 * <li><b>whitespace</b>: If the object passed is a DOM text node and contains only whitespace</li>
488 * @param {Mixed} object
492 if(o === undefined || o === null){
499 if(t == 'object' && o.nodeName) {
501 case 1: return 'element';
502 case 3: return (/\S/).test(o.nodeValue) ? 'textnode' : 'whitespace';
505 if(t == 'object' || t == 'function') {
506 switch(o.constructor) {
507 case Array: return 'array';
508 case RegExp: return 'regexp';
510 if(typeof o.length == 'number' && typeof o.item == 'function') {
518 * Returns true if the passed value is null, undefined or an empty string (optional).
519 * @param {Mixed} value The value to test
520 * @param {Boolean} allowBlank (optional) Pass true if an empty string is not considered empty
523 isEmpty : function(v, allowBlank){
524 return v === null || v === undefined || (!allowBlank ? v === '' : false);
538 isBorderBox : isBorderBox,
540 isWindows : isWindows,
547 * By default, Ext intelligently decides whether floating elements should be shimmed. If you are using flash,
548 * you may want to set this to true.
551 useShims : ((isIE && !isIE7) || (isGecko && isMac))
557 Roo.namespace("Roo", "Roo.util", "Roo.grid", "Roo.dd", "Roo.tree", "Roo.data",
558 "Roo.form", "Roo.menu", "Roo.state", "Roo.lib", "Roo.layout", "Roo.app", "Roo.ux");
561 * Ext JS Library 1.1.1
562 * Copyright(c) 2006-2007, Ext JS, LLC.
564 * Originally Released Under LGPL - original licence link has changed is not relivant.
567 * <script type="text/javascript">
571 // wrappedn so fnCleanup is not in global scope...
573 function fnCleanUp() {
574 var p = Function.prototype;
575 delete p.createSequence;
577 delete p.createDelegate;
578 delete p.createCallback;
579 delete p.createInterceptor;
581 window.detachEvent("onunload", fnCleanUp);
583 window.attachEvent("onunload", fnCleanUp);
590 * These functions are available on every Function object (any JavaScript function).
592 Roo.apply(Function.prototype, {
594 * Creates a callback that passes arguments[0], arguments[1], arguments[2], ...
595 * Call directly on any function. Example: <code>myFunction.createCallback(myarg, myarg2)</code>
596 * Will create a function that is bound to those 2 args.
597 * @return {Function} The new function
599 createCallback : function(/*args...*/){
600 // make args available, in function below
601 var args = arguments;
604 return method.apply(window, args);
609 * Creates a delegate (callback) that sets the scope to obj.
610 * Call directly on any function. Example: <code>this.myFunction.createDelegate(this)</code>
611 * Will create a function that is automatically scoped to this.
612 * @param {Object} obj (optional) The object for which the scope is set
613 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
614 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
615 * if a number the args are inserted at the specified position
616 * @return {Function} The new function
618 createDelegate : function(obj, args, appendArgs){
621 var callArgs = args || arguments;
622 if(appendArgs === true){
623 callArgs = Array.prototype.slice.call(arguments, 0);
624 callArgs = callArgs.concat(args);
625 }else if(typeof appendArgs == "number"){
626 callArgs = Array.prototype.slice.call(arguments, 0); // copy arguments first
627 var applyArgs = [appendArgs, 0].concat(args); // create method call params
628 Array.prototype.splice.apply(callArgs, applyArgs); // splice them in
630 return method.apply(obj || window, callArgs);
635 * Calls this function after the number of millseconds specified.
636 * @param {Number} millis The number of milliseconds for the setTimeout call (if 0 the function is executed immediately)
637 * @param {Object} obj (optional) The object for which the scope is set
638 * @param {Array} args (optional) Overrides arguments for the call. (Defaults to the arguments passed by the caller)
639 * @param {Boolean/Number} appendArgs (optional) if True args are appended to call args instead of overriding,
640 * if a number the args are inserted at the specified position
641 * @return {Number} The timeout id that can be used with clearTimeout
643 defer : function(millis, obj, args, appendArgs){
644 var fn = this.createDelegate(obj, args, appendArgs);
646 return setTimeout(fn, millis);
652 * Create a combined function call sequence of the original function + the passed function.
653 * The resulting function returns the results of the original function.
654 * The passed fcn is called with the parameters of the original function
655 * @param {Function} fcn The function to sequence
656 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
657 * @return {Function} The new function
659 createSequence : function(fcn, scope){
660 if(typeof fcn != "function"){
665 var retval = method.apply(this || window, arguments);
666 fcn.apply(scope || this || window, arguments);
672 * Creates an interceptor function. The passed fcn is called before the original one. If it returns false, the original one is not called.
673 * The resulting function returns the results of the original function.
674 * The passed fcn is called with the parameters of the original function.
676 * @param {Function} fcn The function to call before the original
677 * @param {Object} scope (optional) The scope of the passed fcn (Defaults to scope of original function or window)
678 * @return {Function} The new function
680 createInterceptor : function(fcn, scope){
681 if(typeof fcn != "function"){
688 if(fcn.apply(scope || this || window, arguments) === false){
691 return method.apply(this || window, arguments);
697 * Ext JS Library 1.1.1
698 * Copyright(c) 2006-2007, Ext JS, LLC.
700 * Originally Released Under LGPL - original licence link has changed is not relivant.
703 * <script type="text/javascript">
706 Roo.applyIf(String, {
711 * Escapes the passed string for ' and \
712 * @param {String} string The string to escape
713 * @return {String} The escaped string
716 escape : function(string) {
717 return string.replace(/('|\\)/g, "\\$1");
721 * Pads the left side of a string with a specified character. This is especially useful
722 * for normalizing number and date strings. Example usage:
724 var s = String.leftPad('123', 5, '0');
725 // s now contains the string: '00123'
727 * @param {String} string The original string
728 * @param {Number} size The total length of the output string
729 * @param {String} char (optional) The character with which to pad the original string (defaults to empty string " ")
730 * @return {String} The padded string
733 leftPad : function (val, size, ch) {
734 var result = new String(val);
735 if(ch === null || ch === undefined || ch === '') {
738 while (result.length < size) {
739 result = ch + result;
745 * Allows you to define a tokenized string and pass an arbitrary number of arguments to replace the tokens. Each
746 * token must be unique, and must increment in the format {0}, {1}, etc. Example usage:
748 var cls = 'my-class', text = 'Some text';
749 var s = String.format('<div class="{0}">{1}</div>', cls, text);
750 // s now contains the string: '<div class="my-class">Some text</div>'
752 * @param {String} string The tokenized string to be formatted
753 * @param {String} value1 The value to replace token {0}
754 * @param {String} value2 Etc...
755 * @return {String} The formatted string
758 format : function(format){
759 var args = Array.prototype.slice.call(arguments, 1);
760 return format.replace(/\{(\d+)\}/g, function(m, i){
761 return Roo.util.Format.htmlEncode(args[i]);
767 * Utility function that allows you to easily switch a string between two alternating values. The passed value
768 * is compared to the current string, and if they are equal, the other value that was passed in is returned. If
769 * they are already different, the first value passed in is returned. Note that this method returns the new value
770 * but does not change the current string.
772 // alternate sort directions
773 sort = sort.toggle('ASC', 'DESC');
775 // instead of conditional logic:
776 sort = (sort == 'ASC' ? 'DESC' : 'ASC');
778 * @param {String} value The value to compare to the current string
779 * @param {String} other The new value to use if the string already equals the first value passed in
780 * @return {String} The new value
783 String.prototype.toggle = function(value, other){
784 return this == value ? other : value;
787 * Ext JS Library 1.1.1
788 * Copyright(c) 2006-2007, Ext JS, LLC.
790 * Originally Released Under LGPL - original licence link has changed is not relivant.
793 * <script type="text/javascript">
799 Roo.applyIf(Number.prototype, {
801 * Checks whether or not the current number is within a desired range. If the number is already within the
802 * range it is returned, otherwise the min or max value is returned depending on which side of the range is
803 * exceeded. Note that this method returns the constrained value but does not change the current number.
804 * @param {Number} min The minimum number in the range
805 * @param {Number} max The maximum number in the range
806 * @return {Number} The constrained value if outside the range, otherwise the current value
808 constrain : function(min, max){
809 return Math.min(Math.max(this, min), max);
813 * Ext JS Library 1.1.1
814 * Copyright(c) 2006-2007, Ext JS, LLC.
816 * Originally Released Under LGPL - original licence link has changed is not relivant.
819 * <script type="text/javascript">
824 Roo.applyIf(Array.prototype, {
826 * Checks whether or not the specified object exists in the array.
827 * @param {Object} o The object to check for
828 * @return {Number} The index of o in the array (or -1 if it is not found)
830 indexOf : function(o){
831 for (var i = 0, len = this.length; i < len; i++){
832 if(this[i] == o) return i;
838 * Removes the specified object from the array. If the object is not found nothing happens.
839 * @param {Object} o The object to remove
841 remove : function(o){
842 var index = this.indexOf(o);
844 this.splice(index, 1);
849 * Ext JS Library 1.1.1
850 * Copyright(c) 2006-2007, Ext JS, LLC.
852 * Originally Released Under LGPL - original licence link has changed is not relivant.
855 * <script type="text/javascript">
861 * The date parsing and format syntax is a subset of
862 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
863 * supported will provide results equivalent to their PHP versions.
865 * Following is the list of all currently supported formats:
868 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
870 Format Output Description
871 ------ ---------- --------------------------------------------------------------
872 d 10 Day of the month, 2 digits with leading zeros
873 D Wed A textual representation of a day, three letters
874 j 10 Day of the month without leading zeros
875 l Wednesday A full textual representation of the day of the week
876 S th English ordinal day of month suffix, 2 chars (use with j)
877 w 3 Numeric representation of the day of the week
878 z 9 The julian date, or day of the year (0-365)
879 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
880 F January A full textual representation of the month
881 m 01 Numeric representation of a month, with leading zeros
882 M Jan Month name abbreviation, three letters
883 n 1 Numeric representation of a month, without leading zeros
884 t 31 Number of days in the given month
885 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
886 Y 2007 A full numeric representation of a year, 4 digits
887 y 07 A two digit representation of a year
888 a pm Lowercase Ante meridiem and Post meridiem
889 A PM Uppercase Ante meridiem and Post meridiem
890 g 3 12-hour format of an hour without leading zeros
891 G 15 24-hour format of an hour without leading zeros
892 h 03 12-hour format of an hour with leading zeros
893 H 15 24-hour format of an hour with leading zeros
894 i 05 Minutes with leading zeros
895 s 01 Seconds, with leading zeros
896 O -0600 Difference to Greenwich time (GMT) in hours
897 T CST Timezone setting of the machine running the code
898 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
901 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
903 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
904 document.write(dt.format('Y-m-d')); //2007-01-10
905 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
906 document.write(dt.format('l, \\t\\he dS of F Y h:i:s A')); //Wednesday, the 10th of January 2007 03:05:01 PM
909 * Here are some standard date/time patterns that you might find helpful. They
910 * are not part of the source of Date.js, but to use them you can simply copy this
911 * block of code into any script that is included after Date.js and they will also become
912 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
915 ISO8601Long:"Y-m-d H:i:s",
916 ISO8601Short:"Y-m-d",
918 LongDate: "l, F d, Y",
919 FullDateTime: "l, F d, Y g:i:s A",
923 SortableDateTime: "Y-m-d\\TH:i:s",
924 UniversalSortableDateTime: "Y-m-d H:i:sO",
932 document.write(dt.format(Date.patterns.ShortDate));
937 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
938 * They generate precompiled functions from date formats instead of parsing and
939 * processing the pattern every time you format a date. These functions are available
940 * on every Date object (any javascript function).
942 * The original article and download are here:
943 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
950 Returns the number of milliseconds between this date and date
951 @param {Date} date (optional) Defaults to now
952 @return {Number} The diff in milliseconds
953 @member Date getElapsed
955 Date.prototype.getElapsed = function(date) {
956 return Math.abs((date || new Date()).getTime()-this.getTime());
958 // was in date file..
962 Date.parseFunctions = {count:0};
964 Date.parseRegexes = [];
966 Date.formatFunctions = {count:0};
969 Date.prototype.dateFormat = function(format) {
970 if (Date.formatFunctions[format] == null) {
971 Date.createNewFormat(format);
973 var func = Date.formatFunctions[format];
979 * Formats a date given the supplied format string
980 * @param {String} format The format string
981 * @return {String} The formatted date
984 Date.prototype.format = Date.prototype.dateFormat;
987 Date.createNewFormat = function(format) {
988 var funcName = "format" + Date.formatFunctions.count++;
989 Date.formatFunctions[format] = funcName;
990 var code = "Date.prototype." + funcName + " = function(){return ";
993 for (var i = 0; i < format.length; ++i) {
994 ch = format.charAt(i);
995 if (!special && ch == "\\") {
1000 code += "'" + String.escape(ch) + "' + ";
1003 code += Date.getFormatCode(ch);
1006 /** eval:var:zzzzzzzzzzzzz */
1007 eval(code.substring(0, code.length - 3) + ";}");
1011 Date.getFormatCode = function(character) {
1012 switch (character) {
1014 return "String.leftPad(this.getDate(), 2, '0') + ";
1016 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1018 return "this.getDate() + ";
1020 return "Date.dayNames[this.getDay()] + ";
1022 return "this.getSuffix() + ";
1024 return "this.getDay() + ";
1026 return "this.getDayOfYear() + ";
1028 return "this.getWeekOfYear() + ";
1030 return "Date.monthNames[this.getMonth()] + ";
1032 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1034 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1036 return "(this.getMonth() + 1) + ";
1038 return "this.getDaysInMonth() + ";
1040 return "(this.isLeapYear() ? 1 : 0) + ";
1042 return "this.getFullYear() + ";
1044 return "('' + this.getFullYear()).substring(2, 4) + ";
1046 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1048 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1050 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1052 return "this.getHours() + ";
1054 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1056 return "String.leftPad(this.getHours(), 2, '0') + ";
1058 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1060 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1062 return "this.getGMTOffset() + ";
1064 return "this.getTimezone() + ";
1066 return "(this.getTimezoneOffset() * -60) + ";
1068 return "'" + String.escape(character) + "' + ";
1073 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1074 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1075 * the date format that is not specified will default to the current date value for that part. Time parts can also
1076 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1077 * string or the parse operation will fail.
1080 //dt = Fri May 25 2007 (current date)
1081 var dt = new Date();
1083 //dt = Thu May 25 2006 (today's month/day in 2006)
1084 dt = Date.parseDate("2006", "Y");
1086 //dt = Sun Jan 15 2006 (all date parts specified)
1087 dt = Date.parseDate("2006-1-15", "Y-m-d");
1089 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1090 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1092 * @param {String} input The unparsed date as a string
1093 * @param {String} format The format the date is in
1094 * @return {Date} The parsed date
1097 Date.parseDate = function(input, format) {
1098 if (Date.parseFunctions[format] == null) {
1099 Date.createParser(format);
1101 var func = Date.parseFunctions[format];
1102 return Date[func](input);
1106 Date.createParser = function(format) {
1107 var funcName = "parse" + Date.parseFunctions.count++;
1108 var regexNum = Date.parseRegexes.length;
1109 var currentGroup = 1;
1110 Date.parseFunctions[format] = funcName;
1112 var code = "Date." + funcName + " = function(input){\n"
1113 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1114 + "var d = new Date();\n"
1115 + "y = d.getFullYear();\n"
1116 + "m = d.getMonth();\n"
1117 + "d = d.getDate();\n"
1118 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1119 + "if (results && results.length > 0) {";
1122 var special = false;
1124 for (var i = 0; i < format.length; ++i) {
1125 ch = format.charAt(i);
1126 if (!special && ch == "\\") {
1131 regex += String.escape(ch);
1134 var obj = Date.formatCodeToRegex(ch, currentGroup);
1135 currentGroup += obj.g;
1137 if (obj.g && obj.c) {
1143 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1144 + "{v = new Date(y, m, d, h, i, s);}\n"
1145 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1146 + "{v = new Date(y, m, d, h, i);}\n"
1147 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1148 + "{v = new Date(y, m, d, h);}\n"
1149 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1150 + "{v = new Date(y, m, d);}\n"
1151 + "else if (y >= 0 && m >= 0)\n"
1152 + "{v = new Date(y, m);}\n"
1153 + "else if (y >= 0)\n"
1154 + "{v = new Date(y);}\n"
1155 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1156 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1157 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1160 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1161 /** eval:var:zzzzzzzzzzzzz */
1166 Date.formatCodeToRegex = function(character, currentGroup) {
1167 switch (character) {
1171 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1174 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1175 s:"(\\d{1,2})"}; // day of month without leading zeroes
1178 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1179 s:"(\\d{2})"}; // day of month with leading zeroes
1183 s:"(?:" + Date.dayNames.join("|") + ")"};
1187 s:"(?:st|nd|rd|th)"};
1202 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1203 s:"(" + Date.monthNames.join("|") + ")"};
1206 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1207 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1210 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1211 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1214 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1215 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1226 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1230 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1231 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1235 c:"if (results[" + currentGroup + "] == 'am') {\n"
1236 + "if (h == 12) { h = 0; }\n"
1237 + "} else { if (h < 12) { h += 12; }}",
1241 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1242 + "if (h == 12) { h = 0; }\n"
1243 + "} else { if (h < 12) { h += 12; }}",
1248 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1249 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1253 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1254 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1257 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1261 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1266 "o = results[", currentGroup, "];\n",
1267 "var sn = o.substring(0,1);\n", // get + / - sign
1268 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1269 "var mn = o.substring(3,5) % 60;\n", // get minutes
1270 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1271 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1277 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1280 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1281 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1282 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1286 s:String.escape(character)};
1291 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1292 * @return {String} The abbreviated timezone name (e.g. 'CST')
1294 Date.prototype.getTimezone = function() {
1295 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1299 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1300 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1302 Date.prototype.getGMTOffset = function() {
1303 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1304 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1305 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1309 * Get the numeric day number of the year, adjusted for leap year.
1310 * @return {Number} 0 through 364 (365 in leap years)
1312 Date.prototype.getDayOfYear = function() {
1314 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1315 for (var i = 0; i < this.getMonth(); ++i) {
1316 num += Date.daysInMonth[i];
1318 return num + this.getDate() - 1;
1322 * Get the string representation of the numeric week number of the year
1323 * (equivalent to the format specifier 'W').
1324 * @return {String} '00' through '52'
1326 Date.prototype.getWeekOfYear = function() {
1327 // Skip to Thursday of this week
1328 var now = this.getDayOfYear() + (4 - this.getDay());
1329 // Find the first Thursday of the year
1330 var jan1 = new Date(this.getFullYear(), 0, 1);
1331 var then = (7 - jan1.getDay() + 4);
1332 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1336 * Whether or not the current date is in a leap year.
1337 * @return {Boolean} True if the current date is in a leap year, else false
1339 Date.prototype.isLeapYear = function() {
1340 var year = this.getFullYear();
1341 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1345 * Get the first day of the current month, adjusted for leap year. The returned value
1346 * is the numeric day index within the week (0-6) which can be used in conjunction with
1347 * the {@link #monthNames} array to retrieve the textual day name.
1350 var dt = new Date('1/10/2007');
1351 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1353 * @return {Number} The day number (0-6)
1355 Date.prototype.getFirstDayOfMonth = function() {
1356 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1357 return (day < 0) ? (day + 7) : day;
1361 * Get the last day of the current month, adjusted for leap year. The returned value
1362 * is the numeric day index within the week (0-6) which can be used in conjunction with
1363 * the {@link #monthNames} array to retrieve the textual day name.
1366 var dt = new Date('1/10/2007');
1367 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1369 * @return {Number} The day number (0-6)
1371 Date.prototype.getLastDayOfMonth = function() {
1372 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1373 return (day < 0) ? (day + 7) : day;
1378 * Get the first date of this date's month
1381 Date.prototype.getFirstDateOfMonth = function() {
1382 return new Date(this.getFullYear(), this.getMonth(), 1);
1386 * Get the last date of this date's month
1389 Date.prototype.getLastDateOfMonth = function() {
1390 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1393 * Get the number of days in the current month, adjusted for leap year.
1394 * @return {Number} The number of days in the month
1396 Date.prototype.getDaysInMonth = function() {
1397 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1398 return Date.daysInMonth[this.getMonth()];
1402 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1403 * @return {String} 'st, 'nd', 'rd' or 'th'
1405 Date.prototype.getSuffix = function() {
1406 switch (this.getDate()) {
1423 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1426 * An array of textual month names.
1427 * Override these values for international dates, for example...
1428 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1447 * An array of textual day names.
1448 * Override these values for international dates, for example...
1449 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1465 Date.monthNumbers = {
1480 * Creates and returns a new Date instance with the exact same date value as the called instance.
1481 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1482 * variable will also be changed. When the intention is to create a new variable that will not
1483 * modify the original instance, you should create a clone.
1485 * Example of correctly cloning a date:
1488 var orig = new Date('10/1/2006');
1491 document.write(orig); //returns 'Thu Oct 05 2006'!
1494 var orig = new Date('10/1/2006');
1495 var copy = orig.clone();
1497 document.write(orig); //returns 'Thu Oct 01 2006'
1499 * @return {Date} The new Date instance
1501 Date.prototype.clone = function() {
1502 return new Date(this.getTime());
1506 * Clears any time information from this date
1507 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1508 @return {Date} this or the clone
1510 Date.prototype.clearTime = function(clone){
1512 return this.clone().clearTime();
1517 this.setMilliseconds(0);
1522 // safari setMonth is broken
1524 Date.brokenSetMonth = Date.prototype.setMonth;
1525 Date.prototype.setMonth = function(num){
1527 var n = Math.ceil(-num);
1528 var back_year = Math.ceil(n/12);
1529 var month = (n % 12) ? 12 - n % 12 : 0 ;
1530 this.setFullYear(this.getFullYear() - back_year);
1531 return Date.brokenSetMonth.call(this, month);
1533 return Date.brokenSetMonth.apply(this, arguments);
1538 /** Date interval constant
1542 /** Date interval constant
1546 /** Date interval constant
1550 /** Date interval constant
1554 /** Date interval constant
1558 /** Date interval constant
1562 /** Date interval constant
1568 * Provides a convenient method of performing basic date arithmetic. This method
1569 * does not modify the Date instance being called - it creates and returns
1570 * a new Date instance containing the resulting date value.
1575 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1576 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1578 //Negative values will subtract correctly:
1579 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1580 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1582 //You can even chain several calls together in one line!
1583 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1584 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1587 * @param {String} interval A valid date interval enum value
1588 * @param {Number} value The amount to add to the current date
1589 * @return {Date} The new Date instance
1591 Date.prototype.add = function(interval, value){
1592 var d = this.clone();
1593 if (!interval || value === 0) return d;
1594 switch(interval.toLowerCase()){
1596 d.setMilliseconds(this.getMilliseconds() + value);
1599 d.setSeconds(this.getSeconds() + value);
1602 d.setMinutes(this.getMinutes() + value);
1605 d.setHours(this.getHours() + value);
1608 d.setDate(this.getDate() + value);
1611 var day = this.getDate();
1613 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1616 d.setMonth(this.getMonth() + value);
1619 d.setFullYear(this.getFullYear() + value);
1625 * Ext JS Library 1.1.1
1626 * Copyright(c) 2006-2007, Ext JS, LLC.
1628 * Originally Released Under LGPL - original licence link has changed is not relivant.
1631 * <script type="text/javascript">
1635 getViewWidth : function(full) {
1636 return full ? this.getDocumentWidth() : this.getViewportWidth();
1639 getViewHeight : function(full) {
1640 return full ? this.getDocumentHeight() : this.getViewportHeight();
1643 getDocumentHeight: function() {
1644 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1645 return Math.max(scrollHeight, this.getViewportHeight());
1648 getDocumentWidth: function() {
1649 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1650 return Math.max(scrollWidth, this.getViewportWidth());
1653 getViewportHeight: function() {
1654 var height = self.innerHeight;
1655 var mode = document.compatMode;
1657 if ((mode || Roo.isIE) && !Roo.isOpera) {
1658 height = (mode == "CSS1Compat") ?
1659 document.documentElement.clientHeight :
1660 document.body.clientHeight;
1666 getViewportWidth: function() {
1667 var width = self.innerWidth;
1668 var mode = document.compatMode;
1670 if (mode || Roo.isIE) {
1671 width = (mode == "CSS1Compat") ?
1672 document.documentElement.clientWidth :
1673 document.body.clientWidth;
1678 isAncestor : function(p, c) {
1685 if (p.contains && !Roo.isSafari) {
1686 return p.contains(c);
1687 } else if (p.compareDocumentPosition) {
1688 return !!(p.compareDocumentPosition(c) & 16);
1690 var parent = c.parentNode;
1695 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1698 parent = parent.parentNode;
1704 getRegion : function(el) {
1705 return Roo.lib.Region.getRegion(el);
1708 getY : function(el) {
1709 return this.getXY(el)[1];
1712 getX : function(el) {
1713 return this.getXY(el)[0];
1716 getXY : function(el) {
1717 var p, pe, b, scroll, bd = document.body;
1718 el = Roo.getDom(el);
1719 var fly = Roo.lib.AnimBase.fly;
1720 if (el.getBoundingClientRect) {
1721 b = el.getBoundingClientRect();
1722 scroll = fly(document).getScroll();
1723 return [b.left + scroll.left, b.top + scroll.top];
1729 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1736 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1743 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1744 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1751 if (p != el && pe.getStyle('overflow') != 'visible') {
1759 if (Roo.isSafari && hasAbsolute) {
1764 if (Roo.isGecko && !hasAbsolute) {
1766 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1767 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1771 while (p && p != bd) {
1772 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1784 setXY : function(el, xy) {
1785 el = Roo.fly(el, '_setXY');
1787 var pts = el.translatePoints(xy);
1788 if (xy[0] !== false) {
1789 el.dom.style.left = pts.left + "px";
1791 if (xy[1] !== false) {
1792 el.dom.style.top = pts.top + "px";
1796 setX : function(el, x) {
1797 this.setXY(el, [x, false]);
1800 setY : function(el, y) {
1801 this.setXY(el, [false, y]);
1805 * Portions of this file are based on pieces of Yahoo User Interface Library
1806 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1807 * YUI licensed under the BSD License:
1808 * http://developer.yahoo.net/yui/license.txt
1809 * <script type="text/javascript">
1813 Roo.lib.Event = function() {
1814 var loadComplete = false;
1816 var unloadListeners = [];
1818 var onAvailStack = [];
1820 var lastError = null;
1833 startInterval: function() {
1834 if (!this._interval) {
1836 var callback = function() {
1837 self._tryPreloadAttach();
1839 this._interval = setInterval(callback, this.POLL_INTERVAL);
1844 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1845 onAvailStack.push({ id: p_id,
1848 override: p_override,
1849 checkReady: false });
1851 retryCount = this.POLL_RETRYS;
1852 this.startInterval();
1856 addListener: function(el, eventName, fn) {
1857 el = Roo.getDom(el);
1862 if ("unload" == eventName) {
1863 unloadListeners[unloadListeners.length] =
1864 [el, eventName, fn];
1868 var wrappedFn = function(e) {
1869 return fn(Roo.lib.Event.getEvent(e));
1872 var li = [el, eventName, fn, wrappedFn];
1874 var index = listeners.length;
1875 listeners[index] = li;
1877 this.doAdd(el, eventName, wrappedFn, false);
1883 removeListener: function(el, eventName, fn) {
1886 el = Roo.getDom(el);
1889 return this.purgeElement(el, false, eventName);
1893 if ("unload" == eventName) {
1895 for (i = 0,len = unloadListeners.length; i < len; i++) {
1896 var li = unloadListeners[i];
1899 li[1] == eventName &&
1901 unloadListeners.splice(i, 1);
1909 var cacheItem = null;
1912 var index = arguments[3];
1914 if ("undefined" == typeof index) {
1915 index = this._getCacheIndex(el, eventName, fn);
1919 cacheItem = listeners[index];
1922 if (!el || !cacheItem) {
1926 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1928 delete listeners[index][this.WFN];
1929 delete listeners[index][this.FN];
1930 listeners.splice(index, 1);
1937 getTarget: function(ev, resolveTextNode) {
1938 ev = ev.browserEvent || ev;
1939 var t = ev.target || ev.srcElement;
1940 return this.resolveTextNode(t);
1944 resolveTextNode: function(node) {
1945 if (Roo.isSafari && node && 3 == node.nodeType) {
1946 return node.parentNode;
1953 getPageX: function(ev) {
1954 ev = ev.browserEvent || ev;
1956 if (!x && 0 !== x) {
1957 x = ev.clientX || 0;
1960 x += this.getScroll()[1];
1968 getPageY: function(ev) {
1969 ev = ev.browserEvent || ev;
1971 if (!y && 0 !== y) {
1972 y = ev.clientY || 0;
1975 y += this.getScroll()[0];
1984 getXY: function(ev) {
1985 ev = ev.browserEvent || ev;
1986 return [this.getPageX(ev), this.getPageY(ev)];
1990 getRelatedTarget: function(ev) {
1991 ev = ev.browserEvent || ev;
1992 var t = ev.relatedTarget;
1994 if (ev.type == "mouseout") {
1996 } else if (ev.type == "mouseover") {
2001 return this.resolveTextNode(t);
2005 getTime: function(ev) {
2006 ev = ev.browserEvent || ev;
2008 var t = new Date().getTime();
2012 this.lastError = ex;
2021 stopEvent: function(ev) {
2022 this.stopPropagation(ev);
2023 this.preventDefault(ev);
2027 stopPropagation: function(ev) {
2028 ev = ev.browserEvent || ev;
2029 if (ev.stopPropagation) {
2030 ev.stopPropagation();
2032 ev.cancelBubble = true;
2037 preventDefault: function(ev) {
2038 ev = ev.browserEvent || ev;
2039 if(ev.preventDefault) {
2040 ev.preventDefault();
2042 ev.returnValue = false;
2047 getEvent: function(e) {
2048 var ev = e || window.event;
2050 var c = this.getEvent.caller;
2052 ev = c.arguments[0];
2053 if (ev && Event == ev.constructor) {
2063 getCharCode: function(ev) {
2064 ev = ev.browserEvent || ev;
2065 return ev.charCode || ev.keyCode || 0;
2069 _getCacheIndex: function(el, eventName, fn) {
2070 for (var i = 0,len = listeners.length; i < len; ++i) {
2071 var li = listeners[i];
2073 li[this.FN] == fn &&
2074 li[this.EL] == el &&
2075 li[this.TYPE] == eventName) {
2087 getEl: function(id) {
2088 return document.getElementById(id);
2092 clearCache: function() {
2096 _load: function(e) {
2097 loadComplete = true;
2098 var EU = Roo.lib.Event;
2102 EU.doRemove(window, "load", EU._load);
2107 _tryPreloadAttach: function() {
2116 var tryAgain = !loadComplete;
2118 tryAgain = (retryCount > 0);
2123 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2124 var item = onAvailStack[i];
2126 var el = this.getEl(item.id);
2129 if (!item.checkReady ||
2132 (document && document.body)) {
2135 if (item.override) {
2136 if (item.override === true) {
2139 scope = item.override;
2142 item.fn.call(scope, item.obj);
2143 onAvailStack[i] = null;
2146 notAvail.push(item);
2151 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2155 this.startInterval();
2157 clearInterval(this._interval);
2158 this._interval = null;
2161 this.locked = false;
2168 purgeElement: function(el, recurse, eventName) {
2169 var elListeners = this.getListeners(el, eventName);
2171 for (var i = 0,len = elListeners.length; i < len; ++i) {
2172 var l = elListeners[i];
2173 this.removeListener(el, l.type, l.fn);
2177 if (recurse && el && el.childNodes) {
2178 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2179 this.purgeElement(el.childNodes[i], recurse, eventName);
2185 getListeners: function(el, eventName) {
2186 var results = [], searchLists;
2188 searchLists = [listeners, unloadListeners];
2189 } else if (eventName == "unload") {
2190 searchLists = [unloadListeners];
2192 searchLists = [listeners];
2195 for (var j = 0; j < searchLists.length; ++j) {
2196 var searchList = searchLists[j];
2197 if (searchList && searchList.length > 0) {
2198 for (var i = 0,len = searchList.length; i < len; ++i) {
2199 var l = searchList[i];
2200 if (l && l[this.EL] === el &&
2201 (!eventName || eventName === l[this.TYPE])) {
2206 adjust: l[this.ADJ_SCOPE],
2214 return (results.length) ? results : null;
2218 _unload: function(e) {
2220 var EU = Roo.lib.Event, i, j, l, len, index;
2222 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2223 l = unloadListeners[i];
2226 if (l[EU.ADJ_SCOPE]) {
2227 if (l[EU.ADJ_SCOPE] === true) {
2230 scope = l[EU.ADJ_SCOPE];
2233 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2234 unloadListeners[i] = null;
2240 unloadListeners = null;
2242 if (listeners && listeners.length > 0) {
2243 j = listeners.length;
2246 l = listeners[index];
2248 EU.removeListener(l[EU.EL], l[EU.TYPE],
2258 EU.doRemove(window, "unload", EU._unload);
2263 getScroll: function() {
2264 var dd = document.documentElement, db = document.body;
2265 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2266 return [dd.scrollTop, dd.scrollLeft];
2268 return [db.scrollTop, db.scrollLeft];
2275 doAdd: function () {
2276 if (window.addEventListener) {
2277 return function(el, eventName, fn, capture) {
2278 el.addEventListener(eventName, fn, (capture));
2280 } else if (window.attachEvent) {
2281 return function(el, eventName, fn, capture) {
2282 el.attachEvent("on" + eventName, fn);
2291 doRemove: function() {
2292 if (window.removeEventListener) {
2293 return function (el, eventName, fn, capture) {
2294 el.removeEventListener(eventName, fn, (capture));
2296 } else if (window.detachEvent) {
2297 return function (el, eventName, fn) {
2298 el.detachEvent("on" + eventName, fn);
2310 var E = Roo.lib.Event;
2311 E.on = E.addListener;
2312 E.un = E.removeListener;
2314 if (document && document.body) {
2317 E.doAdd(window, "load", E._load);
2319 E.doAdd(window, "unload", E._unload);
2320 E._tryPreloadAttach();
2324 * Portions of this file are based on pieces of Yahoo User Interface Library
2325 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2326 * YUI licensed under the BSD License:
2327 * http://developer.yahoo.net/yui/license.txt
2328 * <script type="text/javascript">
2335 request : function(method, uri, cb, data, options) {
2337 var hs = options.headers;
2340 if(hs.hasOwnProperty(h)){
2341 this.initHeader(h, hs[h], false);
2345 if(options.xmlData){
2346 this.initHeader('Content-Type', 'text/xml', false);
2348 data = options.xmlData;
2352 return this.asyncRequest(method, uri, cb, data);
2355 serializeForm : function(form) {
2356 if(typeof form == 'string') {
2357 form = (document.getElementById(form) || document.forms[form]);
2360 var el, name, val, disabled, data = '', hasSubmit = false;
2361 for (var i = 0; i < form.elements.length; i++) {
2362 el = form.elements[i];
2363 disabled = form.elements[i].disabled;
2364 name = form.elements[i].name;
2365 val = form.elements[i].value;
2367 if (!disabled && name){
2371 case 'select-multiple':
2372 for (var j = 0; j < el.options.length; j++) {
2373 if (el.options[j].selected) {
2375 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2378 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2386 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2399 if(hasSubmit == false) {
2400 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2405 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2410 data = data.substr(0, data.length - 1);
2418 useDefaultHeader:true,
2420 defaultPostHeader:'application/x-www-form-urlencoded',
2422 useDefaultXhrHeader:true,
2424 defaultXhrHeader:'XMLHttpRequest',
2426 hasDefaultHeaders:true,
2438 setProgId:function(id)
2440 this.activeX.unshift(id);
2443 setDefaultPostHeader:function(b)
2445 this.useDefaultHeader = b;
2448 setDefaultXhrHeader:function(b)
2450 this.useDefaultXhrHeader = b;
2453 setPollingInterval:function(i)
2455 if (typeof i == 'number' && isFinite(i)) {
2456 this.pollInterval = i;
2460 createXhrObject:function(transactionId)
2466 http = new XMLHttpRequest();
2468 obj = { conn:http, tId:transactionId };
2472 for (var i = 0; i < this.activeX.length; ++i) {
2476 http = new ActiveXObject(this.activeX[i]);
2478 obj = { conn:http, tId:transactionId };
2491 getConnectionObject:function()
2494 var tId = this.transactionId;
2498 o = this.createXhrObject(tId);
2500 this.transactionId++;
2511 asyncRequest:function(method, uri, callback, postData)
2513 var o = this.getConnectionObject();
2519 o.conn.open(method, uri, true);
2521 if (this.useDefaultXhrHeader) {
2522 if (!this.defaultHeaders['X-Requested-With']) {
2523 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2527 if(postData && this.useDefaultHeader){
2528 this.initHeader('Content-Type', this.defaultPostHeader);
2531 if (this.hasDefaultHeaders || this.hasHeaders) {
2535 this.handleReadyState(o, callback);
2536 o.conn.send(postData || null);
2542 handleReadyState:function(o, callback)
2546 if (callback && callback.timeout) {
2547 this.timeout[o.tId] = window.setTimeout(function() {
2548 oConn.abort(o, callback, true);
2549 }, callback.timeout);
2552 this.poll[o.tId] = window.setInterval(
2554 if (o.conn && o.conn.readyState == 4) {
2555 window.clearInterval(oConn.poll[o.tId]);
2556 delete oConn.poll[o.tId];
2558 if(callback && callback.timeout) {
2559 window.clearTimeout(oConn.timeout[o.tId]);
2560 delete oConn.timeout[o.tId];
2563 oConn.handleTransactionResponse(o, callback);
2566 , this.pollInterval);
2569 handleTransactionResponse:function(o, callback, isAbort)
2573 this.releaseObject(o);
2577 var httpStatus, responseObject;
2581 if (o.conn.status !== undefined && o.conn.status != 0) {
2582 httpStatus = o.conn.status;
2594 if (httpStatus >= 200 && httpStatus < 300) {
2595 responseObject = this.createResponseObject(o, callback.argument);
2596 if (callback.success) {
2597 if (!callback.scope) {
2598 callback.success(responseObject);
2603 callback.success.apply(callback.scope, [responseObject]);
2608 switch (httpStatus) {
2616 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2617 if (callback.failure) {
2618 if (!callback.scope) {
2619 callback.failure(responseObject);
2622 callback.failure.apply(callback.scope, [responseObject]);
2627 responseObject = this.createResponseObject(o, callback.argument);
2628 if (callback.failure) {
2629 if (!callback.scope) {
2630 callback.failure(responseObject);
2633 callback.failure.apply(callback.scope, [responseObject]);
2639 this.releaseObject(o);
2640 responseObject = null;
2643 createResponseObject:function(o, callbackArg)
2650 var headerStr = o.conn.getAllResponseHeaders();
2651 var header = headerStr.split('\n');
2652 for (var i = 0; i < header.length; i++) {
2653 var delimitPos = header[i].indexOf(':');
2654 if (delimitPos != -1) {
2655 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2663 obj.status = o.conn.status;
2664 obj.statusText = o.conn.statusText;
2665 obj.getResponseHeader = headerObj;
2666 obj.getAllResponseHeaders = headerStr;
2667 obj.responseText = o.conn.responseText;
2668 obj.responseXML = o.conn.responseXML;
2670 if (typeof callbackArg !== undefined) {
2671 obj.argument = callbackArg;
2677 createExceptionObject:function(tId, callbackArg, isAbort)
2680 var COMM_ERROR = 'communication failure';
2681 var ABORT_CODE = -1;
2682 var ABORT_ERROR = 'transaction aborted';
2688 obj.status = ABORT_CODE;
2689 obj.statusText = ABORT_ERROR;
2692 obj.status = COMM_CODE;
2693 obj.statusText = COMM_ERROR;
2697 obj.argument = callbackArg;
2703 initHeader:function(label, value, isDefault)
2705 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2707 if (headerObj[label] === undefined) {
2708 headerObj[label] = value;
2713 headerObj[label] = value + "," + headerObj[label];
2717 this.hasDefaultHeaders = true;
2720 this.hasHeaders = true;
2725 setHeader:function(o)
2727 if (this.hasDefaultHeaders) {
2728 for (var prop in this.defaultHeaders) {
2729 if (this.defaultHeaders.hasOwnProperty(prop)) {
2730 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2735 if (this.hasHeaders) {
2736 for (var prop in this.headers) {
2737 if (this.headers.hasOwnProperty(prop)) {
2738 o.conn.setRequestHeader(prop, this.headers[prop]);
2742 this.hasHeaders = false;
2746 resetDefaultHeaders:function() {
2747 delete this.defaultHeaders;
2748 this.defaultHeaders = {};
2749 this.hasDefaultHeaders = false;
2752 abort:function(o, callback, isTimeout)
2754 if(this.isCallInProgress(o)) {
2756 window.clearInterval(this.poll[o.tId]);
2757 delete this.poll[o.tId];
2759 delete this.timeout[o.tId];
2762 this.handleTransactionResponse(o, callback, true);
2772 isCallInProgress:function(o)
2775 return o.conn.readyState != 4 && o.conn.readyState != 0;
2784 releaseObject:function(o)
2793 'MSXML2.XMLHTTP.3.0',
2801 * Portions of this file are based on pieces of Yahoo User Interface Library
2802 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2803 * YUI licensed under the BSD License:
2804 * http://developer.yahoo.net/yui/license.txt
2805 * <script type="text/javascript">
2809 Roo.lib.Region = function(t, r, b, l) {
2819 Roo.lib.Region.prototype = {
2820 contains : function(region) {
2821 return ( region.left >= this.left &&
2822 region.right <= this.right &&
2823 region.top >= this.top &&
2824 region.bottom <= this.bottom );
2828 getArea : function() {
2829 return ( (this.bottom - this.top) * (this.right - this.left) );
2832 intersect : function(region) {
2833 var t = Math.max(this.top, region.top);
2834 var r = Math.min(this.right, region.right);
2835 var b = Math.min(this.bottom, region.bottom);
2836 var l = Math.max(this.left, region.left);
2838 if (b >= t && r >= l) {
2839 return new Roo.lib.Region(t, r, b, l);
2844 union : function(region) {
2845 var t = Math.min(this.top, region.top);
2846 var r = Math.max(this.right, region.right);
2847 var b = Math.max(this.bottom, region.bottom);
2848 var l = Math.min(this.left, region.left);
2850 return new Roo.lib.Region(t, r, b, l);
2853 adjust : function(t, l, b, r) {
2862 Roo.lib.Region.getRegion = function(el) {
2863 var p = Roo.lib.Dom.getXY(el);
2866 var r = p[0] + el.offsetWidth;
2867 var b = p[1] + el.offsetHeight;
2870 return new Roo.lib.Region(t, r, b, l);
2873 * Portions of this file are based on pieces of Yahoo User Interface Library
2874 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2875 * YUI licensed under the BSD License:
2876 * http://developer.yahoo.net/yui/license.txt
2877 * <script type="text/javascript">
2880 //@@dep Roo.lib.Region
2883 Roo.lib.Point = function(x, y) {
2884 if (x instanceof Array) {
2888 this.x = this.right = this.left = this[0] = x;
2889 this.y = this.top = this.bottom = this[1] = y;
2892 Roo.lib.Point.prototype = new Roo.lib.Region();
2894 * Portions of this file are based on pieces of Yahoo User Interface Library
2895 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2896 * YUI licensed under the BSD License:
2897 * http://developer.yahoo.net/yui/license.txt
2898 * <script type="text/javascript">
2905 scroll : function(el, args, duration, easing, cb, scope) {
2906 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2909 motion : function(el, args, duration, easing, cb, scope) {
2910 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2913 color : function(el, args, duration, easing, cb, scope) {
2914 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2917 run : function(el, args, duration, easing, cb, scope, type) {
2918 type = type || Roo.lib.AnimBase;
2919 if (typeof easing == "string") {
2920 easing = Roo.lib.Easing[easing];
2922 var anim = new type(el, args, duration, easing);
2923 anim.animateX(function() {
2924 Roo.callback(cb, scope);
2930 * Portions of this file are based on pieces of Yahoo User Interface Library
2931 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2932 * YUI licensed under the BSD License:
2933 * http://developer.yahoo.net/yui/license.txt
2934 * <script type="text/javascript">
2942 if (!libFlyweight) {
2943 libFlyweight = new Roo.Element.Flyweight();
2945 libFlyweight.dom = el;
2946 return libFlyweight;
2949 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2953 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2955 this.init(el, attributes, duration, method);
2959 Roo.lib.AnimBase.fly = fly;
2963 Roo.lib.AnimBase.prototype = {
2965 toString: function() {
2966 var el = this.getEl();
2967 var id = el.id || el.tagName;
2968 return ("Anim " + id);
2972 noNegatives: /width|height|opacity|padding/i,
2973 offsetAttribute: /^((width|height)|(top|left))$/,
2974 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
2975 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
2979 doMethod: function(attr, start, end) {
2980 return this.method(this.currentFrame, start, end - start, this.totalFrames);
2984 setAttribute: function(attr, val, unit) {
2985 if (this.patterns.noNegatives.test(attr)) {
2986 val = (val > 0) ? val : 0;
2989 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
2993 getAttribute: function(attr) {
2994 var el = this.getEl();
2995 var val = fly(el).getStyle(attr);
2997 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
2998 return parseFloat(val);
3001 var a = this.patterns.offsetAttribute.exec(attr) || [];
3002 var pos = !!( a[3] );
3003 var box = !!( a[2] );
3006 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3007 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3016 getDefaultUnit: function(attr) {
3017 if (this.patterns.defaultUnit.test(attr)) {
3024 animateX : function(callback, scope) {
3025 var f = function() {
3026 this.onComplete.removeListener(f);
3027 if (typeof callback == "function") {
3028 callback.call(scope || this, this);
3031 this.onComplete.addListener(f, this);
3036 setRuntimeAttribute: function(attr) {
3039 var attributes = this.attributes;
3041 this.runtimeAttributes[attr] = {};
3043 var isset = function(prop) {
3044 return (typeof prop !== 'undefined');
3047 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3051 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3054 if (isset(attributes[attr]['to'])) {
3055 end = attributes[attr]['to'];
3056 } else if (isset(attributes[attr]['by'])) {
3057 if (start.constructor == Array) {
3059 for (var i = 0, len = start.length; i < len; ++i) {
3060 end[i] = start[i] + attributes[attr]['by'][i];
3063 end = start + attributes[attr]['by'];
3067 this.runtimeAttributes[attr].start = start;
3068 this.runtimeAttributes[attr].end = end;
3071 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3075 init: function(el, attributes, duration, method) {
3077 var isAnimated = false;
3080 var startTime = null;
3083 var actualFrames = 0;
3086 el = Roo.getDom(el);
3089 this.attributes = attributes || {};
3092 this.duration = duration || 1;
3095 this.method = method || Roo.lib.Easing.easeNone;
3098 this.useSeconds = true;
3101 this.currentFrame = 0;
3104 this.totalFrames = Roo.lib.AnimMgr.fps;
3107 this.getEl = function() {
3112 this.isAnimated = function() {
3117 this.getStartTime = function() {
3121 this.runtimeAttributes = {};
3124 this.animate = function() {
3125 if (this.isAnimated()) {
3129 this.currentFrame = 0;
3131 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3133 Roo.lib.AnimMgr.registerElement(this);
3137 this.stop = function(finish) {
3139 this.currentFrame = this.totalFrames;
3140 this._onTween.fire();
3142 Roo.lib.AnimMgr.stop(this);
3145 var onStart = function() {
3146 this.onStart.fire();
3148 this.runtimeAttributes = {};
3149 for (var attr in this.attributes) {
3150 this.setRuntimeAttribute(attr);
3155 startTime = new Date();
3159 var onTween = function() {
3161 duration: new Date() - this.getStartTime(),
3162 currentFrame: this.currentFrame
3165 data.toString = function() {
3167 'duration: ' + data.duration +
3168 ', currentFrame: ' + data.currentFrame
3172 this.onTween.fire(data);
3174 var runtimeAttributes = this.runtimeAttributes;
3176 for (var attr in runtimeAttributes) {
3177 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3183 var onComplete = function() {
3184 var actual_duration = (new Date() - startTime) / 1000 ;
3187 duration: actual_duration,
3188 frames: actualFrames,
3189 fps: actualFrames / actual_duration
3192 data.toString = function() {
3194 'duration: ' + data.duration +
3195 ', frames: ' + data.frames +
3196 ', fps: ' + data.fps
3202 this.onComplete.fire(data);
3206 this._onStart = new Roo.util.Event(this);
3207 this.onStart = new Roo.util.Event(this);
3208 this.onTween = new Roo.util.Event(this);
3209 this._onTween = new Roo.util.Event(this);
3210 this.onComplete = new Roo.util.Event(this);
3211 this._onComplete = new Roo.util.Event(this);
3212 this._onStart.addListener(onStart);
3213 this._onTween.addListener(onTween);
3214 this._onComplete.addListener(onComplete);
3219 * Portions of this file are based on pieces of Yahoo User Interface Library
3220 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3221 * YUI licensed under the BSD License:
3222 * http://developer.yahoo.net/yui/license.txt
3223 * <script type="text/javascript">
3227 Roo.lib.AnimMgr = new function() {
3244 this.registerElement = function(tween) {
3245 queue[queue.length] = tween;
3247 tween._onStart.fire();
3252 this.unRegister = function(tween, index) {
3253 tween._onComplete.fire();
3254 index = index || getIndex(tween);
3256 queue.splice(index, 1);
3260 if (tweenCount <= 0) {
3266 this.start = function() {
3267 if (thread === null) {
3268 thread = setInterval(this.run, this.delay);
3273 this.stop = function(tween) {
3275 clearInterval(thread);
3277 for (var i = 0, len = queue.length; i < len; ++i) {
3278 if (queue[0].isAnimated()) {
3279 this.unRegister(queue[0], 0);
3288 this.unRegister(tween);
3293 this.run = function() {
3294 for (var i = 0, len = queue.length; i < len; ++i) {
3295 var tween = queue[i];
3296 if (!tween || !tween.isAnimated()) {
3300 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3302 tween.currentFrame += 1;
3304 if (tween.useSeconds) {
3305 correctFrame(tween);
3307 tween._onTween.fire();
3310 Roo.lib.AnimMgr.stop(tween, i);
3315 var getIndex = function(anim) {
3316 for (var i = 0, len = queue.length; i < len; ++i) {
3317 if (queue[i] == anim) {
3325 var correctFrame = function(tween) {
3326 var frames = tween.totalFrames;
3327 var frame = tween.currentFrame;
3328 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3329 var elapsed = (new Date() - tween.getStartTime());
3332 if (elapsed < tween.duration * 1000) {
3333 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3335 tweak = frames - (frame + 1);
3337 if (tweak > 0 && isFinite(tweak)) {
3338 if (tween.currentFrame + tweak >= frames) {
3339 tweak = frames - (frame + 1);
3342 tween.currentFrame += tweak;
3346 * Portions of this file are based on pieces of Yahoo User Interface Library
3347 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3348 * YUI licensed under the BSD License:
3349 * http://developer.yahoo.net/yui/license.txt
3350 * <script type="text/javascript">
3353 Roo.lib.Bezier = new function() {
3355 this.getPosition = function(points, t) {
3356 var n = points.length;
3359 for (var i = 0; i < n; ++i) {
3360 tmp[i] = [points[i][0], points[i][1]];
3363 for (var j = 1; j < n; ++j) {
3364 for (i = 0; i < n - j; ++i) {
3365 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3366 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3370 return [ tmp[0][0], tmp[0][1] ];
3374 * Portions of this file are based on pieces of Yahoo User Interface Library
3375 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3376 * YUI licensed under the BSD License:
3377 * http://developer.yahoo.net/yui/license.txt
3378 * <script type="text/javascript">
3383 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3384 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3387 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3389 var fly = Roo.lib.AnimBase.fly;
3391 var superclass = Y.ColorAnim.superclass;
3392 var proto = Y.ColorAnim.prototype;
3394 proto.toString = function() {
3395 var el = this.getEl();
3396 var id = el.id || el.tagName;
3397 return ("ColorAnim " + id);
3400 proto.patterns.color = /color$/i;
3401 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3402 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3403 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3404 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3407 proto.parseColor = function(s) {
3408 if (s.length == 3) {
3412 var c = this.patterns.hex.exec(s);
3413 if (c && c.length == 4) {
3414 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3417 c = this.patterns.rgb.exec(s);
3418 if (c && c.length == 4) {
3419 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3422 c = this.patterns.hex3.exec(s);
3423 if (c && c.length == 4) {
3424 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3429 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3430 proto.getAttribute = function(attr) {
3431 var el = this.getEl();
3432 if (this.patterns.color.test(attr)) {
3433 var val = fly(el).getStyle(attr);
3435 if (this.patterns.transparent.test(val)) {
3436 var parent = el.parentNode;
3437 val = fly(parent).getStyle(attr);
3439 while (parent && this.patterns.transparent.test(val)) {
3440 parent = parent.parentNode;
3441 val = fly(parent).getStyle(attr);
3442 if (parent.tagName.toUpperCase() == 'HTML') {
3448 val = superclass.getAttribute.call(this, attr);
3453 proto.getAttribute = function(attr) {
3454 var el = this.getEl();
3455 if (this.patterns.color.test(attr)) {
3456 var val = fly(el).getStyle(attr);
3458 if (this.patterns.transparent.test(val)) {
3459 var parent = el.parentNode;
3460 val = fly(parent).getStyle(attr);
3462 while (parent && this.patterns.transparent.test(val)) {
3463 parent = parent.parentNode;
3464 val = fly(parent).getStyle(attr);
3465 if (parent.tagName.toUpperCase() == 'HTML') {
3471 val = superclass.getAttribute.call(this, attr);
3477 proto.doMethod = function(attr, start, end) {
3480 if (this.patterns.color.test(attr)) {
3482 for (var i = 0, len = start.length; i < len; ++i) {
3483 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3486 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3489 val = superclass.doMethod.call(this, attr, start, end);
3495 proto.setRuntimeAttribute = function(attr) {
3496 superclass.setRuntimeAttribute.call(this, attr);
3498 if (this.patterns.color.test(attr)) {
3499 var attributes = this.attributes;
3500 var start = this.parseColor(this.runtimeAttributes[attr].start);
3501 var end = this.parseColor(this.runtimeAttributes[attr].end);
3503 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3504 end = this.parseColor(attributes[attr].by);
3506 for (var i = 0, len = start.length; i < len; ++i) {
3507 end[i] = start[i] + end[i];
3511 this.runtimeAttributes[attr].start = start;
3512 this.runtimeAttributes[attr].end = end;
3518 * Portions of this file are based on pieces of Yahoo User Interface Library
3519 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3520 * YUI licensed under the BSD License:
3521 * http://developer.yahoo.net/yui/license.txt
3522 * <script type="text/javascript">
3528 easeNone: function (t, b, c, d) {
3529 return c * t / d + b;
3533 easeIn: function (t, b, c, d) {
3534 return c * (t /= d) * t + b;
3538 easeOut: function (t, b, c, d) {
3539 return -c * (t /= d) * (t - 2) + b;
3543 easeBoth: function (t, b, c, d) {
3544 if ((t /= d / 2) < 1) {
3545 return c / 2 * t * t + b;
3548 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3552 easeInStrong: function (t, b, c, d) {
3553 return c * (t /= d) * t * t * t + b;
3557 easeOutStrong: function (t, b, c, d) {
3558 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3562 easeBothStrong: function (t, b, c, d) {
3563 if ((t /= d / 2) < 1) {
3564 return c / 2 * t * t * t * t + b;
3567 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3572 elasticIn: function (t, b, c, d, a, p) {
3576 if ((t /= d) == 1) {
3583 if (!a || a < Math.abs(c)) {
3588 var s = p / (2 * Math.PI) * Math.asin(c / a);
3591 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3595 elasticOut: function (t, b, c, d, a, p) {
3599 if ((t /= d) == 1) {
3606 if (!a || a < Math.abs(c)) {
3611 var s = p / (2 * Math.PI) * Math.asin(c / a);
3614 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3618 elasticBoth: function (t, b, c, d, a, p) {
3623 if ((t /= d / 2) == 2) {
3631 if (!a || a < Math.abs(c)) {
3636 var s = p / (2 * Math.PI) * Math.asin(c / a);
3640 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3641 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3643 return a * Math.pow(2, -10 * (t -= 1)) *
3644 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3649 backIn: function (t, b, c, d, s) {
3650 if (typeof s == 'undefined') {
3653 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3657 backOut: function (t, b, c, d, s) {
3658 if (typeof s == 'undefined') {
3661 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3665 backBoth: function (t, b, c, d, s) {
3666 if (typeof s == 'undefined') {
3670 if ((t /= d / 2 ) < 1) {
3671 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3673 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3677 bounceIn: function (t, b, c, d) {
3678 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3682 bounceOut: function (t, b, c, d) {
3683 if ((t /= d) < (1 / 2.75)) {
3684 return c * (7.5625 * t * t) + b;
3685 } else if (t < (2 / 2.75)) {
3686 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3687 } else if (t < (2.5 / 2.75)) {
3688 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3690 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3694 bounceBoth: function (t, b, c, d) {
3696 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3698 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3701 * Portions of this file are based on pieces of Yahoo User Interface Library
3702 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3703 * YUI licensed under the BSD License:
3704 * http://developer.yahoo.net/yui/license.txt
3705 * <script type="text/javascript">
3709 Roo.lib.Motion = function(el, attributes, duration, method) {
3711 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3715 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3719 var superclass = Y.Motion.superclass;
3720 var proto = Y.Motion.prototype;
3722 proto.toString = function() {
3723 var el = this.getEl();
3724 var id = el.id || el.tagName;
3725 return ("Motion " + id);
3728 proto.patterns.points = /^points$/i;
3730 proto.setAttribute = function(attr, val, unit) {
3731 if (this.patterns.points.test(attr)) {
3732 unit = unit || 'px';
3733 superclass.setAttribute.call(this, 'left', val[0], unit);
3734 superclass.setAttribute.call(this, 'top', val[1], unit);
3736 superclass.setAttribute.call(this, attr, val, unit);
3740 proto.getAttribute = function(attr) {
3741 if (this.patterns.points.test(attr)) {
3743 superclass.getAttribute.call(this, 'left'),
3744 superclass.getAttribute.call(this, 'top')
3747 val = superclass.getAttribute.call(this, attr);
3753 proto.doMethod = function(attr, start, end) {
3756 if (this.patterns.points.test(attr)) {
3757 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3758 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3760 val = superclass.doMethod.call(this, attr, start, end);
3765 proto.setRuntimeAttribute = function(attr) {
3766 if (this.patterns.points.test(attr)) {
3767 var el = this.getEl();
3768 var attributes = this.attributes;
3770 var control = attributes['points']['control'] || [];
3774 if (control.length > 0 && !(control[0] instanceof Array)) {
3775 control = [control];
3778 for (i = 0,len = control.length; i < len; ++i) {
3779 tmp[i] = control[i];
3784 Roo.fly(el).position();
3786 if (isset(attributes['points']['from'])) {
3787 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3790 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3793 start = this.getAttribute('points');
3796 if (isset(attributes['points']['to'])) {
3797 end = translateValues.call(this, attributes['points']['to'], start);
3799 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3800 for (i = 0,len = control.length; i < len; ++i) {
3801 control[i] = translateValues.call(this, control[i], start);
3805 } else if (isset(attributes['points']['by'])) {
3806 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3808 for (i = 0,len = control.length; i < len; ++i) {
3809 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3813 this.runtimeAttributes[attr] = [start];
3815 if (control.length > 0) {
3816 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3819 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3822 superclass.setRuntimeAttribute.call(this, attr);
3826 var translateValues = function(val, start) {
3827 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3828 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3833 var isset = function(prop) {
3834 return (typeof prop !== 'undefined');
3838 * Portions of this file are based on pieces of Yahoo User Interface Library
3839 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3840 * YUI licensed under the BSD License:
3841 * http://developer.yahoo.net/yui/license.txt
3842 * <script type="text/javascript">
3846 Roo.lib.Scroll = function(el, attributes, duration, method) {
3848 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3852 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3856 var superclass = Y.Scroll.superclass;
3857 var proto = Y.Scroll.prototype;
3859 proto.toString = function() {
3860 var el = this.getEl();
3861 var id = el.id || el.tagName;
3862 return ("Scroll " + id);
3865 proto.doMethod = function(attr, start, end) {
3868 if (attr == 'scroll') {
3870 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3871 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3875 val = superclass.doMethod.call(this, attr, start, end);
3880 proto.getAttribute = function(attr) {
3882 var el = this.getEl();
3884 if (attr == 'scroll') {
3885 val = [ el.scrollLeft, el.scrollTop ];
3887 val = superclass.getAttribute.call(this, attr);
3893 proto.setAttribute = function(attr, val, unit) {
3894 var el = this.getEl();
3896 if (attr == 'scroll') {
3897 el.scrollLeft = val[0];
3898 el.scrollTop = val[1];
3900 superclass.setAttribute.call(this, attr, val, unit);
3906 * Ext JS Library 1.1.1
3907 * Copyright(c) 2006-2007, Ext JS, LLC.
3909 * Originally Released Under LGPL - original licence link has changed is not relivant.
3912 * <script type="text/javascript">
3917 * @class Roo.DomHelper
3918 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3919 * 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>.
3922 Roo.DomHelper = function(){
3923 var tempTableEl = null;
3924 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3925 var tableRe = /^table|tbody|tr|td$/i;
3927 // build as innerHTML where available
3929 var createHtml = function(o){
3930 if(typeof o == 'string'){
3939 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3940 if(attr == "style"){
3942 if(typeof s == "function"){
3945 if(typeof s == "string"){
3946 b += ' style="' + s + '"';
3947 }else if(typeof s == "object"){
3950 if(typeof s[key] != "function"){
3951 b += key + ":" + s[key] + ";";
3958 b += ' class="' + o["cls"] + '"';
3959 }else if(attr == "htmlFor"){
3960 b += ' for="' + o["htmlFor"] + '"';
3962 b += " " + attr + '="' + o[attr] + '"';
3966 if(emptyTags.test(o.tag)){
3970 var cn = o.children || o.cn;
3972 //http://bugs.kde.org/show_bug.cgi?id=71506
3973 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
3974 for(var i = 0, len = cn.length; i < len; i++) {
3975 b += createHtml(cn[i], b);
3978 b += createHtml(cn, b);
3984 b += "</" + o.tag + ">";
3991 var createDom = function(o, parentNode){
3993 // defininition craeted..
3995 if (o.ns && o.ns != 'html') {
3997 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
3998 xmlns[o.ns] = o.xmlns;
4001 if (typeof(xmlns[o.ns]) == 'undefined') {
4002 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4008 if (typeof(o) == 'string') {
4009 return parentNode.appendChild(document.createTextNode(o));
4011 o.tag = o.tag || div;
4012 if (o.ns && Roo.isIE) {
4014 o.tag = o.ns + ':' + o.tag;
4017 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4018 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4021 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4022 attr == "style" || typeof o[attr] == "function") continue;
4024 if(attr=="cls" && Roo.isIE){
4025 el.className = o["cls"];
4027 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4028 else el[attr] = o[attr];
4031 Roo.DomHelper.applyStyles(el, o.style);
4032 var cn = o.children || o.cn;
4034 //http://bugs.kde.org/show_bug.cgi?id=71506
4035 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4036 for(var i = 0, len = cn.length; i < len; i++) {
4037 createDom(cn[i], el);
4044 el.innerHTML = o.html;
4047 parentNode.appendChild(el);
4052 var ieTable = function(depth, s, h, e){
4053 tempTableEl.innerHTML = [s, h, e].join('');
4054 var i = -1, el = tempTableEl;
4061 // kill repeat to save bytes
4065 tbe = '</tbody>'+te,
4071 * Nasty code for IE's broken table implementation
4073 var insertIntoTable = function(tag, where, el, html){
4075 tempTableEl = document.createElement('div');
4080 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4083 if(where == 'beforebegin'){
4087 before = el.nextSibling;
4090 node = ieTable(4, trs, html, tre);
4092 else if(tag == 'tr'){
4093 if(where == 'beforebegin'){
4096 node = ieTable(3, tbs, html, tbe);
4097 } else if(where == 'afterend'){
4098 before = el.nextSibling;
4100 node = ieTable(3, tbs, html, tbe);
4101 } else{ // INTO a TR
4102 if(where == 'afterbegin'){
4103 before = el.firstChild;
4105 node = ieTable(4, trs, html, tre);
4107 } else if(tag == 'tbody'){
4108 if(where == 'beforebegin'){
4111 node = ieTable(2, ts, html, te);
4112 } else if(where == 'afterend'){
4113 before = el.nextSibling;
4115 node = ieTable(2, ts, html, te);
4117 if(where == 'afterbegin'){
4118 before = el.firstChild;
4120 node = ieTable(3, tbs, html, tbe);
4123 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4126 if(where == 'afterbegin'){
4127 before = el.firstChild;
4129 node = ieTable(2, ts, html, te);
4131 el.insertBefore(node, before);
4136 /** True to force the use of DOM instead of html fragments @type Boolean */
4140 * Returns the markup for the passed Element(s) config
4141 * @param {Object} o The Dom object spec (and children)
4144 markup : function(o){
4145 return createHtml(o);
4149 * Applies a style specification to an element
4150 * @param {String/HTMLElement} el The element to apply styles to
4151 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4152 * a function which returns such a specification.
4154 applyStyles : function(el, styles){
4157 if(typeof styles == "string"){
4158 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4160 while ((matches = re.exec(styles)) != null){
4161 el.setStyle(matches[1], matches[2]);
4163 }else if (typeof styles == "object"){
4164 for (var style in styles){
4165 el.setStyle(style, styles[style]);
4167 }else if (typeof styles == "function"){
4168 Roo.DomHelper.applyStyles(el, styles.call());
4174 * Inserts an HTML fragment into the Dom
4175 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4176 * @param {HTMLElement} el The context element
4177 * @param {String} html The HTML fragmenet
4178 * @return {HTMLElement} The new node
4180 insertHtml : function(where, el, html){
4181 where = where.toLowerCase();
4182 if(el.insertAdjacentHTML){
4183 if(tableRe.test(el.tagName)){
4185 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4191 el.insertAdjacentHTML('BeforeBegin', html);
4192 return el.previousSibling;
4194 el.insertAdjacentHTML('AfterBegin', html);
4195 return el.firstChild;
4197 el.insertAdjacentHTML('BeforeEnd', html);
4198 return el.lastChild;
4200 el.insertAdjacentHTML('AfterEnd', html);
4201 return el.nextSibling;
4203 throw 'Illegal insertion point -> "' + where + '"';
4205 var range = el.ownerDocument.createRange();
4209 range.setStartBefore(el);
4210 frag = range.createContextualFragment(html);
4211 el.parentNode.insertBefore(frag, el);
4212 return el.previousSibling;
4215 range.setStartBefore(el.firstChild);
4216 frag = range.createContextualFragment(html);
4217 el.insertBefore(frag, el.firstChild);
4218 return el.firstChild;
4220 el.innerHTML = html;
4221 return el.firstChild;
4225 range.setStartAfter(el.lastChild);
4226 frag = range.createContextualFragment(html);
4227 el.appendChild(frag);
4228 return el.lastChild;
4230 el.innerHTML = html;
4231 return el.lastChild;
4234 range.setStartAfter(el);
4235 frag = range.createContextualFragment(html);
4236 el.parentNode.insertBefore(frag, el.nextSibling);
4237 return el.nextSibling;
4239 throw 'Illegal insertion point -> "' + where + '"';
4243 * Creates new Dom element(s) and inserts them before el
4244 * @param {String/HTMLElement/Element} el The context element
4245 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4246 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4247 * @return {HTMLElement/Roo.Element} The new node
4249 insertBefore : function(el, o, returnElement){
4250 return this.doInsert(el, o, returnElement, "beforeBegin");
4254 * Creates new Dom element(s) and inserts them after el
4255 * @param {String/HTMLElement/Element} el The context element
4256 * @param {Object} o The Dom object spec (and children)
4257 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4258 * @return {HTMLElement/Roo.Element} The new node
4260 insertAfter : function(el, o, returnElement){
4261 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4265 * Creates new Dom element(s) and inserts them as the first child of el
4266 * @param {String/HTMLElement/Element} el The context element
4267 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4268 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4269 * @return {HTMLElement/Roo.Element} The new node
4271 insertFirst : function(el, o, returnElement){
4272 return this.doInsert(el, o, returnElement, "afterBegin");
4276 doInsert : function(el, o, returnElement, pos, sibling){
4277 el = Roo.getDom(el);
4279 if(this.useDom || o.ns){
4280 newNode = createDom(o, null);
4281 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4283 var html = createHtml(o);
4284 newNode = this.insertHtml(pos, el, html);
4286 return returnElement ? Roo.get(newNode, true) : newNode;
4290 * Creates new Dom element(s) and appends them to el
4291 * @param {String/HTMLElement/Element} el The context element
4292 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4293 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4294 * @return {HTMLElement/Roo.Element} The new node
4296 append : function(el, o, returnElement){
4297 el = Roo.getDom(el);
4299 if(this.useDom || o.ns){
4300 newNode = createDom(o, null);
4301 el.appendChild(newNode);
4303 var html = createHtml(o);
4304 newNode = this.insertHtml("beforeEnd", el, html);
4306 return returnElement ? Roo.get(newNode, true) : newNode;
4310 * Creates new Dom element(s) and overwrites the contents of el with them
4311 * @param {String/HTMLElement/Element} el The context element
4312 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4313 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4314 * @return {HTMLElement/Roo.Element} The new node
4316 overwrite : function(el, o, returnElement){
4317 el = Roo.getDom(el);
4320 while (el.childNodes.length) {
4321 el.removeChild(el.firstChild);
4325 el.innerHTML = createHtml(o);
4328 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4332 * Creates a new Roo.DomHelper.Template from the Dom object spec
4333 * @param {Object} o The Dom object spec (and children)
4334 * @return {Roo.DomHelper.Template} The new template
4336 createTemplate : function(o){
4337 var html = createHtml(o);
4338 return new Roo.Template(html);
4344 * Ext JS Library 1.1.1
4345 * Copyright(c) 2006-2007, Ext JS, LLC.
4347 * Originally Released Under LGPL - original licence link has changed is not relivant.
4350 * <script type="text/javascript">
4354 * @class Roo.Template
4355 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4356 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4359 var t = new Roo.Template(
4360 '<div name="{id}">',
4361 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4364 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4366 * 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>.
4368 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4370 Roo.Template = function(html){
4371 if(html instanceof Array){
4372 html = html.join("");
4373 }else if(arguments.length > 1){
4374 html = Array.prototype.join.call(arguments, "");
4380 Roo.Template.prototype = {
4382 * Returns an HTML fragment of this template with the specified values applied.
4383 * @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'})
4384 * @return {String} The HTML fragment
4386 applyTemplate : function(values){
4388 return this.compiled(values);
4390 var useF = this.disableFormats !== true;
4391 var fm = Roo.util.Format, tpl = this;
4392 var fn = function(m, name, format, args){
4394 if(format.substr(0, 5) == "this."){
4395 return tpl.call(format.substr(5), values[name], values);
4398 // quoted values are required for strings in compiled templates,
4399 // but for non compiled we need to strip them
4400 // quoted reversed for jsmin
4401 var re = /^\s*['"](.*)["']\s*$/;
4402 args = args.split(',');
4403 for(var i = 0, len = args.length; i < len; i++){
4404 args[i] = args[i].replace(re, "$1");
4406 args = [values[name]].concat(args);
4408 args = [values[name]];
4410 return fm[format].apply(fm, args);
4413 return values[name] !== undefined ? values[name] : "";
4416 return this.html.replace(this.re, fn);
4420 * Sets the HTML used as the template and optionally compiles it.
4421 * @param {String} html
4422 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4423 * @return {Roo.Template} this
4425 set : function(html, compile){
4427 this.compiled = null;
4435 * True to disable format functions (defaults to false)
4438 disableFormats : false,
4441 * The regular expression used to match template variables
4445 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4448 * Compiles the template into an internal function, eliminating the RegEx overhead.
4449 * @return {Roo.Template} this
4451 compile : function(){
4452 var fm = Roo.util.Format;
4453 var useF = this.disableFormats !== true;
4454 var sep = Roo.isGecko ? "+" : ",";
4455 var fn = function(m, name, format, args){
4457 args = args ? ',' + args : "";
4458 if(format.substr(0, 5) != "this."){
4459 format = "fm." + format + '(';
4461 format = 'this.call("'+ format.substr(5) + '", ';
4465 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4467 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4470 // branched to use + in gecko and [].join() in others
4472 body = "this.compiled = function(values){ return '" +
4473 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4476 body = ["this.compiled = function(values){ return ['"];
4477 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4478 body.push("'].join('');};");
4479 body = body.join('');
4489 // private function used to call members
4490 call : function(fnName, value, allValues){
4491 return this[fnName](value, allValues);
4495 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4496 * @param {String/HTMLElement/Roo.Element} el The context element
4497 * @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'})
4498 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4499 * @return {HTMLElement/Roo.Element} The new node or Element
4501 insertFirst: function(el, values, returnElement){
4502 return this.doInsert('afterBegin', el, values, returnElement);
4506 * Applies the supplied values to the template and inserts the new node(s) before el.
4507 * @param {String/HTMLElement/Roo.Element} el The context element
4508 * @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'})
4509 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4510 * @return {HTMLElement/Roo.Element} The new node or Element
4512 insertBefore: function(el, values, returnElement){
4513 return this.doInsert('beforeBegin', el, values, returnElement);
4517 * Applies the supplied values to the template and inserts the new node(s) after el.
4518 * @param {String/HTMLElement/Roo.Element} el The context element
4519 * @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'})
4520 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4521 * @return {HTMLElement/Roo.Element} The new node or Element
4523 insertAfter : function(el, values, returnElement){
4524 return this.doInsert('afterEnd', el, values, returnElement);
4528 * Applies the supplied values to the template and appends the new node(s) to el.
4529 * @param {String/HTMLElement/Roo.Element} el The context element
4530 * @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'})
4531 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4532 * @return {HTMLElement/Roo.Element} The new node or Element
4534 append : function(el, values, returnElement){
4535 return this.doInsert('beforeEnd', el, values, returnElement);
4538 doInsert : function(where, el, values, returnEl){
4539 el = Roo.getDom(el);
4540 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4541 return returnEl ? Roo.get(newNode, true) : newNode;
4545 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4546 * @param {String/HTMLElement/Roo.Element} el The context element
4547 * @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'})
4548 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4549 * @return {HTMLElement/Roo.Element} The new node or Element
4551 overwrite : function(el, values, returnElement){
4552 el = Roo.getDom(el);
4553 el.innerHTML = this.applyTemplate(values);
4554 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4558 * Alias for {@link #applyTemplate}
4561 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4564 Roo.DomHelper.Template = Roo.Template;
4567 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4568 * @param {String/HTMLElement} el A DOM element or its id
4569 * @returns {Roo.Template} The created template
4572 Roo.Template.from = function(el){
4573 el = Roo.getDom(el);
4574 return new Roo.Template(el.value || el.innerHTML);
4577 * Ext JS Library 1.1.1
4578 * Copyright(c) 2006-2007, Ext JS, LLC.
4580 * Originally Released Under LGPL - original licence link has changed is not relivant.
4583 * <script type="text/javascript">
4588 * This is code is also distributed under MIT license for use
4589 * with jQuery and prototype JavaScript libraries.
4592 * @class Roo.DomQuery
4593 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).
4595 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>
4598 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.
4600 <h4>Element Selectors:</h4>
4602 <li> <b>*</b> any element</li>
4603 <li> <b>E</b> an element with the tag E</li>
4604 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4605 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4606 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4607 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4609 <h4>Attribute Selectors:</h4>
4610 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4612 <li> <b>E[foo]</b> has an attribute "foo"</li>
4613 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4614 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4615 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4616 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4617 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4618 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4620 <h4>Pseudo Classes:</h4>
4622 <li> <b>E:first-child</b> E is the first child of its parent</li>
4623 <li> <b>E:last-child</b> E is the last child of its parent</li>
4624 <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>
4625 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4626 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4627 <li> <b>E:only-child</b> E is the only child of its parent</li>
4628 <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>
4629 <li> <b>E:first</b> the first E in the resultset</li>
4630 <li> <b>E:last</b> the last E in the resultset</li>
4631 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4632 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4633 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4634 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4635 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4636 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4637 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4638 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4639 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4641 <h4>CSS Value Selectors:</h4>
4643 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4644 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4645 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4646 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4647 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4648 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4652 Roo.DomQuery = function(){
4653 var cache = {}, simpleCache = {}, valueCache = {};
4654 var nonSpace = /\S/;
4655 var trimRe = /^\s+|\s+$/g;
4656 var tplRe = /\{(\d+)\}/g;
4657 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4658 var tagTokenRe = /^(#)?([\w-\*]+)/;
4659 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4661 function child(p, index){
4663 var n = p.firstChild;
4665 if(n.nodeType == 1){
4676 while((n = n.nextSibling) && n.nodeType != 1);
4681 while((n = n.previousSibling) && n.nodeType != 1);
4685 function children(d){
4686 var n = d.firstChild, ni = -1;
4688 var nx = n.nextSibling;
4689 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4699 function byClassName(c, a, v){
4703 var r = [], ri = -1, cn;
4704 for(var i = 0, ci; ci = c[i]; i++){
4705 if((' '+ci.className+' ').indexOf(v) != -1){
4712 function attrValue(n, attr){
4713 if(!n.tagName && typeof n.length != "undefined"){
4722 if(attr == "class" || attr == "className"){
4725 return n.getAttribute(attr) || n[attr];
4729 function getNodes(ns, mode, tagName){
4730 var result = [], ri = -1, cs;
4734 tagName = tagName || "*";
4735 if(typeof ns.getElementsByTagName != "undefined"){
4739 for(var i = 0, ni; ni = ns[i]; i++){
4740 cs = ni.getElementsByTagName(tagName);
4741 for(var j = 0, ci; ci = cs[j]; j++){
4745 }else if(mode == "/" || mode == ">"){
4746 var utag = tagName.toUpperCase();
4747 for(var i = 0, ni, cn; ni = ns[i]; i++){
4748 cn = ni.children || ni.childNodes;
4749 for(var j = 0, cj; cj = cn[j]; j++){
4750 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4755 }else if(mode == "+"){
4756 var utag = tagName.toUpperCase();
4757 for(var i = 0, n; n = ns[i]; i++){
4758 while((n = n.nextSibling) && n.nodeType != 1);
4759 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4763 }else if(mode == "~"){
4764 for(var i = 0, n; n = ns[i]; i++){
4765 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4774 function concat(a, b){
4778 for(var i = 0, l = b.length; i < l; i++){
4784 function byTag(cs, tagName){
4785 if(cs.tagName || cs == document){
4791 var r = [], ri = -1;
4792 tagName = tagName.toLowerCase();
4793 for(var i = 0, ci; ci = cs[i]; i++){
4794 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4801 function byId(cs, attr, id){
4802 if(cs.tagName || cs == document){
4808 var r = [], ri = -1;
4809 for(var i = 0,ci; ci = cs[i]; i++){
4810 if(ci && ci.id == id){
4818 function byAttribute(cs, attr, value, op, custom){
4819 var r = [], ri = -1, st = custom=="{";
4820 var f = Roo.DomQuery.operators[op];
4821 for(var i = 0, ci; ci = cs[i]; i++){
4824 a = Roo.DomQuery.getStyle(ci, attr);
4826 else if(attr == "class" || attr == "className"){
4828 }else if(attr == "for"){
4830 }else if(attr == "href"){
4831 a = ci.getAttribute("href", 2);
4833 a = ci.getAttribute(attr);
4835 if((f && f(a, value)) || (!f && a)){
4842 function byPseudo(cs, name, value){
4843 return Roo.DomQuery.pseudos[name](cs, value);
4846 // This is for IE MSXML which does not support expandos.
4847 // IE runs the same speed using setAttribute, however FF slows way down
4848 // and Safari completely fails so they need to continue to use expandos.
4849 var isIE = window.ActiveXObject ? true : false;
4851 // this eval is stop the compressor from
4852 // renaming the variable to something shorter
4854 /** eval:var:batch */
4859 function nodupIEXml(cs){
4861 cs[0].setAttribute("_nodup", d);
4863 for(var i = 1, len = cs.length; i < len; i++){
4865 if(!c.getAttribute("_nodup") != d){
4866 c.setAttribute("_nodup", d);
4870 for(var i = 0, len = cs.length; i < len; i++){
4871 cs[i].removeAttribute("_nodup");
4880 var len = cs.length, c, i, r = cs, cj, ri = -1;
4881 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4884 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4885 return nodupIEXml(cs);
4889 for(i = 1; c = cs[i]; i++){
4894 for(var j = 0; j < i; j++){
4897 for(j = i+1; cj = cs[j]; j++){
4909 function quickDiffIEXml(c1, c2){
4911 for(var i = 0, len = c1.length; i < len; i++){
4912 c1[i].setAttribute("_qdiff", d);
4915 for(var i = 0, len = c2.length; i < len; i++){
4916 if(c2[i].getAttribute("_qdiff") != d){
4917 r[r.length] = c2[i];
4920 for(var i = 0, len = c1.length; i < len; i++){
4921 c1[i].removeAttribute("_qdiff");
4926 function quickDiff(c1, c2){
4927 var len1 = c1.length;
4931 if(isIE && c1[0].selectSingleNode){
4932 return quickDiffIEXml(c1, c2);
4935 for(var i = 0; i < len1; i++){
4939 for(var i = 0, len = c2.length; i < len; i++){
4940 if(c2[i]._qdiff != d){
4941 r[r.length] = c2[i];
4947 function quickId(ns, mode, root, id){
4949 var d = root.ownerDocument || root;
4950 return d.getElementById(id);
4952 ns = getNodes(ns, mode, "*");
4953 return byId(ns, null, id);
4957 getStyle : function(el, name){
4958 return Roo.fly(el).getStyle(name);
4961 * Compiles a selector/xpath query into a reusable function. The returned function
4962 * takes one parameter "root" (optional), which is the context node from where the query should start.
4963 * @param {String} selector The selector/xpath query
4964 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4965 * @return {Function}
4967 compile : function(path, type){
4968 type = type || "select";
4970 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
4971 var q = path, mode, lq;
4972 var tk = Roo.DomQuery.matchers;
4973 var tklen = tk.length;
4976 // accept leading mode switch
4977 var lmode = q.match(modeRe);
4978 if(lmode && lmode[1]){
4979 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
4980 q = q.replace(lmode[1], "");
4982 // strip leading slashes
4983 while(path.substr(0, 1)=="/"){
4984 path = path.substr(1);
4987 while(q && lq != q){
4989 var tm = q.match(tagTokenRe);
4990 if(type == "select"){
4993 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
4995 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
4997 q = q.replace(tm[0], "");
4998 }else if(q.substr(0, 1) != '@'){
4999 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5004 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5006 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5008 q = q.replace(tm[0], "");
5011 while(!(mm = q.match(modeRe))){
5012 var matched = false;
5013 for(var j = 0; j < tklen; j++){
5015 var m = q.match(t.re);
5017 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5020 q = q.replace(m[0], "");
5025 // prevent infinite loop on bad selector
5027 throw 'Error parsing selector, parsing failed at "' + q + '"';
5031 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5032 q = q.replace(mm[1], "");
5035 fn[fn.length] = "return nodup(n);\n}";
5038 * list of variables that need from compression as they are used by eval.
5048 * eval:var:byClassName
5050 * eval:var:byAttribute
5051 * eval:var:attrValue
5059 * Selects a group of elements.
5060 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5061 * @param {Node} root (optional) The start of the query (defaults to document).
5064 select : function(path, root, type){
5065 if(!root || root == document){
5068 if(typeof root == "string"){
5069 root = document.getElementById(root);
5071 var paths = path.split(",");
5073 for(var i = 0, len = paths.length; i < len; i++){
5074 var p = paths[i].replace(trimRe, "");
5076 cache[p] = Roo.DomQuery.compile(p);
5078 throw p + " is not a valid selector";
5081 var result = cache[p](root);
5082 if(result && result != document){
5083 results = results.concat(result);
5086 if(paths.length > 1){
5087 return nodup(results);
5093 * Selects a single element.
5094 * @param {String} selector The selector/xpath query
5095 * @param {Node} root (optional) The start of the query (defaults to document).
5098 selectNode : function(path, root){
5099 return Roo.DomQuery.select(path, root)[0];
5103 * Selects the value of a node, optionally replacing null with the defaultValue.
5104 * @param {String} selector The selector/xpath query
5105 * @param {Node} root (optional) The start of the query (defaults to document).
5106 * @param {String} defaultValue
5108 selectValue : function(path, root, defaultValue){
5109 path = path.replace(trimRe, "");
5110 if(!valueCache[path]){
5111 valueCache[path] = Roo.DomQuery.compile(path, "select");
5113 var n = valueCache[path](root);
5114 n = n[0] ? n[0] : n;
5115 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5116 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5120 * Selects the value of a node, parsing integers and floats.
5121 * @param {String} selector The selector/xpath query
5122 * @param {Node} root (optional) The start of the query (defaults to document).
5123 * @param {Number} defaultValue
5126 selectNumber : function(path, root, defaultValue){
5127 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5128 return parseFloat(v);
5132 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5133 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5134 * @param {String} selector The simple selector to test
5137 is : function(el, ss){
5138 if(typeof el == "string"){
5139 el = document.getElementById(el);
5141 var isArray = (el instanceof Array);
5142 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5143 return isArray ? (result.length == el.length) : (result.length > 0);
5147 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5148 * @param {Array} el An array of elements to filter
5149 * @param {String} selector The simple selector to test
5150 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5151 * the selector instead of the ones that match
5154 filter : function(els, ss, nonMatches){
5155 ss = ss.replace(trimRe, "");
5156 if(!simpleCache[ss]){
5157 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5159 var result = simpleCache[ss](els);
5160 return nonMatches ? quickDiff(result, els) : result;
5164 * Collection of matching regular expressions and code snippets.
5168 select: 'n = byClassName(n, null, " {1} ");'
5170 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5171 select: 'n = byPseudo(n, "{1}", "{2}");'
5173 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5174 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5177 select: 'n = byId(n, null, "{1}");'
5180 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5185 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5186 * 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, > <.
5189 "=" : function(a, v){
5192 "!=" : function(a, v){
5195 "^=" : function(a, v){
5196 return a && a.substr(0, v.length) == v;
5198 "$=" : function(a, v){
5199 return a && a.substr(a.length-v.length) == v;
5201 "*=" : function(a, v){
5202 return a && a.indexOf(v) !== -1;
5204 "%=" : function(a, v){
5205 return (a % v) == 0;
5207 "|=" : function(a, v){
5208 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5210 "~=" : function(a, v){
5211 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5216 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5217 * and the argument (if any) supplied in the selector.
5220 "first-child" : function(c){
5221 var r = [], ri = -1, n;
5222 for(var i = 0, ci; ci = n = c[i]; i++){
5223 while((n = n.previousSibling) && n.nodeType != 1);
5231 "last-child" : function(c){
5232 var r = [], ri = -1, n;
5233 for(var i = 0, ci; ci = n = c[i]; i++){
5234 while((n = n.nextSibling) && n.nodeType != 1);
5242 "nth-child" : function(c, a) {
5243 var r = [], ri = -1;
5244 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5245 var f = (m[1] || 1) - 0, l = m[2] - 0;
5246 for(var i = 0, n; n = c[i]; i++){
5247 var pn = n.parentNode;
5248 if (batch != pn._batch) {
5250 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5251 if(cn.nodeType == 1){
5258 if (l == 0 || n.nodeIndex == l){
5261 } else if ((n.nodeIndex + l) % f == 0){
5269 "only-child" : function(c){
5270 var r = [], ri = -1;;
5271 for(var i = 0, ci; ci = c[i]; i++){
5272 if(!prev(ci) && !next(ci)){
5279 "empty" : function(c){
5280 var r = [], ri = -1;
5281 for(var i = 0, ci; ci = c[i]; i++){
5282 var cns = ci.childNodes, j = 0, cn, empty = true;
5285 if(cn.nodeType == 1 || cn.nodeType == 3){
5297 "contains" : function(c, v){
5298 var r = [], ri = -1;
5299 for(var i = 0, ci; ci = c[i]; i++){
5300 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5307 "nodeValue" : function(c, v){
5308 var r = [], ri = -1;
5309 for(var i = 0, ci; ci = c[i]; i++){
5310 if(ci.firstChild && ci.firstChild.nodeValue == v){
5317 "checked" : function(c){
5318 var r = [], ri = -1;
5319 for(var i = 0, ci; ci = c[i]; i++){
5320 if(ci.checked == true){
5327 "not" : function(c, ss){
5328 return Roo.DomQuery.filter(c, ss, true);
5331 "odd" : function(c){
5332 return this["nth-child"](c, "odd");
5335 "even" : function(c){
5336 return this["nth-child"](c, "even");
5339 "nth" : function(c, a){
5340 return c[a-1] || [];
5343 "first" : function(c){
5347 "last" : function(c){
5348 return c[c.length-1] || [];
5351 "has" : function(c, ss){
5352 var s = Roo.DomQuery.select;
5353 var r = [], ri = -1;
5354 for(var i = 0, ci; ci = c[i]; i++){
5355 if(s(ss, ci).length > 0){
5362 "next" : function(c, ss){
5363 var is = Roo.DomQuery.is;
5364 var r = [], ri = -1;
5365 for(var i = 0, ci; ci = c[i]; i++){
5374 "prev" : function(c, ss){
5375 var is = Roo.DomQuery.is;
5376 var r = [], ri = -1;
5377 for(var i = 0, ci; ci = c[i]; i++){
5390 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5391 * @param {String} path The selector/xpath query
5392 * @param {Node} root (optional) The start of the query (defaults to document).
5397 Roo.query = Roo.DomQuery.select;
5400 * Ext JS Library 1.1.1
5401 * Copyright(c) 2006-2007, Ext JS, LLC.
5403 * Originally Released Under LGPL - original licence link has changed is not relivant.
5406 * <script type="text/javascript">
5410 * @class Roo.util.Observable
5411 * Base class that provides a common interface for publishing events. Subclasses are expected to
5412 * to have a property "events" with all the events defined.<br>
5415 Employee = function(name){
5422 Roo.extend(Employee, Roo.util.Observable);
5424 * @param {Object} config properties to use (incuding events / listeners)
5427 Roo.util.Observable = function(cfg){
5430 this.addEvents(cfg.events || {});
5432 delete cfg.events; // make sure
5435 Roo.apply(this, cfg);
5438 this.on(this.listeners);
5439 delete this.listeners;
5442 Roo.util.Observable.prototype = {
5444 * @cfg {Object} listeners list of events and functions to call for this object,
5448 'click' : function(e) {
5458 * Fires the specified event with the passed parameters (minus the event name).
5459 * @param {String} eventName
5460 * @param {Object...} args Variable number of parameters are passed to handlers
5461 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5463 fireEvent : function(){
5464 var ce = this.events[arguments[0].toLowerCase()];
5465 if(typeof ce == "object"){
5466 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5473 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5476 * Appends an event handler to this component
5477 * @param {String} eventName The type of event to listen for
5478 * @param {Function} handler The method the event invokes
5479 * @param {Object} scope (optional) The scope in which to execute the handler
5480 * function. The handler function's "this" context.
5481 * @param {Object} options (optional) An object containing handler configuration
5482 * properties. This may contain any of the following properties:<ul>
5483 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5484 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5485 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5486 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5487 * by the specified number of milliseconds. If the event fires again within that time, the original
5488 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5491 * <b>Combining Options</b><br>
5492 * Using the options argument, it is possible to combine different types of listeners:<br>
5494 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5496 el.on('click', this.onClick, this, {
5503 * <b>Attaching multiple handlers in 1 call</b><br>
5504 * The method also allows for a single argument to be passed which is a config object containing properties
5505 * which specify multiple handlers.
5514 fn: this.onMouseOver,
5518 fn: this.onMouseOut,
5524 * Or a shorthand syntax which passes the same scope object to all handlers:
5527 'click': this.onClick,
5528 'mouseover': this.onMouseOver,
5529 'mouseout': this.onMouseOut,
5534 addListener : function(eventName, fn, scope, o){
5535 if(typeof eventName == "object"){
5538 if(this.filterOptRe.test(e)){
5541 if(typeof o[e] == "function"){
5543 this.addListener(e, o[e], o.scope, o);
5545 // individual options
5546 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5551 o = (!o || typeof o == "boolean") ? {} : o;
5552 eventName = eventName.toLowerCase();
5553 var ce = this.events[eventName] || true;
5554 if(typeof ce == "boolean"){
5555 ce = new Roo.util.Event(this, eventName);
5556 this.events[eventName] = ce;
5558 ce.addListener(fn, scope, o);
5562 * Removes a listener
5563 * @param {String} eventName The type of event to listen for
5564 * @param {Function} handler The handler to remove
5565 * @param {Object} scope (optional) The scope (this object) for the handler
5567 removeListener : function(eventName, fn, scope){
5568 var ce = this.events[eventName.toLowerCase()];
5569 if(typeof ce == "object"){
5570 ce.removeListener(fn, scope);
5575 * Removes all listeners for this object
5577 purgeListeners : function(){
5578 for(var evt in this.events){
5579 if(typeof this.events[evt] == "object"){
5580 this.events[evt].clearListeners();
5585 relayEvents : function(o, events){
5586 var createHandler = function(ename){
5588 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5591 for(var i = 0, len = events.length; i < len; i++){
5592 var ename = events[i];
5593 if(!this.events[ename]){ this.events[ename] = true; };
5594 o.on(ename, createHandler(ename), this);
5599 * Used to define events on this Observable
5600 * @param {Object} object The object with the events defined
5602 addEvents : function(o){
5606 Roo.applyIf(this.events, o);
5610 * Checks to see if this object has any listeners for a specified event
5611 * @param {String} eventName The name of the event to check for
5612 * @return {Boolean} True if the event is being listened for, else false
5614 hasListener : function(eventName){
5615 var e = this.events[eventName];
5616 return typeof e == "object" && e.listeners.length > 0;
5620 * Appends an event handler to this element (shorthand for addListener)
5621 * @param {String} eventName The type of event to listen for
5622 * @param {Function} handler The method the event invokes
5623 * @param {Object} scope (optional) The scope in which to execute the handler
5624 * function. The handler function's "this" context.
5625 * @param {Object} options (optional)
5628 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5630 * Removes a listener (shorthand for removeListener)
5631 * @param {String} eventName The type of event to listen for
5632 * @param {Function} handler The handler to remove
5633 * @param {Object} scope (optional) The scope (this object) for the handler
5636 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5639 * Starts capture on the specified Observable. All events will be passed
5640 * to the supplied function with the event name + standard signature of the event
5641 * <b>before</b> the event is fired. If the supplied function returns false,
5642 * the event will not fire.
5643 * @param {Observable} o The Observable to capture
5644 * @param {Function} fn The function to call
5645 * @param {Object} scope (optional) The scope (this object) for the fn
5648 Roo.util.Observable.capture = function(o, fn, scope){
5649 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5653 * Removes <b>all</b> added captures from the Observable.
5654 * @param {Observable} o The Observable to release
5657 Roo.util.Observable.releaseCapture = function(o){
5658 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5663 var createBuffered = function(h, o, scope){
5664 var task = new Roo.util.DelayedTask();
5666 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5670 var createSingle = function(h, e, fn, scope){
5672 e.removeListener(fn, scope);
5673 return h.apply(scope, arguments);
5677 var createDelayed = function(h, o, scope){
5679 var args = Array.prototype.slice.call(arguments, 0);
5680 setTimeout(function(){
5681 h.apply(scope, args);
5686 Roo.util.Event = function(obj, name){
5689 this.listeners = [];
5692 Roo.util.Event.prototype = {
5693 addListener : function(fn, scope, options){
5694 var o = options || {};
5695 scope = scope || this.obj;
5696 if(!this.isListening(fn, scope)){
5697 var l = {fn: fn, scope: scope, options: o};
5700 h = createDelayed(h, o, scope);
5703 h = createSingle(h, this, fn, scope);
5706 h = createBuffered(h, o, scope);
5709 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5710 this.listeners.push(l);
5712 this.listeners = this.listeners.slice(0);
5713 this.listeners.push(l);
5718 findListener : function(fn, scope){
5719 scope = scope || this.obj;
5720 var ls = this.listeners;
5721 for(var i = 0, len = ls.length; i < len; i++){
5723 if(l.fn == fn && l.scope == scope){
5730 isListening : function(fn, scope){
5731 return this.findListener(fn, scope) != -1;
5734 removeListener : function(fn, scope){
5736 if((index = this.findListener(fn, scope)) != -1){
5738 this.listeners.splice(index, 1);
5740 this.listeners = this.listeners.slice(0);
5741 this.listeners.splice(index, 1);
5748 clearListeners : function(){
5749 this.listeners = [];
5753 var ls = this.listeners, scope, len = ls.length;
5756 var args = Array.prototype.slice.call(arguments, 0);
5757 for(var i = 0; i < len; i++){
5759 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5760 this.firing = false;
5764 this.firing = false;
5771 * Ext JS Library 1.1.1
5772 * Copyright(c) 2006-2007, Ext JS, LLC.
5774 * Originally Released Under LGPL - original licence link has changed is not relivant.
5777 * <script type="text/javascript">
5781 * @class Roo.EventManager
5782 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5783 * several useful events directly.
5784 * See {@link Roo.EventObject} for more details on normalized event objects.
5787 Roo.EventManager = function(){
5788 var docReadyEvent, docReadyProcId, docReadyState = false;
5789 var resizeEvent, resizeTask, textEvent, textSize;
5790 var E = Roo.lib.Event;
5791 var D = Roo.lib.Dom;
5794 var fireDocReady = function(){
5796 docReadyState = true;
5799 clearInterval(docReadyProcId);
5801 if(Roo.isGecko || Roo.isOpera) {
5802 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5805 var defer = document.getElementById("ie-deferred-loader");
5807 defer.onreadystatechange = null;
5808 defer.parentNode.removeChild(defer);
5812 docReadyEvent.fire();
5813 docReadyEvent.clearListeners();
5818 var initDocReady = function(){
5819 docReadyEvent = new Roo.util.Event();
5820 if(Roo.isGecko || Roo.isOpera) {
5821 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5823 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5824 var defer = document.getElementById("ie-deferred-loader");
5825 defer.onreadystatechange = function(){
5826 if(this.readyState == "complete"){
5830 }else if(Roo.isSafari){
5831 docReadyProcId = setInterval(function(){
5832 var rs = document.readyState;
5833 if(rs == "complete") {
5838 // no matter what, make sure it fires on load
5839 E.on(window, "load", fireDocReady);
5842 var createBuffered = function(h, o){
5843 var task = new Roo.util.DelayedTask(h);
5845 // create new event object impl so new events don't wipe out properties
5846 e = new Roo.EventObjectImpl(e);
5847 task.delay(o.buffer, h, null, [e]);
5851 var createSingle = function(h, el, ename, fn){
5853 Roo.EventManager.removeListener(el, ename, fn);
5858 var createDelayed = function(h, o){
5860 // create new event object impl so new events don't wipe out properties
5861 e = new Roo.EventObjectImpl(e);
5862 setTimeout(function(){
5868 var listen = function(element, ename, opt, fn, scope){
5869 var o = (!opt || typeof opt == "boolean") ? {} : opt;
5870 fn = fn || o.fn; scope = scope || o.scope;
5871 var el = Roo.getDom(element);
5873 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
5875 var h = function(e){
5876 e = Roo.EventObject.setEvent(e);
5879 t = e.getTarget(o.delegate, el);
5886 if(o.stopEvent === true){
5889 if(o.preventDefault === true){
5892 if(o.stopPropagation === true){
5893 e.stopPropagation();
5896 if(o.normalized === false){
5900 fn.call(scope || el, e, t, o);
5903 h = createDelayed(h, o);
5906 h = createSingle(h, el, ename, fn);
5909 h = createBuffered(h, o);
5911 fn._handlers = fn._handlers || [];
5912 fn._handlers.push([Roo.id(el), ename, h]);
5915 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
5916 el.addEventListener("DOMMouseScroll", h, false);
5917 E.on(window, 'unload', function(){
5918 el.removeEventListener("DOMMouseScroll", h, false);
5921 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5922 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
5927 var stopListening = function(el, ename, fn){
5928 var id = Roo.id(el), hds = fn._handlers, hd = fn;
5930 for(var i = 0, len = hds.length; i < len; i++){
5932 if(h[0] == id && h[1] == ename){
5939 E.un(el, ename, hd);
5940 el = Roo.getDom(el);
5941 if(ename == "mousewheel" && el.addEventListener){
5942 el.removeEventListener("DOMMouseScroll", hd, false);
5944 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5945 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
5949 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
5956 * @scope Roo.EventManager
5961 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
5962 * object with a Roo.EventObject
5963 * @param {Function} fn The method the event invokes
5964 * @param {Object} scope An object that becomes the scope of the handler
5965 * @param {boolean} override If true, the obj passed in becomes
5966 * the execution scope of the listener
5967 * @return {Function} The wrapped function
5970 wrap : function(fn, scope, override){
5972 Roo.EventObject.setEvent(e);
5973 fn.call(override ? scope || window : window, Roo.EventObject, scope);
5978 * Appends an event handler to an element (shorthand for addListener)
5979 * @param {String/HTMLElement} element The html element or id to assign the
5980 * @param {String} eventName The type of event to listen for
5981 * @param {Function} handler The method the event invokes
5982 * @param {Object} scope (optional) The scope in which to execute the handler
5983 * function. The handler function's "this" context.
5984 * @param {Object} options (optional) An object containing handler configuration
5985 * properties. This may contain any of the following properties:<ul>
5986 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5987 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
5988 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
5989 * <li>preventDefault {Boolean} True to prevent the default action</li>
5990 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
5991 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
5992 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5993 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5994 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5995 * by the specified number of milliseconds. If the event fires again within that time, the original
5996 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5999 * <b>Combining Options</b><br>
6000 * Using the options argument, it is possible to combine different types of listeners:<br>
6002 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6004 el.on('click', this.onClick, this, {
6011 * <b>Attaching multiple handlers in 1 call</b><br>
6012 * The method also allows for a single argument to be passed which is a config object containing properties
6013 * which specify multiple handlers.
6023 fn: this.onMouseOver
6032 * Or a shorthand syntax:<br>
6035 'click' : this.onClick,
6036 'mouseover' : this.onMouseOver,
6037 'mouseout' : this.onMouseOut
6041 addListener : function(element, eventName, fn, scope, options){
6042 if(typeof eventName == "object"){
6048 if(typeof o[e] == "function"){
6050 listen(element, e, o, o[e], o.scope);
6052 // individual options
6053 listen(element, e, o[e]);
6058 return listen(element, eventName, options, fn, scope);
6062 * Removes an event handler
6064 * @param {String/HTMLElement} element The id or html element to remove the
6066 * @param {String} eventName The type of event
6067 * @param {Function} fn
6068 * @return {Boolean} True if a listener was actually removed
6070 removeListener : function(element, eventName, fn){
6071 return stopListening(element, eventName, fn);
6075 * Fires when the document is ready (before onload and before images are loaded). Can be
6076 * accessed shorthanded Roo.onReady().
6077 * @param {Function} fn The method the event invokes
6078 * @param {Object} scope An object that becomes the scope of the handler
6079 * @param {boolean} options
6081 onDocumentReady : function(fn, scope, options){
6082 if(docReadyState){ // if it already fired
6083 docReadyEvent.addListener(fn, scope, options);
6084 docReadyEvent.fire();
6085 docReadyEvent.clearListeners();
6091 docReadyEvent.addListener(fn, scope, options);
6095 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6096 * @param {Function} fn The method the event invokes
6097 * @param {Object} scope An object that becomes the scope of the handler
6098 * @param {boolean} options
6100 onWindowResize : function(fn, scope, options){
6102 resizeEvent = new Roo.util.Event();
6103 resizeTask = new Roo.util.DelayedTask(function(){
6104 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6106 E.on(window, "resize", function(){
6108 resizeTask.delay(50);
6110 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6114 resizeEvent.addListener(fn, scope, options);
6118 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6119 * @param {Function} fn The method the event invokes
6120 * @param {Object} scope An object that becomes the scope of the handler
6121 * @param {boolean} options
6123 onTextResize : function(fn, scope, options){
6125 textEvent = new Roo.util.Event();
6126 var textEl = new Roo.Element(document.createElement('div'));
6127 textEl.dom.className = 'x-text-resize';
6128 textEl.dom.innerHTML = 'X';
6129 textEl.appendTo(document.body);
6130 textSize = textEl.dom.offsetHeight;
6131 setInterval(function(){
6132 if(textEl.dom.offsetHeight != textSize){
6133 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6135 }, this.textResizeInterval);
6137 textEvent.addListener(fn, scope, options);
6141 * Removes the passed window resize listener.
6142 * @param {Function} fn The method the event invokes
6143 * @param {Object} scope The scope of handler
6145 removeResizeListener : function(fn, scope){
6147 resizeEvent.removeListener(fn, scope);
6152 fireResize : function(){
6154 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6158 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6162 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6164 textResizeInterval : 50
6169 * @scopeAlias pub=Roo.EventManager
6173 * Appends an event handler to an element (shorthand for addListener)
6174 * @param {String/HTMLElement} element The html element or id to assign the
6175 * @param {String} eventName The type of event to listen for
6176 * @param {Function} handler The method the event invokes
6177 * @param {Object} scope (optional) The scope in which to execute the handler
6178 * function. The handler function's "this" context.
6179 * @param {Object} options (optional) An object containing handler configuration
6180 * properties. This may contain any of the following properties:<ul>
6181 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6182 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6183 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6184 * <li>preventDefault {Boolean} True to prevent the default action</li>
6185 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6186 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6187 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6188 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6189 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6190 * by the specified number of milliseconds. If the event fires again within that time, the original
6191 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6194 * <b>Combining Options</b><br>
6195 * Using the options argument, it is possible to combine different types of listeners:<br>
6197 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6199 el.on('click', this.onClick, this, {
6206 * <b>Attaching multiple handlers in 1 call</b><br>
6207 * The method also allows for a single argument to be passed which is a config object containing properties
6208 * which specify multiple handlers.
6218 fn: this.onMouseOver
6227 * Or a shorthand syntax:<br>
6230 'click' : this.onClick,
6231 'mouseover' : this.onMouseOver,
6232 'mouseout' : this.onMouseOut
6236 pub.on = pub.addListener;
6237 pub.un = pub.removeListener;
6239 pub.stoppedMouseDownEvent = new Roo.util.Event();
6243 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6244 * @param {Function} fn The method the event invokes
6245 * @param {Object} scope An object that becomes the scope of the handler
6246 * @param {boolean} override If true, the obj passed in becomes
6247 * the execution scope of the listener
6251 Roo.onReady = Roo.EventManager.onDocumentReady;
6253 Roo.onReady(function(){
6254 var bd = Roo.get(document.body);
6259 : Roo.isGecko ? "roo-gecko"
6260 : Roo.isOpera ? "roo-opera"
6261 : Roo.isSafari ? "roo-safari" : ""];
6264 cls.push("roo-mac");
6267 cls.push("roo-linux");
6269 if(Roo.isBorderBox){
6270 cls.push('roo-border-box');
6272 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6273 var p = bd.dom.parentNode;
6275 p.className += ' roo-strict';
6278 bd.addClass(cls.join(' '));
6282 * @class Roo.EventObject
6283 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6284 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6287 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6289 var target = e.getTarget();
6292 var myDiv = Roo.get("myDiv");
6293 myDiv.on("click", handleClick);
6295 Roo.EventManager.on("myDiv", 'click', handleClick);
6296 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6300 Roo.EventObject = function(){
6302 var E = Roo.lib.Event;
6304 // safari keypress events for special keys return bad keycodes
6307 63235 : 39, // right
6310 63276 : 33, // page up
6311 63277 : 34, // page down
6312 63272 : 46, // delete
6317 // normalize button clicks
6318 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6319 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6321 Roo.EventObjectImpl = function(e){
6323 this.setEvent(e.browserEvent || e);
6326 Roo.EventObjectImpl.prototype = {
6328 * Used to fix doc tools.
6329 * @scope Roo.EventObject.prototype
6335 /** The normal browser event */
6336 browserEvent : null,
6337 /** The button pressed in a mouse event */
6339 /** True if the shift key was down during the event */
6341 /** True if the control key was down during the event */
6343 /** True if the alt key was down during the event */
6402 setEvent : function(e){
6403 if(e == this || (e && e.browserEvent)){ // already wrapped
6406 this.browserEvent = e;
6408 // normalize buttons
6409 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6410 if(e.type == 'click' && this.button == -1){
6414 this.shiftKey = e.shiftKey;
6415 // mac metaKey behaves like ctrlKey
6416 this.ctrlKey = e.ctrlKey || e.metaKey;
6417 this.altKey = e.altKey;
6418 // in getKey these will be normalized for the mac
6419 this.keyCode = e.keyCode;
6420 // keyup warnings on firefox.
6421 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6422 // cache the target for the delayed and or buffered events
6423 this.target = E.getTarget(e);
6425 this.xy = E.getXY(e);
6428 this.shiftKey = false;
6429 this.ctrlKey = false;
6430 this.altKey = false;
6440 * Stop the event (preventDefault and stopPropagation)
6442 stopEvent : function(){
6443 if(this.browserEvent){
6444 if(this.browserEvent.type == 'mousedown'){
6445 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6447 E.stopEvent(this.browserEvent);
6452 * Prevents the browsers default handling of the event.
6454 preventDefault : function(){
6455 if(this.browserEvent){
6456 E.preventDefault(this.browserEvent);
6461 isNavKeyPress : function(){
6462 var k = this.keyCode;
6463 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6464 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6467 isSpecialKey : function(){
6468 var k = this.keyCode;
6469 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6470 (k == 16) || (k == 17) ||
6471 (k >= 18 && k <= 20) ||
6472 (k >= 33 && k <= 35) ||
6473 (k >= 36 && k <= 39) ||
6474 (k >= 44 && k <= 45);
6477 * Cancels bubbling of the event.
6479 stopPropagation : function(){
6480 if(this.browserEvent){
6481 if(this.type == 'mousedown'){
6482 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6484 E.stopPropagation(this.browserEvent);
6489 * Gets the key code for the event.
6492 getCharCode : function(){
6493 return this.charCode || this.keyCode;
6497 * Returns a normalized keyCode for the event.
6498 * @return {Number} The key code
6500 getKey : function(){
6501 var k = this.keyCode || this.charCode;
6502 return Roo.isSafari ? (safariKeys[k] || k) : k;
6506 * Gets the x coordinate of the event.
6509 getPageX : function(){
6514 * Gets the y coordinate of the event.
6517 getPageY : function(){
6522 * Gets the time of the event.
6525 getTime : function(){
6526 if(this.browserEvent){
6527 return E.getTime(this.browserEvent);
6533 * Gets the page coordinates of the event.
6534 * @return {Array} The xy values like [x, y]
6541 * Gets the target for the event.
6542 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6543 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6544 search as a number or element (defaults to 10 || document.body)
6545 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6546 * @return {HTMLelement}
6548 getTarget : function(selector, maxDepth, returnEl){
6549 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6552 * Gets the related target.
6553 * @return {HTMLElement}
6555 getRelatedTarget : function(){
6556 if(this.browserEvent){
6557 return E.getRelatedTarget(this.browserEvent);
6563 * Normalizes mouse wheel delta across browsers
6564 * @return {Number} The delta
6566 getWheelDelta : function(){
6567 var e = this.browserEvent;
6569 if(e.wheelDelta){ /* IE/Opera. */
6570 delta = e.wheelDelta/120;
6571 }else if(e.detail){ /* Mozilla case. */
6572 delta = -e.detail/3;
6578 * Returns true if the control, meta, shift or alt key was pressed during this event.
6581 hasModifier : function(){
6582 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6586 * Returns true if the target of this event equals el or is a child of el
6587 * @param {String/HTMLElement/Element} el
6588 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6591 within : function(el, related){
6592 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6593 return t && Roo.fly(el).contains(t);
6596 getPoint : function(){
6597 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6601 return new Roo.EventObjectImpl();
6606 * Ext JS Library 1.1.1
6607 * Copyright(c) 2006-2007, Ext JS, LLC.
6609 * Originally Released Under LGPL - original licence link has changed is not relivant.
6612 * <script type="text/javascript">
6616 // was in Composite Element!??!?!
6619 var D = Roo.lib.Dom;
6620 var E = Roo.lib.Event;
6621 var A = Roo.lib.Anim;
6623 // local style camelizing for speed
6625 var camelRe = /(-[a-z])/gi;
6626 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6627 var view = document.defaultView;
6630 * @class Roo.Element
6631 * Represents an Element in the DOM.<br><br>
6634 var el = Roo.get("my-div");
6637 var el = getEl("my-div");
6639 // or with a DOM element
6640 var el = Roo.get(myDivElement);
6642 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6643 * each call instead of constructing a new one.<br><br>
6644 * <b>Animations</b><br />
6645 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6646 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6648 Option Default Description
6649 --------- -------- ---------------------------------------------
6650 duration .35 The duration of the animation in seconds
6651 easing easeOut The YUI easing method
6652 callback none A function to execute when the anim completes
6653 scope this The scope (this) of the callback function
6655 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6656 * manipulate the animation. Here's an example:
6658 var el = Roo.get("my-div");
6663 // default animation
6664 el.setWidth(100, true);
6666 // animation with some options set
6673 // using the "anim" property to get the Anim object
6679 el.setWidth(100, opt);
6681 if(opt.anim.isAnimated()){
6685 * <b> Composite (Collections of) Elements</b><br />
6686 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6687 * @constructor Create a new Element directly.
6688 * @param {String/HTMLElement} element
6689 * @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).
6691 Roo.Element = function(element, forceNew){
6692 var dom = typeof element == "string" ?
6693 document.getElementById(element) : element;
6694 if(!dom){ // invalid id/element
6698 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6699 return Roo.Element.cache[id];
6709 * The DOM element ID
6712 this.id = id || Roo.id(dom);
6715 var El = Roo.Element;
6719 * The element's default display mode (defaults to "")
6722 originalDisplay : "",
6726 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6731 * Sets the element's visibility mode. When setVisible() is called it
6732 * will use this to determine whether to set the visibility or the display property.
6733 * @param visMode Element.VISIBILITY or Element.DISPLAY
6734 * @return {Roo.Element} this
6736 setVisibilityMode : function(visMode){
6737 this.visibilityMode = visMode;
6741 * Convenience method for setVisibilityMode(Element.DISPLAY)
6742 * @param {String} display (optional) What to set display to when visible
6743 * @return {Roo.Element} this
6745 enableDisplayMode : function(display){
6746 this.setVisibilityMode(El.DISPLAY);
6747 if(typeof display != "undefined") this.originalDisplay = display;
6752 * 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)
6753 * @param {String} selector The simple selector to test
6754 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6755 search as a number or element (defaults to 10 || document.body)
6756 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6757 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6759 findParent : function(simpleSelector, maxDepth, returnEl){
6760 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6761 maxDepth = maxDepth || 50;
6762 if(typeof maxDepth != "number"){
6763 stopEl = Roo.getDom(maxDepth);
6766 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6767 if(dq.is(p, simpleSelector)){
6768 return returnEl ? Roo.get(p) : p;
6778 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6779 * @param {String} selector The simple selector to test
6780 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6781 search as a number or element (defaults to 10 || document.body)
6782 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6783 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6785 findParentNode : function(simpleSelector, maxDepth, returnEl){
6786 var p = Roo.fly(this.dom.parentNode, '_internal');
6787 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6791 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6792 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6793 * @param {String} selector The simple selector to test
6794 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6795 search as a number or element (defaults to 10 || document.body)
6796 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6798 up : function(simpleSelector, maxDepth){
6799 return this.findParentNode(simpleSelector, maxDepth, true);
6805 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6806 * @param {String} selector The simple selector to test
6807 * @return {Boolean} True if this element matches the selector, else false
6809 is : function(simpleSelector){
6810 return Roo.DomQuery.is(this.dom, simpleSelector);
6814 * Perform animation on this element.
6815 * @param {Object} args The YUI animation control args
6816 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6817 * @param {Function} onComplete (optional) Function to call when animation completes
6818 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6819 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6820 * @return {Roo.Element} this
6822 animate : function(args, duration, onComplete, easing, animType){
6823 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6828 * @private Internal animation call
6830 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6831 animType = animType || 'run';
6833 var anim = Roo.lib.Anim[animType](
6835 (opt.duration || defaultDur) || .35,
6836 (opt.easing || defaultEase) || 'easeOut',
6838 Roo.callback(cb, this);
6839 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6847 // private legacy anim prep
6848 preanim : function(a, i){
6849 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6853 * Removes worthless text nodes
6854 * @param {Boolean} forceReclean (optional) By default the element
6855 * keeps track if it has been cleaned already so
6856 * you can call this over and over. However, if you update the element and
6857 * need to force a reclean, you can pass true.
6859 clean : function(forceReclean){
6860 if(this.isCleaned && forceReclean !== true){
6864 var d = this.dom, n = d.firstChild, ni = -1;
6866 var nx = n.nextSibling;
6867 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
6874 this.isCleaned = true;
6879 calcOffsetsTo : function(el){
6882 var restorePos = false;
6883 if(el.getStyle('position') == 'static'){
6884 el.position('relative');
6889 while(op && op != d && op.tagName != 'HTML'){
6892 op = op.offsetParent;
6895 el.position('static');
6901 * Scrolls this element into view within the passed container.
6902 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
6903 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
6904 * @return {Roo.Element} this
6906 scrollIntoView : function(container, hscroll){
6907 var c = Roo.getDom(container) || document.body;
6910 var o = this.calcOffsetsTo(c),
6913 b = t+el.offsetHeight,
6914 r = l+el.offsetWidth;
6916 var ch = c.clientHeight;
6917 var ct = parseInt(c.scrollTop, 10);
6918 var cl = parseInt(c.scrollLeft, 10);
6920 var cr = cl + c.clientWidth;
6928 if(hscroll !== false){
6932 c.scrollLeft = r-c.clientWidth;
6939 scrollChildIntoView : function(child, hscroll){
6940 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
6944 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
6945 * the new height may not be available immediately.
6946 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
6947 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
6948 * @param {Function} onComplete (optional) Function to call when animation completes
6949 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
6950 * @return {Roo.Element} this
6952 autoHeight : function(animate, duration, onComplete, easing){
6953 var oldHeight = this.getHeight();
6955 this.setHeight(1); // force clipping
6956 setTimeout(function(){
6957 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
6959 this.setHeight(height);
6961 if(typeof onComplete == "function"){
6965 this.setHeight(oldHeight); // restore original height
6966 this.setHeight(height, animate, duration, function(){
6968 if(typeof onComplete == "function") onComplete();
6969 }.createDelegate(this), easing);
6971 }.createDelegate(this), 0);
6976 * Returns true if this element is an ancestor of the passed element
6977 * @param {HTMLElement/String} el The element to check
6978 * @return {Boolean} True if this element is an ancestor of el, else false
6980 contains : function(el){
6981 if(!el){return false;}
6982 return D.isAncestor(this.dom, el.dom ? el.dom : el);
6986 * Checks whether the element is currently visible using both visibility and display properties.
6987 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
6988 * @return {Boolean} True if the element is currently visible, else false
6990 isVisible : function(deep) {
6991 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
6992 if(deep !== true || !vis){
6995 var p = this.dom.parentNode;
6996 while(p && p.tagName.toLowerCase() != "body"){
6997 if(!Roo.fly(p, '_isVisible').isVisible()){
7006 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7007 * @param {String} selector The CSS selector
7008 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7009 * @return {CompositeElement/CompositeElementLite} The composite element
7011 select : function(selector, unique){
7012 return El.select(selector, unique, this.dom);
7016 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7017 * @param {String} selector The CSS selector
7018 * @return {Array} An array of the matched nodes
7020 query : function(selector, unique){
7021 return Roo.DomQuery.select(selector, this.dom);
7025 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7026 * @param {String} selector The CSS selector
7027 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7028 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7030 child : function(selector, returnDom){
7031 var n = Roo.DomQuery.selectNode(selector, this.dom);
7032 return returnDom ? n : Roo.get(n);
7036 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7037 * @param {String} selector The CSS selector
7038 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7039 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7041 down : function(selector, returnDom){
7042 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7043 return returnDom ? n : Roo.get(n);
7047 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7048 * @param {String} group The group the DD object is member of
7049 * @param {Object} config The DD config object
7050 * @param {Object} overrides An object containing methods to override/implement on the DD object
7051 * @return {Roo.dd.DD} The DD object
7053 initDD : function(group, config, overrides){
7054 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7055 return Roo.apply(dd, overrides);
7059 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7060 * @param {String} group The group the DDProxy object is member of
7061 * @param {Object} config The DDProxy config object
7062 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7063 * @return {Roo.dd.DDProxy} The DDProxy object
7065 initDDProxy : function(group, config, overrides){
7066 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7067 return Roo.apply(dd, overrides);
7071 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7072 * @param {String} group The group the DDTarget object is member of
7073 * @param {Object} config The DDTarget config object
7074 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7075 * @return {Roo.dd.DDTarget} The DDTarget object
7077 initDDTarget : function(group, config, overrides){
7078 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7079 return Roo.apply(dd, overrides);
7083 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7084 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7085 * @param {Boolean} visible Whether the element is visible
7086 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7087 * @return {Roo.Element} this
7089 setVisible : function(visible, animate){
7091 if(this.visibilityMode == El.DISPLAY){
7092 this.setDisplayed(visible);
7095 this.dom.style.visibility = visible ? "visible" : "hidden";
7098 // closure for composites
7100 var visMode = this.visibilityMode;
7102 this.setOpacity(.01);
7103 this.setVisible(true);
7105 this.anim({opacity: { to: (visible?1:0) }},
7106 this.preanim(arguments, 1),
7107 null, .35, 'easeIn', function(){
7109 if(visMode == El.DISPLAY){
7110 dom.style.display = "none";
7112 dom.style.visibility = "hidden";
7114 Roo.get(dom).setOpacity(1);
7122 * Returns true if display is not "none"
7125 isDisplayed : function() {
7126 return this.getStyle("display") != "none";
7130 * Toggles the element's visibility or display, depending on visibility mode.
7131 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7132 * @return {Roo.Element} this
7134 toggle : function(animate){
7135 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7140 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7141 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7142 * @return {Roo.Element} this
7144 setDisplayed : function(value) {
7145 if(typeof value == "boolean"){
7146 value = value ? this.originalDisplay : "none";
7148 this.setStyle("display", value);
7153 * Tries to focus the element. Any exceptions are caught and ignored.
7154 * @return {Roo.Element} this
7156 focus : function() {
7164 * Tries to blur the element. Any exceptions are caught and ignored.
7165 * @return {Roo.Element} this
7175 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7176 * @param {String/Array} className The CSS class to add, or an array of classes
7177 * @return {Roo.Element} this
7179 addClass : function(className){
7180 if(className instanceof Array){
7181 for(var i = 0, len = className.length; i < len; i++) {
7182 this.addClass(className[i]);
7185 if(className && !this.hasClass(className)){
7186 this.dom.className = this.dom.className + " " + className;
7193 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7194 * @param {String/Array} className The CSS class to add, or an array of classes
7195 * @return {Roo.Element} this
7197 radioClass : function(className){
7198 var siblings = this.dom.parentNode.childNodes;
7199 for(var i = 0; i < siblings.length; i++) {
7200 var s = siblings[i];
7201 if(s.nodeType == 1){
7202 Roo.get(s).removeClass(className);
7205 this.addClass(className);
7210 * Removes one or more CSS classes from the element.
7211 * @param {String/Array} className The CSS class to remove, or an array of classes
7212 * @return {Roo.Element} this
7214 removeClass : function(className){
7215 if(!className || !this.dom.className){
7218 if(className instanceof Array){
7219 for(var i = 0, len = className.length; i < len; i++) {
7220 this.removeClass(className[i]);
7223 if(this.hasClass(className)){
7224 var re = this.classReCache[className];
7226 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7227 this.classReCache[className] = re;
7229 this.dom.className =
7230 this.dom.className.replace(re, " ");
7240 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7241 * @param {String} className The CSS class to toggle
7242 * @return {Roo.Element} this
7244 toggleClass : function(className){
7245 if(this.hasClass(className)){
7246 this.removeClass(className);
7248 this.addClass(className);
7254 * Checks if the specified CSS class exists on this element's DOM node.
7255 * @param {String} className The CSS class to check for
7256 * @return {Boolean} True if the class exists, else false
7258 hasClass : function(className){
7259 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7263 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7264 * @param {String} oldClassName The CSS class to replace
7265 * @param {String} newClassName The replacement CSS class
7266 * @return {Roo.Element} this
7268 replaceClass : function(oldClassName, newClassName){
7269 this.removeClass(oldClassName);
7270 this.addClass(newClassName);
7275 * Returns an object with properties matching the styles requested.
7276 * For example, el.getStyles('color', 'font-size', 'width') might return
7277 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7278 * @param {String} style1 A style name
7279 * @param {String} style2 A style name
7280 * @param {String} etc.
7281 * @return {Object} The style object
7283 getStyles : function(){
7284 var a = arguments, len = a.length, r = {};
7285 for(var i = 0; i < len; i++){
7286 r[a[i]] = this.getStyle(a[i]);
7292 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7293 * @param {String} property The style property whose value is returned.
7294 * @return {String} The current value of the style property for this element.
7296 getStyle : function(){
7297 return view && view.getComputedStyle ?
7299 var el = this.dom, v, cs, camel;
7300 if(prop == 'float'){
7303 if(el.style && (v = el.style[prop])){
7306 if(cs = view.getComputedStyle(el, "")){
7307 if(!(camel = propCache[prop])){
7308 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7315 var el = this.dom, v, cs, camel;
7316 if(prop == 'opacity'){
7317 if(typeof el.style.filter == 'string'){
7318 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7320 var fv = parseFloat(m[1]);
7322 return fv ? fv / 100 : 0;
7327 }else if(prop == 'float'){
7328 prop = "styleFloat";
7330 if(!(camel = propCache[prop])){
7331 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7333 if(v = el.style[camel]){
7336 if(cs = el.currentStyle){
7344 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7345 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7346 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7347 * @return {Roo.Element} this
7349 setStyle : function(prop, value){
7350 if(typeof prop == "string"){
7352 if(!(camel = propCache[prop])){
7353 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7355 if(camel == 'opacity') {
7356 this.setOpacity(value);
7358 this.dom.style[camel] = value;
7361 for(var style in prop){
7362 if(typeof prop[style] != "function"){
7363 this.setStyle(style, prop[style]);
7371 * More flexible version of {@link #setStyle} for setting style properties.
7372 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7373 * a function which returns such a specification.
7374 * @return {Roo.Element} this
7376 applyStyles : function(style){
7377 Roo.DomHelper.applyStyles(this.dom, style);
7382 * 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).
7383 * @return {Number} The X position of the element
7386 return D.getX(this.dom);
7390 * 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).
7391 * @return {Number} The Y position of the element
7394 return D.getY(this.dom);
7398 * 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).
7399 * @return {Array} The XY position of the element
7402 return D.getXY(this.dom);
7406 * 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).
7407 * @param {Number} The X position of the element
7408 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7409 * @return {Roo.Element} this
7411 setX : function(x, animate){
7413 D.setX(this.dom, x);
7415 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7421 * 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).
7422 * @param {Number} The Y position of the element
7423 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7424 * @return {Roo.Element} this
7426 setY : function(y, animate){
7428 D.setY(this.dom, y);
7430 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7436 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7437 * @param {String} left The left CSS property value
7438 * @return {Roo.Element} this
7440 setLeft : function(left){
7441 this.setStyle("left", this.addUnits(left));
7446 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7447 * @param {String} top The top CSS property value
7448 * @return {Roo.Element} this
7450 setTop : function(top){
7451 this.setStyle("top", this.addUnits(top));
7456 * Sets the element's CSS right style.
7457 * @param {String} right The right CSS property value
7458 * @return {Roo.Element} this
7460 setRight : function(right){
7461 this.setStyle("right", this.addUnits(right));
7466 * Sets the element's CSS bottom style.
7467 * @param {String} bottom The bottom CSS property value
7468 * @return {Roo.Element} this
7470 setBottom : function(bottom){
7471 this.setStyle("bottom", this.addUnits(bottom));
7476 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7477 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7478 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7479 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7480 * @return {Roo.Element} this
7482 setXY : function(pos, animate){
7484 D.setXY(this.dom, pos);
7486 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7492 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7493 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7494 * @param {Number} x X value for new position (coordinates are page-based)
7495 * @param {Number} y Y value for new position (coordinates are page-based)
7496 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7497 * @return {Roo.Element} this
7499 setLocation : function(x, y, animate){
7500 this.setXY([x, y], this.preanim(arguments, 2));
7505 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7506 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7507 * @param {Number} x X value for new position (coordinates are page-based)
7508 * @param {Number} y Y value for new position (coordinates are page-based)
7509 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7510 * @return {Roo.Element} this
7512 moveTo : function(x, y, animate){
7513 this.setXY([x, y], this.preanim(arguments, 2));
7518 * Returns the region of the given element.
7519 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7520 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7522 getRegion : function(){
7523 return D.getRegion(this.dom);
7527 * Returns the offset height of the element
7528 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7529 * @return {Number} The element's height
7531 getHeight : function(contentHeight){
7532 var h = this.dom.offsetHeight || 0;
7533 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7537 * Returns the offset width of the element
7538 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7539 * @return {Number} The element's width
7541 getWidth : function(contentWidth){
7542 var w = this.dom.offsetWidth || 0;
7543 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7547 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7548 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7549 * if a height has not been set using CSS.
7552 getComputedHeight : function(){
7553 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7555 h = parseInt(this.getStyle('height'), 10) || 0;
7556 if(!this.isBorderBox()){
7557 h += this.getFrameWidth('tb');
7564 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7565 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7566 * if a width has not been set using CSS.
7569 getComputedWidth : function(){
7570 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7572 w = parseInt(this.getStyle('width'), 10) || 0;
7573 if(!this.isBorderBox()){
7574 w += this.getFrameWidth('lr');
7581 * Returns the size of the element.
7582 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7583 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7585 getSize : function(contentSize){
7586 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7590 * Returns the width and height of the viewport.
7591 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7593 getViewSize : function(){
7594 var d = this.dom, doc = document, aw = 0, ah = 0;
7595 if(d == doc || d == doc.body){
7596 return {width : D.getViewWidth(), height: D.getViewHeight()};
7599 width : d.clientWidth,
7600 height: d.clientHeight
7606 * Returns the value of the "value" attribute
7607 * @param {Boolean} asNumber true to parse the value as a number
7608 * @return {String/Number}
7610 getValue : function(asNumber){
7611 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7615 adjustWidth : function(width){
7616 if(typeof width == "number"){
7617 if(this.autoBoxAdjust && !this.isBorderBox()){
7618 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7628 adjustHeight : function(height){
7629 if(typeof height == "number"){
7630 if(this.autoBoxAdjust && !this.isBorderBox()){
7631 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7641 * Set the width of the element
7642 * @param {Number} width The new width
7643 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7644 * @return {Roo.Element} this
7646 setWidth : function(width, animate){
7647 width = this.adjustWidth(width);
7649 this.dom.style.width = this.addUnits(width);
7651 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7657 * Set the height of the element
7658 * @param {Number} height The new height
7659 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7660 * @return {Roo.Element} this
7662 setHeight : function(height, animate){
7663 height = this.adjustHeight(height);
7665 this.dom.style.height = this.addUnits(height);
7667 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7673 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7674 * @param {Number} width The new width
7675 * @param {Number} height The new height
7676 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7677 * @return {Roo.Element} this
7679 setSize : function(width, height, animate){
7680 if(typeof width == "object"){ // in case of object from getSize()
7681 height = width.height; width = width.width;
7683 width = this.adjustWidth(width); height = this.adjustHeight(height);
7685 this.dom.style.width = this.addUnits(width);
7686 this.dom.style.height = this.addUnits(height);
7688 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7694 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7695 * @param {Number} x X value for new position (coordinates are page-based)
7696 * @param {Number} y Y value for new position (coordinates are page-based)
7697 * @param {Number} width The new width
7698 * @param {Number} height The new height
7699 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7700 * @return {Roo.Element} this
7702 setBounds : function(x, y, width, height, animate){
7704 this.setSize(width, height);
7705 this.setLocation(x, y);
7707 width = this.adjustWidth(width); height = this.adjustHeight(height);
7708 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7709 this.preanim(arguments, 4), 'motion');
7715 * 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.
7716 * @param {Roo.lib.Region} region The region to fill
7717 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7718 * @return {Roo.Element} this
7720 setRegion : function(region, animate){
7721 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7726 * Appends an event handler
7728 * @param {String} eventName The type of event to append
7729 * @param {Function} fn The method the event invokes
7730 * @param {Object} scope (optional) The scope (this object) of the fn
7731 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7733 addListener : function(eventName, fn, scope, options){
7734 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7738 * Removes an event handler from this element
7739 * @param {String} eventName the type of event to remove
7740 * @param {Function} fn the method the event invokes
7741 * @return {Roo.Element} this
7743 removeListener : function(eventName, fn){
7744 Roo.EventManager.removeListener(this.dom, eventName, fn);
7749 * Removes all previous added listeners from this element
7750 * @return {Roo.Element} this
7752 removeAllListeners : function(){
7753 E.purgeElement(this.dom);
7757 relayEvent : function(eventName, observable){
7758 this.on(eventName, function(e){
7759 observable.fireEvent(eventName, e);
7764 * Set the opacity of the element
7765 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7766 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7767 * @return {Roo.Element} this
7769 setOpacity : function(opacity, animate){
7771 var s = this.dom.style;
7774 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7775 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7777 s.opacity = opacity;
7780 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7786 * Gets the left X coordinate
7787 * @param {Boolean} local True to get the local css position instead of page coordinate
7790 getLeft : function(local){
7794 return parseInt(this.getStyle("left"), 10) || 0;
7799 * Gets the right X coordinate of the element (element X position + element width)
7800 * @param {Boolean} local True to get the local css position instead of page coordinate
7803 getRight : function(local){
7805 return this.getX() + this.getWidth();
7807 return (this.getLeft(true) + this.getWidth()) || 0;
7812 * Gets the top Y coordinate
7813 * @param {Boolean} local True to get the local css position instead of page coordinate
7816 getTop : function(local) {
7820 return parseInt(this.getStyle("top"), 10) || 0;
7825 * Gets the bottom Y coordinate of the element (element Y position + element height)
7826 * @param {Boolean} local True to get the local css position instead of page coordinate
7829 getBottom : function(local){
7831 return this.getY() + this.getHeight();
7833 return (this.getTop(true) + this.getHeight()) || 0;
7838 * Initializes positioning on this element. If a desired position is not passed, it will make the
7839 * the element positioned relative IF it is not already positioned.
7840 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7841 * @param {Number} zIndex (optional) The zIndex to apply
7842 * @param {Number} x (optional) Set the page X position
7843 * @param {Number} y (optional) Set the page Y position
7845 position : function(pos, zIndex, x, y){
7847 if(this.getStyle('position') == 'static'){
7848 this.setStyle('position', 'relative');
7851 this.setStyle("position", pos);
7854 this.setStyle("z-index", zIndex);
7856 if(x !== undefined && y !== undefined){
7858 }else if(x !== undefined){
7860 }else if(y !== undefined){
7866 * Clear positioning back to the default when the document was loaded
7867 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7868 * @return {Roo.Element} this
7870 clearPositioning : function(value){
7878 "position" : "static"
7884 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7885 * snapshot before performing an update and then restoring the element.
7888 getPositioning : function(){
7889 var l = this.getStyle("left");
7890 var t = this.getStyle("top");
7892 "position" : this.getStyle("position"),
7894 "right" : l ? "" : this.getStyle("right"),
7896 "bottom" : t ? "" : this.getStyle("bottom"),
7897 "z-index" : this.getStyle("z-index")
7902 * Gets the width of the border(s) for the specified side(s)
7903 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7904 * passing lr would get the border (l)eft width + the border (r)ight width.
7905 * @return {Number} The width of the sides passed added together
7907 getBorderWidth : function(side){
7908 return this.addStyles(side, El.borders);
7912 * Gets the width of the padding(s) for the specified side(s)
7913 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7914 * passing lr would get the padding (l)eft + the padding (r)ight.
7915 * @return {Number} The padding of the sides passed added together
7917 getPadding : function(side){
7918 return this.addStyles(side, El.paddings);
7922 * Set positioning with an object returned by getPositioning().
7923 * @param {Object} posCfg
7924 * @return {Roo.Element} this
7926 setPositioning : function(pc){
7927 this.applyStyles(pc);
7928 if(pc.right == "auto"){
7929 this.dom.style.right = "";
7931 if(pc.bottom == "auto"){
7932 this.dom.style.bottom = "";
7938 fixDisplay : function(){
7939 if(this.getStyle("display") == "none"){
7940 this.setStyle("visibility", "hidden");
7941 this.setStyle("display", this.originalDisplay); // first try reverting to default
7942 if(this.getStyle("display") == "none"){ // if that fails, default to block
7943 this.setStyle("display", "block");
7949 * Quick set left and top adding default units
7950 * @param {String} left The left CSS property value
7951 * @param {String} top The top CSS property value
7952 * @return {Roo.Element} this
7954 setLeftTop : function(left, top){
7955 this.dom.style.left = this.addUnits(left);
7956 this.dom.style.top = this.addUnits(top);
7961 * Move this element relative to its current position.
7962 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
7963 * @param {Number} distance How far to move the element in pixels
7964 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7965 * @return {Roo.Element} this
7967 move : function(direction, distance, animate){
7968 var xy = this.getXY();
7969 direction = direction.toLowerCase();
7973 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
7977 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
7982 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
7987 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
7994 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
7995 * @return {Roo.Element} this
7998 if(!this.isClipped){
7999 this.isClipped = true;
8000 this.originalClip = {
8001 "o": this.getStyle("overflow"),
8002 "x": this.getStyle("overflow-x"),
8003 "y": this.getStyle("overflow-y")
8005 this.setStyle("overflow", "hidden");
8006 this.setStyle("overflow-x", "hidden");
8007 this.setStyle("overflow-y", "hidden");
8013 * Return clipping (overflow) to original clipping before clip() was called
8014 * @return {Roo.Element} this
8016 unclip : function(){
8018 this.isClipped = false;
8019 var o = this.originalClip;
8020 if(o.o){this.setStyle("overflow", o.o);}
8021 if(o.x){this.setStyle("overflow-x", o.x);}
8022 if(o.y){this.setStyle("overflow-y", o.y);}
8029 * Gets the x,y coordinates specified by the anchor position on the element.
8030 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8031 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8032 * {width: (target width), height: (target height)} (defaults to the element's current size)
8033 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8034 * @return {Array} [x, y] An array containing the element's x and y coordinates
8036 getAnchorXY : function(anchor, local, s){
8037 //Passing a different size is useful for pre-calculating anchors,
8038 //especially for anchored animations that change the el size.
8040 var w, h, vp = false;
8043 if(d == document.body || d == document){
8045 w = D.getViewWidth(); h = D.getViewHeight();
8047 w = this.getWidth(); h = this.getHeight();
8050 w = s.width; h = s.height;
8052 var x = 0, y = 0, r = Math.round;
8053 switch((anchor || "tl").toLowerCase()){
8095 var sc = this.getScroll();
8096 return [x + sc.left, y + sc.top];
8098 //Add the element's offset xy
8099 var o = this.getXY();
8100 return [x+o[0], y+o[1]];
8104 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8105 * supported position values.
8106 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8107 * @param {String} position The position to align to.
8108 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8109 * @return {Array} [x, y]
8111 getAlignToXY : function(el, p, o){
8115 throw "Element.alignTo with an element that doesn't exist";
8117 var c = false; //constrain to viewport
8118 var p1 = "", p2 = "";
8125 }else if(p.indexOf("-") == -1){
8128 p = p.toLowerCase();
8129 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8131 throw "Element.alignTo with an invalid alignment " + p;
8133 p1 = m[1]; p2 = m[2]; c = !!m[3];
8135 //Subtract the aligned el's internal xy from the target's offset xy
8136 //plus custom offset to get the aligned el's new offset xy
8137 var a1 = this.getAnchorXY(p1, true);
8138 var a2 = el.getAnchorXY(p2, false);
8139 var x = a2[0] - a1[0] + o[0];
8140 var y = a2[1] - a1[1] + o[1];
8142 //constrain the aligned el to viewport if necessary
8143 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8144 // 5px of margin for ie
8145 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8147 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8148 //perpendicular to the vp border, allow the aligned el to slide on that border,
8149 //otherwise swap the aligned el to the opposite border of the target.
8150 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8151 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8152 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8153 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8156 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8157 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8159 if((x+w) > dw + scrollX){
8160 x = swapX ? r.left-w : dw+scrollX-w;
8163 x = swapX ? r.right : scrollX;
8165 if((y+h) > dh + scrollY){
8166 y = swapY ? r.top-h : dh+scrollY-h;
8169 y = swapY ? r.bottom : scrollY;
8176 getConstrainToXY : function(){
8177 var os = {top:0, left:0, bottom:0, right: 0};
8179 return function(el, local, offsets, proposedXY){
8181 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8183 var vw, vh, vx = 0, vy = 0;
8184 if(el.dom == document.body || el.dom == document){
8185 vw = Roo.lib.Dom.getViewWidth();
8186 vh = Roo.lib.Dom.getViewHeight();
8188 vw = el.dom.clientWidth;
8189 vh = el.dom.clientHeight;
8191 var vxy = el.getXY();
8197 var s = el.getScroll();
8199 vx += offsets.left + s.left;
8200 vy += offsets.top + s.top;
8202 vw -= offsets.right;
8203 vh -= offsets.bottom;
8208 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8209 var x = xy[0], y = xy[1];
8210 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8212 // only move it if it needs it
8215 // first validate right/bottom
8224 // then make sure top/left isn't negative
8233 return moved ? [x, y] : false;
8238 adjustForConstraints : function(xy, parent, offsets){
8239 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8243 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8244 * document it aligns it to the viewport.
8245 * The position parameter is optional, and can be specified in any one of the following formats:
8247 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8248 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8249 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8250 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8251 * <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
8252 * element's anchor point, and the second value is used as the target's anchor point.</li>
8254 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8255 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8256 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8257 * that specified in order to enforce the viewport constraints.
8258 * Following are all of the supported anchor positions:
8261 ----- -----------------------------
8262 tl The top left corner (default)
8263 t The center of the top edge
8264 tr The top right corner
8265 l The center of the left edge
8266 c In the center of the element
8267 r The center of the right edge
8268 bl The bottom left corner
8269 b The center of the bottom edge
8270 br The bottom right corner
8274 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8275 el.alignTo("other-el");
8277 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8278 el.alignTo("other-el", "tr?");
8280 // align the bottom right corner of el with the center left edge of other-el
8281 el.alignTo("other-el", "br-l?");
8283 // align the center of el with the bottom left corner of other-el and
8284 // adjust the x position by -6 pixels (and the y position by 0)
8285 el.alignTo("other-el", "c-bl", [-6, 0]);
8287 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8288 * @param {String} position The position to align to.
8289 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8290 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8291 * @return {Roo.Element} this
8293 alignTo : function(element, position, offsets, animate){
8294 var xy = this.getAlignToXY(element, position, offsets);
8295 this.setXY(xy, this.preanim(arguments, 3));
8300 * Anchors an element to another element and realigns it when the window is resized.
8301 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8302 * @param {String} position The position to align to.
8303 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8304 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8305 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8306 * is a number, it is used as the buffer delay (defaults to 50ms).
8307 * @param {Function} callback The function to call after the animation finishes
8308 * @return {Roo.Element} this
8310 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8311 var action = function(){
8312 this.alignTo(el, alignment, offsets, animate);
8313 Roo.callback(callback, this);
8315 Roo.EventManager.onWindowResize(action, this);
8316 var tm = typeof monitorScroll;
8317 if(tm != 'undefined'){
8318 Roo.EventManager.on(window, 'scroll', action, this,
8319 {buffer: tm == 'number' ? monitorScroll : 50});
8321 action.call(this); // align immediately
8325 * Clears any opacity settings from this element. Required in some cases for IE.
8326 * @return {Roo.Element} this
8328 clearOpacity : function(){
8329 if (window.ActiveXObject) {
8330 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8331 this.dom.style.filter = "";
8334 this.dom.style.opacity = "";
8335 this.dom.style["-moz-opacity"] = "";
8336 this.dom.style["-khtml-opacity"] = "";
8342 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8343 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8344 * @return {Roo.Element} this
8346 hide : function(animate){
8347 this.setVisible(false, this.preanim(arguments, 0));
8352 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8353 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8354 * @return {Roo.Element} this
8356 show : function(animate){
8357 this.setVisible(true, this.preanim(arguments, 0));
8362 * @private Test if size has a unit, otherwise appends the default
8364 addUnits : function(size){
8365 return Roo.Element.addUnits(size, this.defaultUnit);
8369 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8370 * @return {Roo.Element} this
8372 beginMeasure : function(){
8374 if(el.offsetWidth || el.offsetHeight){
8375 return this; // offsets work already
8378 var p = this.dom, b = document.body; // start with this element
8379 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8380 var pe = Roo.get(p);
8381 if(pe.getStyle('display') == 'none'){
8382 changed.push({el: p, visibility: pe.getStyle("visibility")});
8383 p.style.visibility = "hidden";
8384 p.style.display = "block";
8388 this._measureChanged = changed;
8394 * Restores displays to before beginMeasure was called
8395 * @return {Roo.Element} this
8397 endMeasure : function(){
8398 var changed = this._measureChanged;
8400 for(var i = 0, len = changed.length; i < len; i++) {
8402 r.el.style.visibility = r.visibility;
8403 r.el.style.display = "none";
8405 this._measureChanged = null;
8411 * Update the innerHTML of this element, optionally searching for and processing scripts
8412 * @param {String} html The new HTML
8413 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8414 * @param {Function} callback For async script loading you can be noticed when the update completes
8415 * @return {Roo.Element} this
8417 update : function(html, loadScripts, callback){
8418 if(typeof html == "undefined"){
8421 if(loadScripts !== true){
8422 this.dom.innerHTML = html;
8423 if(typeof callback == "function"){
8431 html += '<span id="' + id + '"></span>';
8433 E.onAvailable(id, function(){
8434 var hd = document.getElementsByTagName("head")[0];
8435 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8436 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8437 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8440 while(match = re.exec(html)){
8441 var attrs = match[1];
8442 var srcMatch = attrs ? attrs.match(srcRe) : false;
8443 if(srcMatch && srcMatch[2]){
8444 var s = document.createElement("script");
8445 s.src = srcMatch[2];
8446 var typeMatch = attrs.match(typeRe);
8447 if(typeMatch && typeMatch[2]){
8448 s.type = typeMatch[2];
8451 }else if(match[2] && match[2].length > 0){
8452 if(window.execScript) {
8453 window.execScript(match[2]);
8461 window.eval(match[2]);
8465 var el = document.getElementById(id);
8466 if(el){el.parentNode.removeChild(el);}
8467 if(typeof callback == "function"){
8471 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8476 * Direct access to the UpdateManager update() method (takes the same parameters).
8477 * @param {String/Function} url The url for this request or a function to call to get the url
8478 * @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}
8479 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8480 * @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.
8481 * @return {Roo.Element} this
8484 var um = this.getUpdateManager();
8485 um.update.apply(um, arguments);
8490 * Gets this element's UpdateManager
8491 * @return {Roo.UpdateManager} The UpdateManager
8493 getUpdateManager : function(){
8494 if(!this.updateManager){
8495 this.updateManager = new Roo.UpdateManager(this);
8497 return this.updateManager;
8501 * Disables text selection for this element (normalized across browsers)
8502 * @return {Roo.Element} this
8504 unselectable : function(){
8505 this.dom.unselectable = "on";
8506 this.swallowEvent("selectstart", true);
8507 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8508 this.addClass("x-unselectable");
8513 * Calculates the x, y to center this element on the screen
8514 * @return {Array} The x, y values [x, y]
8516 getCenterXY : function(){
8517 return this.getAlignToXY(document, 'c-c');
8521 * Centers the Element in either the viewport, or another Element.
8522 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8524 center : function(centerIn){
8525 this.alignTo(centerIn || document, 'c-c');
8530 * Tests various css rules/browsers to determine if this element uses a border box
8533 isBorderBox : function(){
8534 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8538 * Return a box {x, y, width, height} that can be used to set another elements
8539 * size/location to match this element.
8540 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8541 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8542 * @return {Object} box An object in the format {x, y, width, height}
8544 getBox : function(contentBox, local){
8549 var left = parseInt(this.getStyle("left"), 10) || 0;
8550 var top = parseInt(this.getStyle("top"), 10) || 0;
8553 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8555 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8557 var l = this.getBorderWidth("l")+this.getPadding("l");
8558 var r = this.getBorderWidth("r")+this.getPadding("r");
8559 var t = this.getBorderWidth("t")+this.getPadding("t");
8560 var b = this.getBorderWidth("b")+this.getPadding("b");
8561 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)};
8563 bx.right = bx.x + bx.width;
8564 bx.bottom = bx.y + bx.height;
8569 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8570 for more information about the sides.
8571 * @param {String} sides
8574 getFrameWidth : function(sides, onlyContentBox){
8575 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8579 * 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.
8580 * @param {Object} box The box to fill {x, y, width, height}
8581 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8582 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8583 * @return {Roo.Element} this
8585 setBox : function(box, adjust, animate){
8586 var w = box.width, h = box.height;
8587 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8588 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8589 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8591 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8596 * Forces the browser to repaint this element
8597 * @return {Roo.Element} this
8599 repaint : function(){
8601 this.addClass("x-repaint");
8602 setTimeout(function(){
8603 Roo.get(dom).removeClass("x-repaint");
8609 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8610 * then it returns the calculated width of the sides (see getPadding)
8611 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8612 * @return {Object/Number}
8614 getMargins : function(side){
8617 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8618 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8619 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8620 right: parseInt(this.getStyle("margin-right"), 10) || 0
8623 return this.addStyles(side, El.margins);
8628 addStyles : function(sides, styles){
8630 for(var i = 0, len = sides.length; i < len; i++){
8631 v = this.getStyle(styles[sides.charAt(i)]);
8633 w = parseInt(v, 10);
8641 * Creates a proxy element of this element
8642 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8643 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8644 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8645 * @return {Roo.Element} The new proxy element
8647 createProxy : function(config, renderTo, matchBox){
8649 renderTo = Roo.getDom(renderTo);
8651 renderTo = document.body;
8653 config = typeof config == "object" ?
8654 config : {tag : "div", cls: config};
8655 var proxy = Roo.DomHelper.append(renderTo, config, true);
8657 proxy.setBox(this.getBox());
8663 * Puts a mask over this element to disable user interaction. Requires core.css.
8664 * This method can only be applied to elements which accept child nodes.
8665 * @param {String} msg (optional) A message to display in the mask
8666 * @param {String} msgCls (optional) A css class to apply to the msg element
8667 * @return {Element} The mask element
8669 mask : function(msg, msgCls){
8670 if(this.getStyle("position") == "static"){
8671 this.setStyle("position", "relative");
8674 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8676 this.addClass("x-masked");
8677 this._mask.setDisplayed(true);
8678 if(typeof msg == 'string'){
8680 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8682 var mm = this._maskMsg;
8683 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8684 mm.dom.firstChild.innerHTML = msg;
8685 mm.setDisplayed(true);
8688 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8689 this._mask.setHeight(this.getHeight());
8695 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8696 * it is cached for reuse.
8698 unmask : function(removeEl){
8700 if(removeEl === true){
8701 this._mask.remove();
8704 this._maskMsg.remove();
8705 delete this._maskMsg;
8708 this._mask.setDisplayed(false);
8710 this._maskMsg.setDisplayed(false);
8714 this.removeClass("x-masked");
8718 * Returns true if this element is masked
8721 isMasked : function(){
8722 return this._mask && this._mask.isVisible();
8726 * Creates an iframe shim for this element to keep selects and other windowed objects from
8728 * @return {Roo.Element} The new shim element
8730 createShim : function(){
8731 var el = document.createElement('iframe');
8732 el.frameBorder = 'no';
8733 el.className = 'roo-shim';
8734 if(Roo.isIE && Roo.isSecure){
8735 el.src = Roo.SSL_SECURE_URL;
8737 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8738 shim.autoBoxAdjust = false;
8743 * Removes this element from the DOM and deletes it from the cache
8745 remove : function(){
8746 if(this.dom.parentNode){
8747 this.dom.parentNode.removeChild(this.dom);
8749 delete El.cache[this.dom.id];
8753 * Sets up event handlers to add and remove a css class when the mouse is over this element
8754 * @param {String} className
8755 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8756 * mouseout events for children elements
8757 * @return {Roo.Element} this
8759 addClassOnOver : function(className, preventFlicker){
8760 this.on("mouseover", function(){
8761 Roo.fly(this, '_internal').addClass(className);
8763 var removeFn = function(e){
8764 if(preventFlicker !== true || !e.within(this, true)){
8765 Roo.fly(this, '_internal').removeClass(className);
8768 this.on("mouseout", removeFn, this.dom);
8773 * Sets up event handlers to add and remove a css class when this element has the focus
8774 * @param {String} className
8775 * @return {Roo.Element} this
8777 addClassOnFocus : function(className){
8778 this.on("focus", function(){
8779 Roo.fly(this, '_internal').addClass(className);
8781 this.on("blur", function(){
8782 Roo.fly(this, '_internal').removeClass(className);
8787 * 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)
8788 * @param {String} className
8789 * @return {Roo.Element} this
8791 addClassOnClick : function(className){
8793 this.on("mousedown", function(){
8794 Roo.fly(dom, '_internal').addClass(className);
8795 var d = Roo.get(document);
8796 var fn = function(){
8797 Roo.fly(dom, '_internal').removeClass(className);
8798 d.removeListener("mouseup", fn);
8800 d.on("mouseup", fn);
8806 * Stops the specified event from bubbling and optionally prevents the default action
8807 * @param {String} eventName
8808 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8809 * @return {Roo.Element} this
8811 swallowEvent : function(eventName, preventDefault){
8812 var fn = function(e){
8813 e.stopPropagation();
8818 if(eventName instanceof Array){
8819 for(var i = 0, len = eventName.length; i < len; i++){
8820 this.on(eventName[i], fn);
8824 this.on(eventName, fn);
8831 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8834 * Sizes this element to its parent element's dimensions performing
8835 * neccessary box adjustments.
8836 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8837 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8838 * @return {Roo.Element} this
8840 fitToParent : function(monitorResize, targetParent) {
8841 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8842 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8843 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8846 var p = Roo.get(targetParent || this.dom.parentNode);
8847 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8848 if (monitorResize === true) {
8849 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8850 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8856 * Gets the next sibling, skipping text nodes
8857 * @return {HTMLElement} The next sibling or null
8859 getNextSibling : function(){
8860 var n = this.dom.nextSibling;
8861 while(n && n.nodeType != 1){
8868 * Gets the previous sibling, skipping text nodes
8869 * @return {HTMLElement} The previous sibling or null
8871 getPrevSibling : function(){
8872 var n = this.dom.previousSibling;
8873 while(n && n.nodeType != 1){
8874 n = n.previousSibling;
8881 * Appends the passed element(s) to this element
8882 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8883 * @return {Roo.Element} this
8885 appendChild: function(el){
8892 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8893 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8894 * automatically generated with the specified attributes.
8895 * @param {HTMLElement} insertBefore (optional) a child element of this element
8896 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8897 * @return {Roo.Element} The new child element
8899 createChild: function(config, insertBefore, returnDom){
8900 config = config || {tag:'div'};
8902 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8904 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8908 * Appends this element to the passed element
8909 * @param {String/HTMLElement/Element} el The new parent element
8910 * @return {Roo.Element} this
8912 appendTo: function(el){
8913 el = Roo.getDom(el);
8914 el.appendChild(this.dom);
8919 * Inserts this element before the passed element in the DOM
8920 * @param {String/HTMLElement/Element} el The element to insert before
8921 * @return {Roo.Element} this
8923 insertBefore: function(el){
8924 el = Roo.getDom(el);
8925 el.parentNode.insertBefore(this.dom, el);
8930 * Inserts this element after the passed element in the DOM
8931 * @param {String/HTMLElement/Element} el The element to insert after
8932 * @return {Roo.Element} this
8934 insertAfter: function(el){
8935 el = Roo.getDom(el);
8936 el.parentNode.insertBefore(this.dom, el.nextSibling);
8941 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
8942 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8943 * @return {Roo.Element} The new child
8945 insertFirst: function(el, returnDom){
8947 if(typeof el == 'object' && !el.nodeType){ // dh config
8948 return this.createChild(el, this.dom.firstChild, returnDom);
8950 el = Roo.getDom(el);
8951 this.dom.insertBefore(el, this.dom.firstChild);
8952 return !returnDom ? Roo.get(el) : el;
8957 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
8958 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8959 * @param {String} where (optional) 'before' or 'after' defaults to before
8960 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8961 * @return {Roo.Element} the inserted Element
8963 insertSibling: function(el, where, returnDom){
8964 where = where ? where.toLowerCase() : 'before';
8966 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
8968 if(typeof el == 'object' && !el.nodeType){ // dh config
8969 if(where == 'after' && !this.dom.nextSibling){
8970 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
8972 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
8976 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
8977 where == 'before' ? this.dom : this.dom.nextSibling);
8986 * Creates and wraps this element with another element
8987 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
8988 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8989 * @return {HTMLElement/Element} The newly created wrapper element
8991 wrap: function(config, returnDom){
8993 config = {tag: "div"};
8995 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
8996 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9001 * Replaces the passed element with this element
9002 * @param {String/HTMLElement/Element} el The element to replace
9003 * @return {Roo.Element} this
9005 replace: function(el){
9007 this.insertBefore(el);
9013 * Inserts an html fragment into this element
9014 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9015 * @param {String} html The HTML fragment
9016 * @param {Boolean} returnEl True to return an Roo.Element
9017 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9019 insertHtml : function(where, html, returnEl){
9020 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9021 return returnEl ? Roo.get(el) : el;
9025 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9026 * @param {Object} o The object with the attributes
9027 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9028 * @return {Roo.Element} this
9030 set : function(o, useSet){
9032 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9034 if(attr == "style" || typeof o[attr] == "function") continue;
9036 el.className = o["cls"];
9038 if(useSet) el.setAttribute(attr, o[attr]);
9039 else el[attr] = o[attr];
9043 Roo.DomHelper.applyStyles(el, o.style);
9049 * Convenience method for constructing a KeyMap
9050 * @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:
9051 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9052 * @param {Function} fn The function to call
9053 * @param {Object} scope (optional) The scope of the function
9054 * @return {Roo.KeyMap} The KeyMap created
9056 addKeyListener : function(key, fn, scope){
9058 if(typeof key != "object" || key instanceof Array){
9074 return new Roo.KeyMap(this, config);
9078 * Creates a KeyMap for this element
9079 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9080 * @return {Roo.KeyMap} The KeyMap created
9082 addKeyMap : function(config){
9083 return new Roo.KeyMap(this, config);
9087 * Returns true if this element is scrollable.
9090 isScrollable : function(){
9092 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9096 * 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().
9097 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9098 * @param {Number} value The new scroll value
9099 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9100 * @return {Element} this
9103 scrollTo : function(side, value, animate){
9104 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9106 this.dom[prop] = value;
9108 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9109 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9115 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9116 * within this element's scrollable range.
9117 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9118 * @param {Number} distance How far to scroll the element in pixels
9119 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9120 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9121 * was scrolled as far as it could go.
9123 scroll : function(direction, distance, animate){
9124 if(!this.isScrollable()){
9128 var l = el.scrollLeft, t = el.scrollTop;
9129 var w = el.scrollWidth, h = el.scrollHeight;
9130 var cw = el.clientWidth, ch = el.clientHeight;
9131 direction = direction.toLowerCase();
9132 var scrolled = false;
9133 var a = this.preanim(arguments, 2);
9138 var v = Math.min(l + distance, w-cw);
9139 this.scrollTo("left", v, a);
9146 var v = Math.max(l - distance, 0);
9147 this.scrollTo("left", v, a);
9155 var v = Math.max(t - distance, 0);
9156 this.scrollTo("top", v, a);
9164 var v = Math.min(t + distance, h-ch);
9165 this.scrollTo("top", v, a);
9174 * Translates the passed page coordinates into left/top css values for this element
9175 * @param {Number/Array} x The page x or an array containing [x, y]
9176 * @param {Number} y The page y
9177 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9179 translatePoints : function(x, y){
9180 if(typeof x == 'object' || x instanceof Array){
9183 var p = this.getStyle('position');
9184 var o = this.getXY();
9186 var l = parseInt(this.getStyle('left'), 10);
9187 var t = parseInt(this.getStyle('top'), 10);
9190 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9193 t = (p == "relative") ? 0 : this.dom.offsetTop;
9196 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9200 * Returns the current scroll position of the element.
9201 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9203 getScroll : function(){
9204 var d = this.dom, doc = document;
9205 if(d == doc || d == doc.body){
9206 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9207 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9208 return {left: l, top: t};
9210 return {left: d.scrollLeft, top: d.scrollTop};
9215 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9216 * are convert to standard 6 digit hex color.
9217 * @param {String} attr The css attribute
9218 * @param {String} defaultValue The default value to use when a valid color isn't found
9219 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9222 getColor : function(attr, defaultValue, prefix){
9223 var v = this.getStyle(attr);
9224 if(!v || v == "transparent" || v == "inherit") {
9225 return defaultValue;
9227 var color = typeof prefix == "undefined" ? "#" : prefix;
9228 if(v.substr(0, 4) == "rgb("){
9229 var rvs = v.slice(4, v.length -1).split(",");
9230 for(var i = 0; i < 3; i++){
9231 var h = parseInt(rvs[i]).toString(16);
9238 if(v.substr(0, 1) == "#"){
9240 for(var i = 1; i < 4; i++){
9241 var c = v.charAt(i);
9244 }else if(v.length == 7){
9245 color += v.substr(1);
9249 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9253 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9254 * gradient background, rounded corners and a 4-way shadow.
9255 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9256 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9257 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9258 * @return {Roo.Element} this
9260 boxWrap : function(cls){
9261 cls = cls || 'x-box';
9262 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9263 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9268 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9269 * @param {String} namespace The namespace in which to look for the attribute
9270 * @param {String} name The attribute name
9271 * @return {String} The attribute value
9273 getAttributeNS : Roo.isIE ? function(ns, name){
9275 var type = typeof d[ns+":"+name];
9276 if(type != 'undefined' && type != 'unknown'){
9277 return d[ns+":"+name];
9280 } : function(ns, name){
9282 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9286 var ep = El.prototype;
9289 * Appends an event handler (Shorthand for addListener)
9290 * @param {String} eventName The type of event to append
9291 * @param {Function} fn The method the event invokes
9292 * @param {Object} scope (optional) The scope (this object) of the fn
9293 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9296 ep.on = ep.addListener;
9298 ep.mon = ep.addListener;
9301 * Removes an event handler from this element (shorthand for removeListener)
9302 * @param {String} eventName the type of event to remove
9303 * @param {Function} fn the method the event invokes
9304 * @return {Roo.Element} this
9307 ep.un = ep.removeListener;
9310 * true to automatically adjust width and height settings for box-model issues (default to true)
9312 ep.autoBoxAdjust = true;
9315 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9318 El.addUnits = function(v, defaultUnit){
9319 if(v === "" || v == "auto"){
9322 if(v === undefined){
9325 if(typeof v == "number" || !El.unitPattern.test(v)){
9326 return v + (defaultUnit || 'px');
9331 // special markup used throughout Roo when box wrapping elements
9332 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>';
9334 * Visibility mode constant - Use visibility to hide element
9340 * Visibility mode constant - Use display to hide element
9346 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9347 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9348 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9360 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9361 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9362 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9363 * @return {Element} The Element object
9366 El.get = function(el){
9368 if(!el){ return null; }
9369 if(typeof el == "string"){ // element id
9370 if(!(elm = document.getElementById(el))){
9373 if(ex = El.cache[el]){
9376 ex = El.cache[el] = new El(elm);
9379 }else if(el.tagName){ // dom element
9383 if(ex = El.cache[id]){
9386 ex = El.cache[id] = new El(el);
9389 }else if(el instanceof El){
9391 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9392 // catch case where it hasn't been appended
9393 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9396 }else if(el.isComposite){
9398 }else if(el instanceof Array){
9399 return El.select(el);
9400 }else if(el == document){
9401 // create a bogus element object representing the document object
9403 var f = function(){};
9404 f.prototype = El.prototype;
9406 docEl.dom = document;
9414 El.uncache = function(el){
9415 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9417 delete El.cache[a[i].id || a[i]];
9423 // Garbage collection - uncache elements/purge listeners on orphaned elements
9424 // so we don't hold a reference and cause the browser to retain them
9425 El.garbageCollect = function(){
9426 if(!Roo.enableGarbageCollector){
9427 clearInterval(El.collectorThread);
9430 for(var eid in El.cache){
9431 var el = El.cache[eid], d = el.dom;
9432 // -------------------------------------------------------
9433 // Determining what is garbage:
9434 // -------------------------------------------------------
9436 // dom node is null, definitely garbage
9437 // -------------------------------------------------------
9439 // no parentNode == direct orphan, definitely garbage
9440 // -------------------------------------------------------
9441 // !d.offsetParent && !document.getElementById(eid)
9442 // display none elements have no offsetParent so we will
9443 // also try to look it up by it's id. However, check
9444 // offsetParent first so we don't do unneeded lookups.
9445 // This enables collection of elements that are not orphans
9446 // directly, but somewhere up the line they have an orphan
9448 // -------------------------------------------------------
9449 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9450 delete El.cache[eid];
9451 if(d && Roo.enableListenerCollection){
9457 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9461 El.Flyweight = function(dom){
9464 El.Flyweight.prototype = El.prototype;
9466 El._flyweights = {};
9468 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9469 * the dom node can be overwritten by other code.
9470 * @param {String/HTMLElement} el The dom node or id
9471 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9472 * prevent conflicts (e.g. internally Roo uses "_internal")
9474 * @return {Element} The shared Element object
9476 El.fly = function(el, named){
9477 named = named || '_global';
9478 el = Roo.getDom(el);
9482 if(!El._flyweights[named]){
9483 El._flyweights[named] = new El.Flyweight();
9485 El._flyweights[named].dom = el;
9486 return El._flyweights[named];
9490 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9491 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9492 * Shorthand of {@link Roo.Element#get}
9493 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9494 * @return {Element} The Element object
9500 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9501 * the dom node can be overwritten by other code.
9502 * Shorthand of {@link Roo.Element#fly}
9503 * @param {String/HTMLElement} el The dom node or id
9504 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9505 * prevent conflicts (e.g. internally Roo uses "_internal")
9507 * @return {Element} The shared Element object
9513 // speedy lookup for elements never to box adjust
9514 var noBoxAdjust = Roo.isStrict ? {
9517 input:1, select:1, textarea:1
9519 if(Roo.isIE || Roo.isGecko){
9520 noBoxAdjust['button'] = 1;
9524 Roo.EventManager.on(window, 'unload', function(){
9526 delete El._flyweights;
9534 Roo.Element.selectorFunction = Roo.DomQuery.select;
9537 Roo.Element.select = function(selector, unique, root){
9539 if(typeof selector == "string"){
9540 els = Roo.Element.selectorFunction(selector, root);
9541 }else if(selector.length !== undefined){
9544 throw "Invalid selector";
9546 if(unique === true){
9547 return new Roo.CompositeElement(els);
9549 return new Roo.CompositeElementLite(els);
9553 * Selects elements based on the passed CSS selector to enable working on them as 1.
9554 * @param {String/Array} selector The CSS selector or an array of elements
9555 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9556 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9557 * @return {CompositeElementLite/CompositeElement}
9561 Roo.select = Roo.Element.select;
9578 * Ext JS Library 1.1.1
9579 * Copyright(c) 2006-2007, Ext JS, LLC.
9581 * Originally Released Under LGPL - original licence link has changed is not relivant.
9584 * <script type="text/javascript">
9589 //Notifies Element that fx methods are available
9590 Roo.enableFx = true;
9594 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9595 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9596 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9597 * Element effects to work.</p><br/>
9599 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9600 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9601 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9602 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9603 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9604 * expected results and should be done with care.</p><br/>
9606 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9607 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9610 ----- -----------------------------
9611 tl The top left corner
9612 t The center of the top edge
9613 tr The top right corner
9614 l The center of the left edge
9615 r The center of the right edge
9616 bl The bottom left corner
9617 b The center of the bottom edge
9618 br The bottom right corner
9620 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9621 * below are common options that can be passed to any Fx method.</b>
9622 * @cfg {Function} callback A function called when the effect is finished
9623 * @cfg {Object} scope The scope of the effect function
9624 * @cfg {String} easing A valid Easing value for the effect
9625 * @cfg {String} afterCls A css class to apply after the effect
9626 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9627 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9628 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9629 * effects that end with the element being visually hidden, ignored otherwise)
9630 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9631 * a function which returns such a specification that will be applied to the Element after the effect finishes
9632 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9633 * @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
9634 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9638 * Slides the element into view. An anchor point can be optionally passed to set the point of
9639 * origin for the slide effect. This function automatically handles wrapping the element with
9640 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9643 // default: slide the element in from the top
9646 // custom: slide the element in from the right with a 2-second duration
9647 el.slideIn('r', { duration: 2 });
9649 // common config options shown with default values
9655 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9656 * @param {Object} options (optional) Object literal with any of the Fx config options
9657 * @return {Roo.Element} The Element
9659 slideIn : function(anchor, o){
9660 var el = this.getFxEl();
9663 el.queueFx(o, function(){
9665 anchor = anchor || "t";
9667 // fix display to visibility
9670 // restore values after effect
9671 var r = this.getFxRestore();
9672 var b = this.getBox();
9673 // fixed size for slide
9677 var wrap = this.fxWrap(r.pos, o, "hidden");
9679 var st = this.dom.style;
9680 st.visibility = "visible";
9681 st.position = "absolute";
9683 // clear out temp styles after slide and unwrap
9684 var after = function(){
9685 el.fxUnwrap(wrap, r.pos, o);
9687 st.height = r.height;
9690 // time to calc the positions
9691 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9693 switch(anchor.toLowerCase()){
9695 wrap.setSize(b.width, 0);
9696 st.left = st.bottom = "0";
9700 wrap.setSize(0, b.height);
9701 st.right = st.top = "0";
9705 wrap.setSize(0, b.height);
9707 st.left = st.top = "0";
9708 a = {width: bw, points: pt};
9711 wrap.setSize(b.width, 0);
9712 wrap.setY(b.bottom);
9713 st.left = st.top = "0";
9714 a = {height: bh, points: pt};
9718 st.right = st.bottom = "0";
9719 a = {width: bw, height: bh};
9723 wrap.setY(b.y+b.height);
9724 st.right = st.top = "0";
9725 a = {width: bw, height: bh, points: pt};
9729 wrap.setXY([b.right, b.bottom]);
9730 st.left = st.top = "0";
9731 a = {width: bw, height: bh, points: pt};
9735 wrap.setX(b.x+b.width);
9736 st.left = st.bottom = "0";
9737 a = {width: bw, height: bh, points: pt};
9740 this.dom.style.visibility = "visible";
9743 arguments.callee.anim = wrap.fxanim(a,
9753 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9754 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9755 * 'hidden') but block elements will still take up space in the document. The element must be removed
9756 * from the DOM using the 'remove' config option if desired. This function automatically handles
9757 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9760 // default: slide the element out to the top
9763 // custom: slide the element out to the right with a 2-second duration
9764 el.slideOut('r', { duration: 2 });
9766 // common config options shown with default values
9774 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9775 * @param {Object} options (optional) Object literal with any of the Fx config options
9776 * @return {Roo.Element} The Element
9778 slideOut : function(anchor, o){
9779 var el = this.getFxEl();
9782 el.queueFx(o, function(){
9784 anchor = anchor || "t";
9786 // restore values after effect
9787 var r = this.getFxRestore();
9789 var b = this.getBox();
9790 // fixed size for slide
9794 var wrap = this.fxWrap(r.pos, o, "visible");
9796 var st = this.dom.style;
9797 st.visibility = "visible";
9798 st.position = "absolute";
9802 var after = function(){
9804 el.setDisplayed(false);
9809 el.fxUnwrap(wrap, r.pos, o);
9812 st.height = r.height;
9817 var a, zero = {to: 0};
9818 switch(anchor.toLowerCase()){
9820 st.left = st.bottom = "0";
9824 st.right = st.top = "0";
9828 st.left = st.top = "0";
9829 a = {width: zero, points: {to:[b.right, b.y]}};
9832 st.left = st.top = "0";
9833 a = {height: zero, points: {to:[b.x, b.bottom]}};
9836 st.right = st.bottom = "0";
9837 a = {width: zero, height: zero};
9840 st.right = st.top = "0";
9841 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9844 st.left = st.top = "0";
9845 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9848 st.left = st.bottom = "0";
9849 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9853 arguments.callee.anim = wrap.fxanim(a,
9863 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
9864 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
9865 * The element must be removed from the DOM using the 'remove' config option if desired.
9871 // common config options shown with default values
9879 * @param {Object} options (optional) Object literal with any of the Fx config options
9880 * @return {Roo.Element} The Element
9883 var el = this.getFxEl();
9886 el.queueFx(o, function(){
9887 this.clearOpacity();
9890 // restore values after effect
9891 var r = this.getFxRestore();
9892 var st = this.dom.style;
9894 var after = function(){
9896 el.setDisplayed(false);
9903 el.setPositioning(r.pos);
9905 st.height = r.height;
9910 var width = this.getWidth();
9911 var height = this.getHeight();
9913 arguments.callee.anim = this.fxanim({
9914 width : {to: this.adjustWidth(width * 2)},
9915 height : {to: this.adjustHeight(height * 2)},
9916 points : {by: [-(width * .5), -(height * .5)]},
9918 fontSize: {to:200, unit: "%"}
9929 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
9930 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
9931 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
9937 // all config options shown with default values
9945 * @param {Object} options (optional) Object literal with any of the Fx config options
9946 * @return {Roo.Element} The Element
9948 switchOff : function(o){
9949 var el = this.getFxEl();
9952 el.queueFx(o, function(){
9953 this.clearOpacity();
9956 // restore values after effect
9957 var r = this.getFxRestore();
9958 var st = this.dom.style;
9960 var after = function(){
9962 el.setDisplayed(false);
9968 el.setPositioning(r.pos);
9970 st.height = r.height;
9975 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
9976 this.clearOpacity();
9980 points:{by:[0, this.getHeight() * .5]}
9981 }, o, 'motion', 0.3, 'easeIn', after);
9982 }).defer(100, this);
9989 * Highlights the Element by setting a color (applies to the background-color by default, but can be
9990 * changed using the "attr" config option) and then fading back to the original color. If no original
9991 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
9994 // default: highlight background to yellow
9997 // custom: highlight foreground text to blue for 2 seconds
9998 el.highlight("0000ff", { attr: 'color', duration: 2 });
10000 // common config options shown with default values
10001 el.highlight("ffff9c", {
10002 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10003 endColor: (current color) or "ffffff",
10008 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10009 * @param {Object} options (optional) Object literal with any of the Fx config options
10010 * @return {Roo.Element} The Element
10012 highlight : function(color, o){
10013 var el = this.getFxEl();
10016 el.queueFx(o, function(){
10017 color = color || "ffff9c";
10018 attr = o.attr || "backgroundColor";
10020 this.clearOpacity();
10023 var origColor = this.getColor(attr);
10024 var restoreColor = this.dom.style[attr];
10025 endColor = (o.endColor || origColor) || "ffffff";
10027 var after = function(){
10028 el.dom.style[attr] = restoreColor;
10033 a[attr] = {from: color, to: endColor};
10034 arguments.callee.anim = this.fxanim(a,
10044 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10047 // default: a single light blue ripple
10050 // custom: 3 red ripples lasting 3 seconds total
10051 el.frame("ff0000", 3, { duration: 3 });
10053 // common config options shown with default values
10054 el.frame("C3DAF9", 1, {
10055 duration: 1 //duration of entire animation (not each individual ripple)
10056 // Note: Easing is not configurable and will be ignored if included
10059 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10060 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10061 * @param {Object} options (optional) Object literal with any of the Fx config options
10062 * @return {Roo.Element} The Element
10064 frame : function(color, count, o){
10065 var el = this.getFxEl();
10068 el.queueFx(o, function(){
10069 color = color || "#C3DAF9";
10070 if(color.length == 6){
10071 color = "#" + color;
10073 count = count || 1;
10074 duration = o.duration || 1;
10077 var b = this.getBox();
10078 var animFn = function(){
10079 var proxy = this.createProxy({
10082 visbility:"hidden",
10083 position:"absolute",
10084 "z-index":"35000", // yee haw
10085 border:"0px solid " + color
10088 var scale = Roo.isBorderBox ? 2 : 1;
10090 top:{from:b.y, to:b.y - 20},
10091 left:{from:b.x, to:b.x - 20},
10092 borderWidth:{from:0, to:10},
10093 opacity:{from:1, to:0},
10094 height:{from:b.height, to:(b.height + (20*scale))},
10095 width:{from:b.width, to:(b.width + (20*scale))}
10096 }, duration, function(){
10100 animFn.defer((duration/2)*1000, this);
10111 * Creates a pause before any subsequent queued effects begin. If there are
10112 * no effects queued after the pause it will have no effect.
10117 * @param {Number} seconds The length of time to pause (in seconds)
10118 * @return {Roo.Element} The Element
10120 pause : function(seconds){
10121 var el = this.getFxEl();
10124 el.queueFx(o, function(){
10125 setTimeout(function(){
10127 }, seconds * 1000);
10133 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10134 * using the "endOpacity" config option.
10137 // default: fade in from opacity 0 to 100%
10140 // custom: fade in from opacity 0 to 75% over 2 seconds
10141 el.fadeIn({ endOpacity: .75, duration: 2});
10143 // common config options shown with default values
10145 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10150 * @param {Object} options (optional) Object literal with any of the Fx config options
10151 * @return {Roo.Element} The Element
10153 fadeIn : function(o){
10154 var el = this.getFxEl();
10156 el.queueFx(o, function(){
10157 this.setOpacity(0);
10159 this.dom.style.visibility = 'visible';
10160 var to = o.endOpacity || 1;
10161 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10162 o, null, .5, "easeOut", function(){
10164 this.clearOpacity();
10173 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10174 * using the "endOpacity" config option.
10177 // default: fade out from the element's current opacity to 0
10180 // custom: fade out from the element's current opacity to 25% over 2 seconds
10181 el.fadeOut({ endOpacity: .25, duration: 2});
10183 // common config options shown with default values
10185 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10192 * @param {Object} options (optional) Object literal with any of the Fx config options
10193 * @return {Roo.Element} The Element
10195 fadeOut : function(o){
10196 var el = this.getFxEl();
10198 el.queueFx(o, function(){
10199 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10200 o, null, .5, "easeOut", function(){
10201 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10202 this.dom.style.display = "none";
10204 this.dom.style.visibility = "hidden";
10206 this.clearOpacity();
10214 * Animates the transition of an element's dimensions from a starting height/width
10215 * to an ending height/width.
10218 // change height and width to 100x100 pixels
10219 el.scale(100, 100);
10221 // common config options shown with default values. The height and width will default to
10222 // the element's existing values if passed as null.
10225 [element's height], {
10230 * @param {Number} width The new width (pass undefined to keep the original width)
10231 * @param {Number} height The new height (pass undefined to keep the original height)
10232 * @param {Object} options (optional) Object literal with any of the Fx config options
10233 * @return {Roo.Element} The Element
10235 scale : function(w, h, o){
10236 this.shift(Roo.apply({}, o, {
10244 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10245 * Any of these properties not specified in the config object will not be changed. This effect
10246 * requires that at least one new dimension, position or opacity setting must be passed in on
10247 * the config object in order for the function to have any effect.
10250 // slide the element horizontally to x position 200 while changing the height and opacity
10251 el.shift({ x: 200, height: 50, opacity: .8 });
10253 // common config options shown with default values.
10255 width: [element's width],
10256 height: [element's height],
10257 x: [element's x position],
10258 y: [element's y position],
10259 opacity: [element's opacity],
10264 * @param {Object} options Object literal with any of the Fx config options
10265 * @return {Roo.Element} The Element
10267 shift : function(o){
10268 var el = this.getFxEl();
10270 el.queueFx(o, function(){
10271 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10272 if(w !== undefined){
10273 a.width = {to: this.adjustWidth(w)};
10275 if(h !== undefined){
10276 a.height = {to: this.adjustHeight(h)};
10278 if(x !== undefined || y !== undefined){
10280 x !== undefined ? x : this.getX(),
10281 y !== undefined ? y : this.getY()
10284 if(op !== undefined){
10285 a.opacity = {to: op};
10287 if(o.xy !== undefined){
10288 a.points = {to: o.xy};
10290 arguments.callee.anim = this.fxanim(a,
10291 o, 'motion', .35, "easeOut", function(){
10299 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10300 * ending point of the effect.
10303 // default: slide the element downward while fading out
10306 // custom: slide the element out to the right with a 2-second duration
10307 el.ghost('r', { duration: 2 });
10309 // common config options shown with default values
10317 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10318 * @param {Object} options (optional) Object literal with any of the Fx config options
10319 * @return {Roo.Element} The Element
10321 ghost : function(anchor, o){
10322 var el = this.getFxEl();
10325 el.queueFx(o, function(){
10326 anchor = anchor || "b";
10328 // restore values after effect
10329 var r = this.getFxRestore();
10330 var w = this.getWidth(),
10331 h = this.getHeight();
10333 var st = this.dom.style;
10335 var after = function(){
10337 el.setDisplayed(false);
10343 el.setPositioning(r.pos);
10344 st.width = r.width;
10345 st.height = r.height;
10350 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10351 switch(anchor.toLowerCase()){
10378 arguments.callee.anim = this.fxanim(a,
10388 * Ensures that all effects queued after syncFx is called on the element are
10389 * run concurrently. This is the opposite of {@link #sequenceFx}.
10390 * @return {Roo.Element} The Element
10392 syncFx : function(){
10393 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10402 * Ensures that all effects queued after sequenceFx is called on the element are
10403 * run in sequence. This is the opposite of {@link #syncFx}.
10404 * @return {Roo.Element} The Element
10406 sequenceFx : function(){
10407 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10409 concurrent : false,
10416 nextFx : function(){
10417 var ef = this.fxQueue[0];
10424 * Returns true if the element has any effects actively running or queued, else returns false.
10425 * @return {Boolean} True if element has active effects, else false
10427 hasActiveFx : function(){
10428 return this.fxQueue && this.fxQueue[0];
10432 * Stops any running effects and clears the element's internal effects queue if it contains
10433 * any additional effects that haven't started yet.
10434 * @return {Roo.Element} The Element
10436 stopFx : function(){
10437 if(this.hasActiveFx()){
10438 var cur = this.fxQueue[0];
10439 if(cur && cur.anim && cur.anim.isAnimated()){
10440 this.fxQueue = [cur]; // clear out others
10441 cur.anim.stop(true);
10448 beforeFx : function(o){
10449 if(this.hasActiveFx() && !o.concurrent){
10460 * Returns true if the element is currently blocking so that no other effect can be queued
10461 * until this effect is finished, else returns false if blocking is not set. This is commonly
10462 * used to ensure that an effect initiated by a user action runs to completion prior to the
10463 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10464 * @return {Boolean} True if blocking, else false
10466 hasFxBlock : function(){
10467 var q = this.fxQueue;
10468 return q && q[0] && q[0].block;
10472 queueFx : function(o, fn){
10476 if(!this.hasFxBlock()){
10477 Roo.applyIf(o, this.fxDefaults);
10479 var run = this.beforeFx(o);
10480 fn.block = o.block;
10481 this.fxQueue.push(fn);
10493 fxWrap : function(pos, o, vis){
10495 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10498 wrapXY = this.getXY();
10500 var div = document.createElement("div");
10501 div.style.visibility = vis;
10502 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10503 wrap.setPositioning(pos);
10504 if(wrap.getStyle("position") == "static"){
10505 wrap.position("relative");
10507 this.clearPositioning('auto');
10509 wrap.dom.appendChild(this.dom);
10511 wrap.setXY(wrapXY);
10518 fxUnwrap : function(wrap, pos, o){
10519 this.clearPositioning();
10520 this.setPositioning(pos);
10522 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10528 getFxRestore : function(){
10529 var st = this.dom.style;
10530 return {pos: this.getPositioning(), width: st.width, height : st.height};
10534 afterFx : function(o){
10536 this.applyStyles(o.afterStyle);
10539 this.addClass(o.afterCls);
10541 if(o.remove === true){
10544 Roo.callback(o.callback, o.scope, [this]);
10546 this.fxQueue.shift();
10552 getFxEl : function(){ // support for composite element fx
10553 return Roo.get(this.dom);
10557 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10558 animType = animType || 'run';
10560 var anim = Roo.lib.Anim[animType](
10562 (opt.duration || defaultDur) || .35,
10563 (opt.easing || defaultEase) || 'easeOut',
10565 Roo.callback(cb, this);
10574 // backwords compat
10575 Roo.Fx.resize = Roo.Fx.scale;
10577 //When included, Roo.Fx is automatically applied to Element so that all basic
10578 //effects are available directly via the Element API
10579 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10581 * Ext JS Library 1.1.1
10582 * Copyright(c) 2006-2007, Ext JS, LLC.
10584 * Originally Released Under LGPL - original licence link has changed is not relivant.
10587 * <script type="text/javascript">
10592 * @class Roo.CompositeElement
10593 * Standard composite class. Creates a Roo.Element for every element in the collection.
10595 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10596 * actions will be performed on all the elements in this collection.</b>
10598 * All methods return <i>this</i> and can be chained.
10600 var els = Roo.select("#some-el div.some-class", true);
10601 // or select directly from an existing element
10602 var el = Roo.get('some-el');
10603 el.select('div.some-class', true);
10605 els.setWidth(100); // all elements become 100 width
10606 els.hide(true); // all elements fade out and hide
10608 els.setWidth(100).hide(true);
10611 Roo.CompositeElement = function(els){
10612 this.elements = [];
10613 this.addElements(els);
10615 Roo.CompositeElement.prototype = {
10617 addElements : function(els){
10618 if(!els) return this;
10619 if(typeof els == "string"){
10620 els = Roo.Element.selectorFunction(els);
10622 var yels = this.elements;
10623 var index = yels.length-1;
10624 for(var i = 0, len = els.length; i < len; i++) {
10625 yels[++index] = Roo.get(els[i]);
10631 * Clears this composite and adds the elements returned by the passed selector.
10632 * @param {String/Array} els A string CSS selector, an array of elements or an element
10633 * @return {CompositeElement} this
10635 fill : function(els){
10636 this.elements = [];
10642 * Filters this composite to only elements that match the passed selector.
10643 * @param {String} selector A string CSS selector
10644 * @return {CompositeElement} this
10646 filter : function(selector){
10648 this.each(function(el){
10649 if(el.is(selector)){
10650 els[els.length] = el.dom;
10657 invoke : function(fn, args){
10658 var els = this.elements;
10659 for(var i = 0, len = els.length; i < len; i++) {
10660 Roo.Element.prototype[fn].apply(els[i], args);
10665 * Adds elements to this composite.
10666 * @param {String/Array} els A string CSS selector, an array of elements or an element
10667 * @return {CompositeElement} this
10669 add : function(els){
10670 if(typeof els == "string"){
10671 this.addElements(Roo.Element.selectorFunction(els));
10672 }else if(els.length !== undefined){
10673 this.addElements(els);
10675 this.addElements([els]);
10680 * Calls the passed function passing (el, this, index) for each element in this composite.
10681 * @param {Function} fn The function to call
10682 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10683 * @return {CompositeElement} this
10685 each : function(fn, scope){
10686 var els = this.elements;
10687 for(var i = 0, len = els.length; i < len; i++){
10688 if(fn.call(scope || els[i], els[i], this, i) === false) {
10696 * Returns the Element object at the specified index
10697 * @param {Number} index
10698 * @return {Roo.Element}
10700 item : function(index){
10701 return this.elements[index] || null;
10705 * Returns the first Element
10706 * @return {Roo.Element}
10708 first : function(){
10709 return this.item(0);
10713 * Returns the last Element
10714 * @return {Roo.Element}
10717 return this.item(this.elements.length-1);
10721 * Returns the number of elements in this composite
10724 getCount : function(){
10725 return this.elements.length;
10729 * Returns true if this composite contains the passed element
10732 contains : function(el){
10733 return this.indexOf(el) !== -1;
10737 * Returns true if this composite contains the passed element
10740 indexOf : function(el){
10741 return this.elements.indexOf(Roo.get(el));
10746 * Removes the specified element(s).
10747 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10748 * or an array of any of those.
10749 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10750 * @return {CompositeElement} this
10752 removeElement : function(el, removeDom){
10753 if(el instanceof Array){
10754 for(var i = 0, len = el.length; i < len; i++){
10755 this.removeElement(el[i]);
10759 var index = typeof el == 'number' ? el : this.indexOf(el);
10762 var d = this.elements[index];
10766 d.parentNode.removeChild(d);
10769 this.elements.splice(index, 1);
10775 * Replaces the specified element with the passed element.
10776 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10778 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10779 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10780 * @return {CompositeElement} this
10782 replaceElement : function(el, replacement, domReplace){
10783 var index = typeof el == 'number' ? el : this.indexOf(el);
10786 this.elements[index].replaceWith(replacement);
10788 this.elements.splice(index, 1, Roo.get(replacement))
10795 * Removes all elements.
10797 clear : function(){
10798 this.elements = [];
10802 Roo.CompositeElement.createCall = function(proto, fnName){
10803 if(!proto[fnName]){
10804 proto[fnName] = function(){
10805 return this.invoke(fnName, arguments);
10809 for(var fnName in Roo.Element.prototype){
10810 if(typeof Roo.Element.prototype[fnName] == "function"){
10811 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10817 * Ext JS Library 1.1.1
10818 * Copyright(c) 2006-2007, Ext JS, LLC.
10820 * Originally Released Under LGPL - original licence link has changed is not relivant.
10823 * <script type="text/javascript">
10827 * @class Roo.CompositeElementLite
10828 * @extends Roo.CompositeElement
10829 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10831 var els = Roo.select("#some-el div.some-class");
10832 // or select directly from an existing element
10833 var el = Roo.get('some-el');
10834 el.select('div.some-class');
10836 els.setWidth(100); // all elements become 100 width
10837 els.hide(true); // all elements fade out and hide
10839 els.setWidth(100).hide(true);
10840 </code></pre><br><br>
10841 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10842 * actions will be performed on all the elements in this collection.</b>
10844 Roo.CompositeElementLite = function(els){
10845 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10846 this.el = new Roo.Element.Flyweight();
10848 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10849 addElements : function(els){
10851 if(els instanceof Array){
10852 this.elements = this.elements.concat(els);
10854 var yels = this.elements;
10855 var index = yels.length-1;
10856 for(var i = 0, len = els.length; i < len; i++) {
10857 yels[++index] = els[i];
10863 invoke : function(fn, args){
10864 var els = this.elements;
10866 for(var i = 0, len = els.length; i < len; i++) {
10868 Roo.Element.prototype[fn].apply(el, args);
10873 * Returns a flyweight Element of the dom element object at the specified index
10874 * @param {Number} index
10875 * @return {Roo.Element}
10877 item : function(index){
10878 if(!this.elements[index]){
10881 this.el.dom = this.elements[index];
10885 // fixes scope with flyweight
10886 addListener : function(eventName, handler, scope, opt){
10887 var els = this.elements;
10888 for(var i = 0, len = els.length; i < len; i++) {
10889 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
10895 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
10896 * passed is the flyweight (shared) Roo.Element instance, so if you require a
10897 * a reference to the dom node, use el.dom.</b>
10898 * @param {Function} fn The function to call
10899 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10900 * @return {CompositeElement} this
10902 each : function(fn, scope){
10903 var els = this.elements;
10905 for(var i = 0, len = els.length; i < len; i++){
10907 if(fn.call(scope || el, el, this, i) === false){
10914 indexOf : function(el){
10915 return this.elements.indexOf(Roo.getDom(el));
10918 replaceElement : function(el, replacement, domReplace){
10919 var index = typeof el == 'number' ? el : this.indexOf(el);
10921 replacement = Roo.getDom(replacement);
10923 var d = this.elements[index];
10924 d.parentNode.insertBefore(replacement, d);
10925 d.parentNode.removeChild(d);
10927 this.elements.splice(index, 1, replacement);
10932 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
10936 * Ext JS Library 1.1.1
10937 * Copyright(c) 2006-2007, Ext JS, LLC.
10939 * Originally Released Under LGPL - original licence link has changed is not relivant.
10942 * <script type="text/javascript">
10948 * @class Roo.data.Connection
10949 * @extends Roo.util.Observable
10950 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
10951 * either to a configured URL, or to a URL specified at request time.<br><br>
10953 * Requests made by this class are asynchronous, and will return immediately. No data from
10954 * the server will be available to the statement immediately following the {@link #request} call.
10955 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
10957 * Note: If you are doing a file upload, you will not get a normal response object sent back to
10958 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
10959 * The response object is created using the innerHTML of the IFRAME's document as the responseText
10960 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
10961 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
10962 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
10963 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
10964 * standard DOM methods.
10966 * @param {Object} config a configuration object.
10968 Roo.data.Connection = function(config){
10969 Roo.apply(this, config);
10972 * @event beforerequest
10973 * Fires before a network request is made to retrieve a data object.
10974 * @param {Connection} conn This Connection object.
10975 * @param {Object} options The options config object passed to the {@link #request} method.
10977 "beforerequest" : true,
10979 * @event requestcomplete
10980 * Fires if the request was successfully completed.
10981 * @param {Connection} conn This Connection object.
10982 * @param {Object} response The XHR object containing the response data.
10983 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
10984 * @param {Object} options The options config object passed to the {@link #request} method.
10986 "requestcomplete" : true,
10988 * @event requestexception
10989 * Fires if an error HTTP status was returned from the server.
10990 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
10991 * @param {Connection} conn This Connection object.
10992 * @param {Object} response The XHR object containing the response data.
10993 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
10994 * @param {Object} options The options config object passed to the {@link #request} method.
10996 "requestexception" : true
10998 Roo.data.Connection.superclass.constructor.call(this);
11001 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11003 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11006 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11007 * extra parameters to each request made by this object. (defaults to undefined)
11010 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11011 * to each request made by this object. (defaults to undefined)
11014 * @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)
11017 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11021 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11027 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11030 disableCaching: true,
11033 * Sends an HTTP request to a remote server.
11034 * @param {Object} options An object which may contain the following properties:<ul>
11035 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11036 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11037 * request, a url encoded string or a function to call to get either.</li>
11038 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11039 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11040 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11041 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11042 * <li>options {Object} The parameter to the request call.</li>
11043 * <li>success {Boolean} True if the request succeeded.</li>
11044 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11046 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11047 * The callback is passed the following parameters:<ul>
11048 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11049 * <li>options {Object} The parameter to the request call.</li>
11051 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11052 * The callback is passed the following parameters:<ul>
11053 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11054 * <li>options {Object} The parameter to the request call.</li>
11056 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11057 * for the callback function. Defaults to the browser window.</li>
11058 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11059 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11060 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11061 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11062 * params for the post data. Any params will be appended to the URL.</li>
11063 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11065 * @return {Number} transactionId
11067 request : function(o){
11068 if(this.fireEvent("beforerequest", this, o) !== false){
11071 if(typeof p == "function"){
11072 p = p.call(o.scope||window, o);
11074 if(typeof p == "object"){
11075 p = Roo.urlEncode(o.params);
11077 if(this.extraParams){
11078 var extras = Roo.urlEncode(this.extraParams);
11079 p = p ? (p + '&' + extras) : extras;
11082 var url = o.url || this.url;
11083 if(typeof url == 'function'){
11084 url = url.call(o.scope||window, o);
11088 var form = Roo.getDom(o.form);
11089 url = url || form.action;
11091 var enctype = form.getAttribute("enctype");
11092 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11093 return this.doFormUpload(o, p, url);
11095 var f = Roo.lib.Ajax.serializeForm(form);
11096 p = p ? (p + '&' + f) : f;
11099 var hs = o.headers;
11100 if(this.defaultHeaders){
11101 hs = Roo.apply(hs || {}, this.defaultHeaders);
11108 success: this.handleResponse,
11109 failure: this.handleFailure,
11111 argument: {options: o},
11112 timeout : this.timeout
11115 var method = o.method||this.method||(p ? "POST" : "GET");
11117 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11118 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11121 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11125 }else if(this.autoAbort !== false){
11129 if((method == 'GET' && p) || o.xmlData){
11130 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11133 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11134 return this.transId;
11136 Roo.callback(o.callback, o.scope, [o, null, null]);
11142 * Determine whether this object has a request outstanding.
11143 * @param {Number} transactionId (Optional) defaults to the last transaction
11144 * @return {Boolean} True if there is an outstanding request.
11146 isLoading : function(transId){
11148 return Roo.lib.Ajax.isCallInProgress(transId);
11150 return this.transId ? true : false;
11155 * Aborts any outstanding request.
11156 * @param {Number} transactionId (Optional) defaults to the last transaction
11158 abort : function(transId){
11159 if(transId || this.isLoading()){
11160 Roo.lib.Ajax.abort(transId || this.transId);
11165 handleResponse : function(response){
11166 this.transId = false;
11167 var options = response.argument.options;
11168 response.argument = options ? options.argument : null;
11169 this.fireEvent("requestcomplete", this, response, options);
11170 Roo.callback(options.success, options.scope, [response, options]);
11171 Roo.callback(options.callback, options.scope, [options, true, response]);
11175 handleFailure : function(response, e){
11176 this.transId = false;
11177 var options = response.argument.options;
11178 response.argument = options ? options.argument : null;
11179 this.fireEvent("requestexception", this, response, options, e);
11180 Roo.callback(options.failure, options.scope, [response, options]);
11181 Roo.callback(options.callback, options.scope, [options, false, response]);
11185 doFormUpload : function(o, ps, url){
11187 var frame = document.createElement('iframe');
11190 frame.className = 'x-hidden';
11192 frame.src = Roo.SSL_SECURE_URL;
11194 document.body.appendChild(frame);
11197 document.frames[id].name = id;
11200 var form = Roo.getDom(o.form);
11202 form.method = 'POST';
11203 form.enctype = form.encoding = 'multipart/form-data';
11209 if(ps){ // add dynamic params
11211 ps = Roo.urlDecode(ps, false);
11213 if(ps.hasOwnProperty(k)){
11214 hd = document.createElement('input');
11215 hd.type = 'hidden';
11218 form.appendChild(hd);
11225 var r = { // bogus response object
11230 r.argument = o ? o.argument : null;
11235 doc = frame.contentWindow.document;
11237 doc = (frame.contentDocument || window.frames[id].document);
11239 if(doc && doc.body){
11240 r.responseText = doc.body.innerHTML;
11242 if(doc && doc.XMLDocument){
11243 r.responseXML = doc.XMLDocument;
11245 r.responseXML = doc;
11252 Roo.EventManager.removeListener(frame, 'load', cb, this);
11254 this.fireEvent("requestcomplete", this, r, o);
11255 Roo.callback(o.success, o.scope, [r, o]);
11256 Roo.callback(o.callback, o.scope, [o, true, r]);
11258 setTimeout(function(){document.body.removeChild(frame);}, 100);
11261 Roo.EventManager.on(frame, 'load', cb, this);
11264 if(hiddens){ // remove dynamic params
11265 for(var i = 0, len = hiddens.length; i < len; i++){
11266 form.removeChild(hiddens[i]);
11274 * @extends Roo.data.Connection
11275 * Global Ajax request class.
11279 Roo.Ajax = new Roo.data.Connection({
11282 * @cfg {String} url @hide
11285 * @cfg {Object} extraParams @hide
11288 * @cfg {Object} defaultHeaders @hide
11291 * @cfg {String} method (Optional) @hide
11294 * @cfg {Number} timeout (Optional) @hide
11297 * @cfg {Boolean} autoAbort (Optional) @hide
11301 * @cfg {Boolean} disableCaching (Optional) @hide
11305 * @property disableCaching
11306 * True to add a unique cache-buster param to GET requests. (defaults to true)
11311 * The default URL to be used for requests to the server. (defaults to undefined)
11315 * @property extraParams
11316 * An object containing properties which are used as
11317 * extra parameters to each request made by this object. (defaults to undefined)
11321 * @property defaultHeaders
11322 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11327 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11331 * @property timeout
11332 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11337 * @property autoAbort
11338 * Whether a new request should abort any pending requests. (defaults to false)
11344 * Serialize the passed form into a url encoded string
11345 * @param {String/HTMLElement} form
11348 serializeForm : function(form){
11349 return Roo.lib.Ajax.serializeForm(form);
11353 * Ext JS Library 1.1.1
11354 * Copyright(c) 2006-2007, Ext JS, LLC.
11356 * Originally Released Under LGPL - original licence link has changed is not relivant.
11359 * <script type="text/javascript">
11364 * @extends Roo.data.Connection
11365 * Global Ajax request class.
11367 * @instanceOf Roo.data.Connection
11369 Roo.Ajax = new Roo.data.Connection({
11378 * @cfg {String} url @hide
11381 * @cfg {Object} extraParams @hide
11384 * @cfg {Object} defaultHeaders @hide
11387 * @cfg {String} method (Optional) @hide
11390 * @cfg {Number} timeout (Optional) @hide
11393 * @cfg {Boolean} autoAbort (Optional) @hide
11397 * @cfg {Boolean} disableCaching (Optional) @hide
11401 * @property disableCaching
11402 * True to add a unique cache-buster param to GET requests. (defaults to true)
11407 * The default URL to be used for requests to the server. (defaults to undefined)
11411 * @property extraParams
11412 * An object containing properties which are used as
11413 * extra parameters to each request made by this object. (defaults to undefined)
11417 * @property defaultHeaders
11418 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11423 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11427 * @property timeout
11428 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11433 * @property autoAbort
11434 * Whether a new request should abort any pending requests. (defaults to false)
11440 * Serialize the passed form into a url encoded string
11441 * @param {String/HTMLElement} form
11444 serializeForm : function(form){
11445 return Roo.lib.Ajax.serializeForm(form);
11449 * Ext JS Library 1.1.1
11450 * Copyright(c) 2006-2007, Ext JS, LLC.
11452 * Originally Released Under LGPL - original licence link has changed is not relivant.
11455 * <script type="text/javascript">
11460 * @class Roo.UpdateManager
11461 * @extends Roo.util.Observable
11462 * Provides AJAX-style update for Element object.<br><br>
11465 * // Get it from a Roo.Element object
11466 * var el = Roo.get("foo");
11467 * var mgr = el.getUpdateManager();
11468 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11470 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11472 * // or directly (returns the same UpdateManager instance)
11473 * var mgr = new Roo.UpdateManager("myElementId");
11474 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11475 * mgr.on("update", myFcnNeedsToKnow);
11477 // short handed call directly from the element object
11478 Roo.get("foo").load({
11482 text: "Loading Foo..."
11486 * Create new UpdateManager directly.
11487 * @param {String/HTMLElement/Roo.Element} el The element to update
11488 * @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).
11490 Roo.UpdateManager = function(el, forceNew){
11492 if(!forceNew && el.updateManager){
11493 return el.updateManager;
11496 * The Element object
11497 * @type Roo.Element
11501 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11504 this.defaultUrl = null;
11508 * @event beforeupdate
11509 * Fired before an update is made, return false from your handler and the update is cancelled.
11510 * @param {Roo.Element} el
11511 * @param {String/Object/Function} url
11512 * @param {String/Object} params
11514 "beforeupdate": true,
11517 * Fired after successful update is made.
11518 * @param {Roo.Element} el
11519 * @param {Object} oResponseObject The response Object
11524 * Fired on update failure.
11525 * @param {Roo.Element} el
11526 * @param {Object} oResponseObject The response Object
11530 var d = Roo.UpdateManager.defaults;
11532 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11535 this.sslBlankUrl = d.sslBlankUrl;
11537 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11540 this.disableCaching = d.disableCaching;
11542 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11545 this.indicatorText = d.indicatorText;
11547 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11550 this.showLoadIndicator = d.showLoadIndicator;
11552 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11555 this.timeout = d.timeout;
11558 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11561 this.loadScripts = d.loadScripts;
11564 * Transaction object of current executing transaction
11566 this.transaction = null;
11571 this.autoRefreshProcId = null;
11573 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11576 this.refreshDelegate = this.refresh.createDelegate(this);
11578 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11581 this.updateDelegate = this.update.createDelegate(this);
11583 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11586 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11590 this.successDelegate = this.processSuccess.createDelegate(this);
11594 this.failureDelegate = this.processFailure.createDelegate(this);
11596 if(!this.renderer){
11598 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11600 this.renderer = new Roo.UpdateManager.BasicRenderer();
11603 Roo.UpdateManager.superclass.constructor.call(this);
11606 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11608 * Get the Element this UpdateManager is bound to
11609 * @return {Roo.Element} The element
11611 getEl : function(){
11615 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11616 * @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:
11619 url: "your-url.php",<br/>
11620 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11621 callback: yourFunction,<br/>
11622 scope: yourObject, //(optional scope) <br/>
11623 discardUrl: false, <br/>
11624 nocache: false,<br/>
11625 text: "Loading...",<br/>
11627 scripts: false<br/>
11630 * The only required property is url. The optional properties nocache, text and scripts
11631 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11632 * @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}
11633 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11634 * @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.
11636 update : function(url, params, callback, discardUrl){
11637 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11638 var method = this.method, cfg;
11639 if(typeof url == "object"){ // must be config object
11642 params = params || cfg.params;
11643 callback = callback || cfg.callback;
11644 discardUrl = discardUrl || cfg.discardUrl;
11645 if(callback && cfg.scope){
11646 callback = callback.createDelegate(cfg.scope);
11648 if(typeof cfg.method != "undefined"){method = cfg.method;};
11649 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11650 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11651 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11652 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11654 this.showLoading();
11656 this.defaultUrl = url;
11658 if(typeof url == "function"){
11659 url = url.call(this);
11662 method = method || (params ? "POST" : "GET");
11663 if(method == "GET"){
11664 url = this.prepareUrl(url);
11667 var o = Roo.apply(cfg ||{}, {
11670 success: this.successDelegate,
11671 failure: this.failureDelegate,
11672 callback: undefined,
11673 timeout: (this.timeout*1000),
11674 argument: {"url": url, "form": null, "callback": callback, "params": params}
11677 this.transaction = Roo.Ajax.request(o);
11682 * 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.
11683 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11684 * @param {String/HTMLElement} form The form Id or form element
11685 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11686 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11687 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11689 formUpdate : function(form, url, reset, callback){
11690 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11691 if(typeof url == "function"){
11692 url = url.call(this);
11694 form = Roo.getDom(form);
11695 this.transaction = Roo.Ajax.request({
11698 success: this.successDelegate,
11699 failure: this.failureDelegate,
11700 timeout: (this.timeout*1000),
11701 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11703 this.showLoading.defer(1, this);
11708 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11709 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11711 refresh : function(callback){
11712 if(this.defaultUrl == null){
11715 this.update(this.defaultUrl, null, callback, true);
11719 * Set this element to auto refresh.
11720 * @param {Number} interval How often to update (in seconds).
11721 * @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)
11722 * @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}
11723 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11724 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11726 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11728 this.update(url || this.defaultUrl, params, callback, true);
11730 if(this.autoRefreshProcId){
11731 clearInterval(this.autoRefreshProcId);
11733 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11737 * Stop auto refresh on this element.
11739 stopAutoRefresh : function(){
11740 if(this.autoRefreshProcId){
11741 clearInterval(this.autoRefreshProcId);
11742 delete this.autoRefreshProcId;
11746 isAutoRefreshing : function(){
11747 return this.autoRefreshProcId ? true : false;
11750 * Called to update the element to "Loading" state. Override to perform custom action.
11752 showLoading : function(){
11753 if(this.showLoadIndicator){
11754 this.el.update(this.indicatorText);
11759 * Adds unique parameter to query string if disableCaching = true
11762 prepareUrl : function(url){
11763 if(this.disableCaching){
11764 var append = "_dc=" + (new Date().getTime());
11765 if(url.indexOf("?") !== -1){
11766 url += "&" + append;
11768 url += "?" + append;
11777 processSuccess : function(response){
11778 this.transaction = null;
11779 if(response.argument.form && response.argument.reset){
11780 try{ // put in try/catch since some older FF releases had problems with this
11781 response.argument.form.reset();
11784 if(this.loadScripts){
11785 this.renderer.render(this.el, response, this,
11786 this.updateComplete.createDelegate(this, [response]));
11788 this.renderer.render(this.el, response, this);
11789 this.updateComplete(response);
11793 updateComplete : function(response){
11794 this.fireEvent("update", this.el, response);
11795 if(typeof response.argument.callback == "function"){
11796 response.argument.callback(this.el, true, response);
11803 processFailure : function(response){
11804 this.transaction = null;
11805 this.fireEvent("failure", this.el, response);
11806 if(typeof response.argument.callback == "function"){
11807 response.argument.callback(this.el, false, response);
11812 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11813 * @param {Object} renderer The object implementing the render() method
11815 setRenderer : function(renderer){
11816 this.renderer = renderer;
11819 getRenderer : function(){
11820 return this.renderer;
11824 * Set the defaultUrl used for updates
11825 * @param {String/Function} defaultUrl The url or a function to call to get the url
11827 setDefaultUrl : function(defaultUrl){
11828 this.defaultUrl = defaultUrl;
11832 * Aborts the executing transaction
11834 abort : function(){
11835 if(this.transaction){
11836 Roo.Ajax.abort(this.transaction);
11841 * Returns true if an update is in progress
11842 * @return {Boolean}
11844 isUpdating : function(){
11845 if(this.transaction){
11846 return Roo.Ajax.isLoading(this.transaction);
11853 * @class Roo.UpdateManager.defaults
11854 * @static (not really - but it helps the doc tool)
11855 * The defaults collection enables customizing the default properties of UpdateManager
11857 Roo.UpdateManager.defaults = {
11859 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
11865 * True to process scripts by default (Defaults to false).
11868 loadScripts : false,
11871 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
11874 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
11876 * Whether to append unique parameter on get request to disable caching (Defaults to false).
11879 disableCaching : false,
11881 * Whether to show indicatorText when loading (Defaults to true).
11884 showLoadIndicator : true,
11886 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
11889 indicatorText : '<div class="loading-indicator">Loading...</div>'
11893 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
11895 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
11896 * @param {String/HTMLElement/Roo.Element} el The element to update
11897 * @param {String} url The url
11898 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
11899 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
11902 * @member Roo.UpdateManager
11904 Roo.UpdateManager.updateElement = function(el, url, params, options){
11905 var um = Roo.get(el, true).getUpdateManager();
11906 Roo.apply(um, options);
11907 um.update(url, params, options ? options.callback : null);
11909 // alias for backwards compat
11910 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
11912 * @class Roo.UpdateManager.BasicRenderer
11913 * Default Content renderer. Updates the elements innerHTML with the responseText.
11915 Roo.UpdateManager.BasicRenderer = function(){};
11917 Roo.UpdateManager.BasicRenderer.prototype = {
11919 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
11920 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
11921 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
11922 * @param {Roo.Element} el The element being rendered
11923 * @param {Object} response The YUI Connect response object
11924 * @param {UpdateManager} updateManager The calling update manager
11925 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
11927 render : function(el, response, updateManager, callback){
11928 el.update(response.responseText, updateManager.loadScripts, callback);
11933 * Ext JS Library 1.1.1
11934 * Copyright(c) 2006-2007, Ext JS, LLC.
11936 * Originally Released Under LGPL - original licence link has changed is not relivant.
11939 * <script type="text/javascript">
11943 * @class Roo.util.DelayedTask
11944 * Provides a convenient method of performing setTimeout where a new
11945 * timeout cancels the old timeout. An example would be performing validation on a keypress.
11946 * You can use this class to buffer
11947 * the keypress events for a certain number of milliseconds, and perform only if they stop
11948 * for that amount of time.
11949 * @constructor The parameters to this constructor serve as defaults and are not required.
11950 * @param {Function} fn (optional) The default function to timeout
11951 * @param {Object} scope (optional) The default scope of that timeout
11952 * @param {Array} args (optional) The default Array of arguments
11954 Roo.util.DelayedTask = function(fn, scope, args){
11955 var id = null, d, t;
11957 var call = function(){
11958 var now = new Date().getTime();
11962 fn.apply(scope, args || []);
11966 * Cancels any pending timeout and queues a new one
11967 * @param {Number} delay The milliseconds to delay
11968 * @param {Function} newFn (optional) Overrides function passed to constructor
11969 * @param {Object} newScope (optional) Overrides scope passed to constructor
11970 * @param {Array} newArgs (optional) Overrides args passed to constructor
11972 this.delay = function(delay, newFn, newScope, newArgs){
11973 if(id && delay != d){
11977 t = new Date().getTime();
11979 scope = newScope || scope;
11980 args = newArgs || args;
11982 id = setInterval(call, d);
11987 * Cancel the last queued timeout
11989 this.cancel = function(){
11997 * Ext JS Library 1.1.1
11998 * Copyright(c) 2006-2007, Ext JS, LLC.
12000 * Originally Released Under LGPL - original licence link has changed is not relivant.
12003 * <script type="text/javascript">
12007 Roo.util.TaskRunner = function(interval){
12008 interval = interval || 10;
12009 var tasks = [], removeQueue = [];
12011 var running = false;
12013 var stopThread = function(){
12019 var startThread = function(){
12022 id = setInterval(runTasks, interval);
12026 var removeTask = function(task){
12027 removeQueue.push(task);
12033 var runTasks = function(){
12034 if(removeQueue.length > 0){
12035 for(var i = 0, len = removeQueue.length; i < len; i++){
12036 tasks.remove(removeQueue[i]);
12039 if(tasks.length < 1){
12044 var now = new Date().getTime();
12045 for(var i = 0, len = tasks.length; i < len; ++i){
12047 var itime = now - t.taskRunTime;
12048 if(t.interval <= itime){
12049 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12050 t.taskRunTime = now;
12051 if(rt === false || t.taskRunCount === t.repeat){
12056 if(t.duration && t.duration <= (now - t.taskStartTime)){
12063 * Queues a new task.
12064 * @param {Object} task
12066 this.start = function(task){
12068 task.taskStartTime = new Date().getTime();
12069 task.taskRunTime = 0;
12070 task.taskRunCount = 0;
12075 this.stop = function(task){
12080 this.stopAll = function(){
12082 for(var i = 0, len = tasks.length; i < len; i++){
12083 if(tasks[i].onStop){
12092 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12094 * Ext JS Library 1.1.1
12095 * Copyright(c) 2006-2007, Ext JS, LLC.
12097 * Originally Released Under LGPL - original licence link has changed is not relivant.
12100 * <script type="text/javascript">
12105 * @class Roo.util.MixedCollection
12106 * @extends Roo.util.Observable
12107 * A Collection class that maintains both numeric indexes and keys and exposes events.
12109 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12110 * collection (defaults to false)
12111 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12112 * and return the key value for that item. This is used when available to look up the key on items that
12113 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12114 * equivalent to providing an implementation for the {@link #getKey} method.
12116 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12124 * Fires when the collection is cleared.
12129 * Fires when an item is added to the collection.
12130 * @param {Number} index The index at which the item was added.
12131 * @param {Object} o The item added.
12132 * @param {String} key The key associated with the added item.
12137 * Fires when an item is replaced in the collection.
12138 * @param {String} key he key associated with the new added.
12139 * @param {Object} old The item being replaced.
12140 * @param {Object} new The new item.
12145 * Fires when an item is removed from the collection.
12146 * @param {Object} o The item being removed.
12147 * @param {String} key (optional) The key associated with the removed item.
12152 this.allowFunctions = allowFunctions === true;
12154 this.getKey = keyFn;
12156 Roo.util.MixedCollection.superclass.constructor.call(this);
12159 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12160 allowFunctions : false,
12163 * Adds an item to the collection.
12164 * @param {String} key The key to associate with the item
12165 * @param {Object} o The item to add.
12166 * @return {Object} The item added.
12168 add : function(key, o){
12169 if(arguments.length == 1){
12171 key = this.getKey(o);
12173 if(typeof key == "undefined" || key === null){
12175 this.items.push(o);
12176 this.keys.push(null);
12178 var old = this.map[key];
12180 return this.replace(key, o);
12183 this.items.push(o);
12185 this.keys.push(key);
12187 this.fireEvent("add", this.length-1, o, key);
12192 * MixedCollection has a generic way to fetch keys if you implement getKey.
12195 var mc = new Roo.util.MixedCollection();
12196 mc.add(someEl.dom.id, someEl);
12197 mc.add(otherEl.dom.id, otherEl);
12201 var mc = new Roo.util.MixedCollection();
12202 mc.getKey = function(el){
12208 // or via the constructor
12209 var mc = new Roo.util.MixedCollection(false, function(el){
12215 * @param o {Object} The item for which to find the key.
12216 * @return {Object} The key for the passed item.
12218 getKey : function(o){
12223 * Replaces an item in the collection.
12224 * @param {String} key The key associated with the item to replace, or the item to replace.
12225 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12226 * @return {Object} The new item.
12228 replace : function(key, o){
12229 if(arguments.length == 1){
12231 key = this.getKey(o);
12233 var old = this.item(key);
12234 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12235 return this.add(key, o);
12237 var index = this.indexOfKey(key);
12238 this.items[index] = o;
12240 this.fireEvent("replace", key, old, o);
12245 * Adds all elements of an Array or an Object to the collection.
12246 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12247 * an Array of values, each of which are added to the collection.
12249 addAll : function(objs){
12250 if(arguments.length > 1 || objs instanceof Array){
12251 var args = arguments.length > 1 ? arguments : objs;
12252 for(var i = 0, len = args.length; i < len; i++){
12256 for(var key in objs){
12257 if(this.allowFunctions || typeof objs[key] != "function"){
12258 this.add(key, objs[key]);
12265 * Executes the specified function once for every item in the collection, passing each
12266 * item as the first and only parameter. returning false from the function will stop the iteration.
12267 * @param {Function} fn The function to execute for each item.
12268 * @param {Object} scope (optional) The scope in which to execute the function.
12270 each : function(fn, scope){
12271 var items = [].concat(this.items); // each safe for removal
12272 for(var i = 0, len = items.length; i < len; i++){
12273 if(fn.call(scope || items[i], items[i], i, len) === false){
12280 * Executes the specified function once for every key in the collection, passing each
12281 * key, and its associated item as the first two parameters.
12282 * @param {Function} fn The function to execute for each item.
12283 * @param {Object} scope (optional) The scope in which to execute the function.
12285 eachKey : function(fn, scope){
12286 for(var i = 0, len = this.keys.length; i < len; i++){
12287 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12292 * Returns the first item in the collection which elicits a true return value from the
12293 * passed selection function.
12294 * @param {Function} fn The selection function to execute for each item.
12295 * @param {Object} scope (optional) The scope in which to execute the function.
12296 * @return {Object} The first item in the collection which returned true from the selection function.
12298 find : function(fn, scope){
12299 for(var i = 0, len = this.items.length; i < len; i++){
12300 if(fn.call(scope || window, this.items[i], this.keys[i])){
12301 return this.items[i];
12308 * Inserts an item at the specified index in the collection.
12309 * @param {Number} index The index to insert the item at.
12310 * @param {String} key The key to associate with the new item, or the item itself.
12311 * @param {Object} o (optional) If the second parameter was a key, the new item.
12312 * @return {Object} The item inserted.
12314 insert : function(index, key, o){
12315 if(arguments.length == 2){
12317 key = this.getKey(o);
12319 if(index >= this.length){
12320 return this.add(key, o);
12323 this.items.splice(index, 0, o);
12324 if(typeof key != "undefined" && key != null){
12327 this.keys.splice(index, 0, key);
12328 this.fireEvent("add", index, o, key);
12333 * Removed an item from the collection.
12334 * @param {Object} o The item to remove.
12335 * @return {Object} The item removed.
12337 remove : function(o){
12338 return this.removeAt(this.indexOf(o));
12342 * Remove an item from a specified index in the collection.
12343 * @param {Number} index The index within the collection of the item to remove.
12345 removeAt : function(index){
12346 if(index < this.length && index >= 0){
12348 var o = this.items[index];
12349 this.items.splice(index, 1);
12350 var key = this.keys[index];
12351 if(typeof key != "undefined"){
12352 delete this.map[key];
12354 this.keys.splice(index, 1);
12355 this.fireEvent("remove", o, key);
12360 * Removed an item associated with the passed key fom the collection.
12361 * @param {String} key The key of the item to remove.
12363 removeKey : function(key){
12364 return this.removeAt(this.indexOfKey(key));
12368 * Returns the number of items in the collection.
12369 * @return {Number} the number of items in the collection.
12371 getCount : function(){
12372 return this.length;
12376 * Returns index within the collection of the passed Object.
12377 * @param {Object} o The item to find the index of.
12378 * @return {Number} index of the item.
12380 indexOf : function(o){
12381 if(!this.items.indexOf){
12382 for(var i = 0, len = this.items.length; i < len; i++){
12383 if(this.items[i] == o) return i;
12387 return this.items.indexOf(o);
12392 * Returns index within the collection of the passed key.
12393 * @param {String} key The key to find the index of.
12394 * @return {Number} index of the key.
12396 indexOfKey : function(key){
12397 if(!this.keys.indexOf){
12398 for(var i = 0, len = this.keys.length; i < len; i++){
12399 if(this.keys[i] == key) return i;
12403 return this.keys.indexOf(key);
12408 * Returns the item associated with the passed key OR index. Key has priority over index.
12409 * @param {String/Number} key The key or index of the item.
12410 * @return {Object} The item associated with the passed key.
12412 item : function(key){
12413 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12414 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12418 * Returns the item at the specified index.
12419 * @param {Number} index The index of the item.
12422 itemAt : function(index){
12423 return this.items[index];
12427 * Returns the item associated with the passed key.
12428 * @param {String/Number} key The key of the item.
12429 * @return {Object} The item associated with the passed key.
12431 key : function(key){
12432 return this.map[key];
12436 * Returns true if the collection contains the passed Object as an item.
12437 * @param {Object} o The Object to look for in the collection.
12438 * @return {Boolean} True if the collection contains the Object as an item.
12440 contains : function(o){
12441 return this.indexOf(o) != -1;
12445 * Returns true if the collection contains the passed Object as a key.
12446 * @param {String} key The key to look for in the collection.
12447 * @return {Boolean} True if the collection contains the Object as a key.
12449 containsKey : function(key){
12450 return typeof this.map[key] != "undefined";
12454 * Removes all items from the collection.
12456 clear : function(){
12461 this.fireEvent("clear");
12465 * Returns the first item in the collection.
12466 * @return {Object} the first item in the collection..
12468 first : function(){
12469 return this.items[0];
12473 * Returns the last item in the collection.
12474 * @return {Object} the last item in the collection..
12477 return this.items[this.length-1];
12480 _sort : function(property, dir, fn){
12481 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12482 fn = fn || function(a, b){
12485 var c = [], k = this.keys, items = this.items;
12486 for(var i = 0, len = items.length; i < len; i++){
12487 c[c.length] = {key: k[i], value: items[i], index: i};
12489 c.sort(function(a, b){
12490 var v = fn(a[property], b[property]) * dsc;
12492 v = (a.index < b.index ? -1 : 1);
12496 for(var i = 0, len = c.length; i < len; i++){
12497 items[i] = c[i].value;
12500 this.fireEvent("sort", this);
12504 * Sorts this collection with the passed comparison function
12505 * @param {String} direction (optional) "ASC" or "DESC"
12506 * @param {Function} fn (optional) comparison function
12508 sort : function(dir, fn){
12509 this._sort("value", dir, fn);
12513 * Sorts this collection by keys
12514 * @param {String} direction (optional) "ASC" or "DESC"
12515 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12517 keySort : function(dir, fn){
12518 this._sort("key", dir, fn || function(a, b){
12519 return String(a).toUpperCase()-String(b).toUpperCase();
12524 * Returns a range of items in this collection
12525 * @param {Number} startIndex (optional) defaults to 0
12526 * @param {Number} endIndex (optional) default to the last item
12527 * @return {Array} An array of items
12529 getRange : function(start, end){
12530 var items = this.items;
12531 if(items.length < 1){
12534 start = start || 0;
12535 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12538 for(var i = start; i <= end; i++) {
12539 r[r.length] = items[i];
12542 for(var i = start; i >= end; i--) {
12543 r[r.length] = items[i];
12550 * Filter the <i>objects</i> in this collection by a specific property.
12551 * Returns a new collection that has been filtered.
12552 * @param {String} property A property on your objects
12553 * @param {String/RegExp} value Either string that the property values
12554 * should start with or a RegExp to test against the property
12555 * @return {MixedCollection} The new filtered collection
12557 filter : function(property, value){
12558 if(!value.exec){ // not a regex
12559 value = String(value);
12560 if(value.length == 0){
12561 return this.clone();
12563 value = new RegExp("^" + Roo.escapeRe(value), "i");
12565 return this.filterBy(function(o){
12566 return o && value.test(o[property]);
12571 * Filter by a function. * Returns a new collection that has been filtered.
12572 * The passed function will be called with each
12573 * object in the collection. If the function returns true, the value is included
12574 * otherwise it is filtered.
12575 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12576 * @param {Object} scope (optional) The scope of the function (defaults to this)
12577 * @return {MixedCollection} The new filtered collection
12579 filterBy : function(fn, scope){
12580 var r = new Roo.util.MixedCollection();
12581 r.getKey = this.getKey;
12582 var k = this.keys, it = this.items;
12583 for(var i = 0, len = it.length; i < len; i++){
12584 if(fn.call(scope||this, it[i], k[i])){
12585 r.add(k[i], it[i]);
12592 * Creates a duplicate of this collection
12593 * @return {MixedCollection}
12595 clone : function(){
12596 var r = new Roo.util.MixedCollection();
12597 var k = this.keys, it = this.items;
12598 for(var i = 0, len = it.length; i < len; i++){
12599 r.add(k[i], it[i]);
12601 r.getKey = this.getKey;
12606 * Returns the item associated with the passed key or index.
12608 * @param {String/Number} key The key or index of the item.
12609 * @return {Object} The item associated with the passed key.
12611 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12613 * Ext JS Library 1.1.1
12614 * Copyright(c) 2006-2007, Ext JS, LLC.
12616 * Originally Released Under LGPL - original licence link has changed is not relivant.
12619 * <script type="text/javascript">
12622 * @class Roo.util.JSON
12623 * Modified version of Douglas Crockford"s json.js that doesn"t
12624 * mess with the Object prototype
12625 * http://www.json.org/js.html
12628 Roo.util.JSON = new (function(){
12629 var useHasOwn = {}.hasOwnProperty ? true : false;
12631 // crashes Safari in some instances
12632 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12634 var pad = function(n) {
12635 return n < 10 ? "0" + n : n;
12648 var encodeString = function(s){
12649 if (/["\\\x00-\x1f]/.test(s)) {
12650 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12655 c = b.charCodeAt();
12657 Math.floor(c / 16).toString(16) +
12658 (c % 16).toString(16);
12661 return '"' + s + '"';
12664 var encodeArray = function(o){
12665 var a = ["["], b, i, l = o.length, v;
12666 for (i = 0; i < l; i += 1) {
12668 switch (typeof v) {
12677 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12685 var encodeDate = function(o){
12686 return '"' + o.getFullYear() + "-" +
12687 pad(o.getMonth() + 1) + "-" +
12688 pad(o.getDate()) + "T" +
12689 pad(o.getHours()) + ":" +
12690 pad(o.getMinutes()) + ":" +
12691 pad(o.getSeconds()) + '"';
12695 * Encodes an Object, Array or other value
12696 * @param {Mixed} o The variable to encode
12697 * @return {String} The JSON string
12699 this.encode = function(o){
12700 if(typeof o == "undefined" || o === null){
12702 }else if(o instanceof Array){
12703 return encodeArray(o);
12704 }else if(o instanceof Date){
12705 return encodeDate(o);
12706 }else if(typeof o == "string"){
12707 return encodeString(o);
12708 }else if(typeof o == "number"){
12709 return isFinite(o) ? String(o) : "null";
12710 }else if(typeof o == "boolean"){
12713 var a = ["{"], b, i, v;
12715 if(!useHasOwn || o.hasOwnProperty(i)) {
12717 switch (typeof v) {
12726 a.push(this.encode(i), ":",
12727 v === null ? "null" : this.encode(v));
12738 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12739 * @param {String} json The JSON string
12740 * @return {Object} The resulting object
12742 this.decode = function(json){
12746 return eval("(" + json + ')');
12750 * Shorthand for {@link Roo.util.JSON#encode}
12751 * @member Roo encode
12753 Roo.encode = Roo.util.JSON.encode;
12755 * Shorthand for {@link Roo.util.JSON#decode}
12756 * @member Roo decode
12758 Roo.decode = Roo.util.JSON.decode;
12761 * Ext JS Library 1.1.1
12762 * Copyright(c) 2006-2007, Ext JS, LLC.
12764 * Originally Released Under LGPL - original licence link has changed is not relivant.
12767 * <script type="text/javascript">
12771 * @class Roo.util.Format
12772 * Reusable data formatting functions
12775 Roo.util.Format = function(){
12776 var trimRe = /^\s+|\s+$/g;
12779 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12780 * @param {String} value The string to truncate
12781 * @param {Number} length The maximum length to allow before truncating
12782 * @return {String} The converted text
12784 ellipsis : function(value, len){
12785 if(value && value.length > len){
12786 return value.substr(0, len-3)+"...";
12792 * Checks a reference and converts it to empty string if it is undefined
12793 * @param {Mixed} value Reference to check
12794 * @return {Mixed} Empty string if converted, otherwise the original value
12796 undef : function(value){
12797 return typeof value != "undefined" ? value : "";
12801 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12802 * @param {String} value The string to encode
12803 * @return {String} The encoded text
12805 htmlEncode : function(value){
12806 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12810 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12811 * @param {String} value The string to decode
12812 * @return {String} The decoded text
12814 htmlDecode : function(value){
12815 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12819 * Trims any whitespace from either side of a string
12820 * @param {String} value The text to trim
12821 * @return {String} The trimmed text
12823 trim : function(value){
12824 return String(value).replace(trimRe, "");
12828 * Returns a substring from within an original string
12829 * @param {String} value The original text
12830 * @param {Number} start The start index of the substring
12831 * @param {Number} length The length of the substring
12832 * @return {String} The substring
12834 substr : function(value, start, length){
12835 return String(value).substr(start, length);
12839 * Converts a string to all lower case letters
12840 * @param {String} value The text to convert
12841 * @return {String} The converted text
12843 lowercase : function(value){
12844 return String(value).toLowerCase();
12848 * Converts a string to all upper case letters
12849 * @param {String} value The text to convert
12850 * @return {String} The converted text
12852 uppercase : function(value){
12853 return String(value).toUpperCase();
12857 * Converts the first character only of a string to upper case
12858 * @param {String} value The text to convert
12859 * @return {String} The converted text
12861 capitalize : function(value){
12862 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
12866 call : function(value, fn){
12867 if(arguments.length > 2){
12868 var args = Array.prototype.slice.call(arguments, 2);
12869 args.unshift(value);
12871 return /** eval:var:value */ eval(fn).apply(window, args);
12873 /** eval:var:value */
12874 return /** eval:var:value */ eval(fn).call(window, value);
12879 * Format a number as US currency
12880 * @param {Number/String} value The numeric value to format
12881 * @return {String} The formatted currency string
12883 usMoney : function(v){
12884 v = (Math.round((v-0)*100))/100;
12885 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
12887 var ps = v.split('.');
12889 var sub = ps[1] ? '.'+ ps[1] : '.00';
12890 var r = /(\d+)(\d{3})/;
12891 while (r.test(whole)) {
12892 whole = whole.replace(r, '$1' + ',' + '$2');
12894 return "$" + whole + sub ;
12898 * Parse a value into a formatted date using the specified format pattern.
12899 * @param {Mixed} value The value to format
12900 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
12901 * @return {String} The formatted date string
12903 date : function(v, format){
12907 if(!(v instanceof Date)){
12908 v = new Date(Date.parse(v));
12910 return v.dateFormat(format || "m/d/Y");
12914 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
12915 * @param {String} format Any valid date format string
12916 * @return {Function} The date formatting function
12918 dateRenderer : function(format){
12919 return function(v){
12920 return Roo.util.Format.date(v, format);
12925 stripTagsRE : /<\/?[^>]+>/gi,
12928 * Strips all HTML tags
12929 * @param {Mixed} value The text from which to strip tags
12930 * @return {String} The stripped text
12932 stripTags : function(v){
12933 return !v ? v : String(v).replace(this.stripTagsRE, "");
12938 * Ext JS Library 1.1.1
12939 * Copyright(c) 2006-2007, Ext JS, LLC.
12941 * Originally Released Under LGPL - original licence link has changed is not relivant.
12944 * <script type="text/javascript">
12951 * @class Roo.MasterTemplate
12952 * @extends Roo.Template
12953 * Provides a template that can have child templates. The syntax is:
12955 var t = new Roo.MasterTemplate(
12956 '<select name="{name}">',
12957 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
12960 t.add('options', {value: 'foo', text: 'bar'});
12961 // or you can add multiple child elements in one shot
12962 t.addAll('options', [
12963 {value: 'foo', text: 'bar'},
12964 {value: 'foo2', text: 'bar2'},
12965 {value: 'foo3', text: 'bar3'}
12967 // then append, applying the master template values
12968 t.append('my-form', {name: 'my-select'});
12970 * A name attribute for the child template is not required if you have only one child
12971 * template or you want to refer to them by index.
12973 Roo.MasterTemplate = function(){
12974 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
12975 this.originalHtml = this.html;
12977 var m, re = this.subTemplateRe;
12980 while(m = re.exec(this.html)){
12981 var name = m[1], content = m[2];
12986 tpl : new Roo.Template(content)
12989 st[name] = st[subIndex];
12991 st[subIndex].tpl.compile();
12992 st[subIndex].tpl.call = this.call.createDelegate(this);
12995 this.subCount = subIndex;
12998 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13000 * The regular expression used to match sub templates
13004 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13007 * Applies the passed values to a child template.
13008 * @param {String/Number} name (optional) The name or index of the child template
13009 * @param {Array/Object} values The values to be applied to the template
13010 * @return {MasterTemplate} this
13012 add : function(name, values){
13013 if(arguments.length == 1){
13014 values = arguments[0];
13017 var s = this.subs[name];
13018 s.buffer[s.buffer.length] = s.tpl.apply(values);
13023 * Applies all the passed values to a child template.
13024 * @param {String/Number} name (optional) The name or index of the child template
13025 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13026 * @param {Boolean} reset (optional) True to reset the template first
13027 * @return {MasterTemplate} this
13029 fill : function(name, values, reset){
13031 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13039 for(var i = 0, len = values.length; i < len; i++){
13040 this.add(name, values[i]);
13046 * Resets the template for reuse
13047 * @return {MasterTemplate} this
13049 reset : function(){
13051 for(var i = 0; i < this.subCount; i++){
13057 applyTemplate : function(values){
13059 var replaceIndex = -1;
13060 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13061 return s[++replaceIndex].buffer.join("");
13063 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13066 apply : function(){
13067 return this.applyTemplate.apply(this, arguments);
13070 compile : function(){return this;}
13074 * Alias for fill().
13077 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13079 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13080 * var tpl = Roo.MasterTemplate.from('element-id');
13081 * @param {String/HTMLElement} el
13082 * @param {Object} config
13085 Roo.MasterTemplate.from = function(el, config){
13086 el = Roo.getDom(el);
13087 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13090 * Ext JS Library 1.1.1
13091 * Copyright(c) 2006-2007, Ext JS, LLC.
13093 * Originally Released Under LGPL - original licence link has changed is not relivant.
13096 * <script type="text/javascript">
13101 * @class Roo.util.CSS
13102 * Utility class for manipulating CSS rules
13105 Roo.util.CSS = function(){
13107 var doc = document;
13109 var camelRe = /(-[a-z])/gi;
13110 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13114 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13115 * tag and appended to the HEAD of the document.
13116 * @param {String} cssText The text containing the css rules
13117 * @param {String} id An id to add to the stylesheet for later removal
13118 * @return {StyleSheet}
13120 createStyleSheet : function(cssText, id){
13122 var head = doc.getElementsByTagName("head")[0];
13123 var rules = doc.createElement("style");
13124 rules.setAttribute("type", "text/css");
13126 rules.setAttribute("id", id);
13129 head.appendChild(rules);
13130 ss = rules.styleSheet;
13131 ss.cssText = cssText;
13134 rules.appendChild(doc.createTextNode(cssText));
13136 rules.cssText = cssText;
13138 head.appendChild(rules);
13139 ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13141 this.cacheStyleSheet(ss);
13146 * Removes a style or link tag by id
13147 * @param {String} id The id of the tag
13149 removeStyleSheet : function(id){
13150 var existing = doc.getElementById(id);
13152 existing.parentNode.removeChild(existing);
13157 * Dynamically swaps an existing stylesheet reference for a new one
13158 * @param {String} id The id of an existing link tag to remove
13159 * @param {String} url The href of the new stylesheet to include
13161 swapStyleSheet : function(id, url){
13162 this.removeStyleSheet(id);
13163 var ss = doc.createElement("link");
13164 ss.setAttribute("rel", "stylesheet");
13165 ss.setAttribute("type", "text/css");
13166 ss.setAttribute("id", id);
13167 ss.setAttribute("href", url);
13168 doc.getElementsByTagName("head")[0].appendChild(ss);
13172 * Refresh the rule cache if you have dynamically added stylesheets
13173 * @return {Object} An object (hash) of rules indexed by selector
13175 refreshCache : function(){
13176 return this.getRules(true);
13180 cacheStyleSheet : function(ss){
13184 try{// try catch for cross domain access issue
13185 var ssRules = ss.cssRules || ss.rules;
13186 for(var j = ssRules.length-1; j >= 0; --j){
13187 rules[ssRules[j].selectorText] = ssRules[j];
13193 * Gets all css rules for the document
13194 * @param {Boolean} refreshCache true to refresh the internal cache
13195 * @return {Object} An object (hash) of rules indexed by selector
13197 getRules : function(refreshCache){
13198 if(rules == null || refreshCache){
13200 var ds = doc.styleSheets;
13201 for(var i =0, len = ds.length; i < len; i++){
13203 this.cacheStyleSheet(ds[i]);
13211 * Gets an an individual CSS rule by selector(s)
13212 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13213 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13214 * @return {CSSRule} The CSS rule or null if one is not found
13216 getRule : function(selector, refreshCache){
13217 var rs = this.getRules(refreshCache);
13218 if(!(selector instanceof Array)){
13219 return rs[selector];
13221 for(var i = 0; i < selector.length; i++){
13222 if(rs[selector[i]]){
13223 return rs[selector[i]];
13231 * Updates a rule property
13232 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13233 * @param {String} property The css property
13234 * @param {String} value The new value for the property
13235 * @return {Boolean} true If a rule was found and updated
13237 updateRule : function(selector, property, value){
13238 if(!(selector instanceof Array)){
13239 var rule = this.getRule(selector);
13241 rule.style[property.replace(camelRe, camelFn)] = value;
13245 for(var i = 0; i < selector.length; i++){
13246 if(this.updateRule(selector[i], property, value)){
13256 * Ext JS Library 1.1.1
13257 * Copyright(c) 2006-2007, Ext JS, LLC.
13259 * Originally Released Under LGPL - original licence link has changed is not relivant.
13262 * <script type="text/javascript">
13268 * @class Roo.util.ClickRepeater
13269 * @extends Roo.util.Observable
13271 * A wrapper class which can be applied to any element. Fires a "click" event while the
13272 * mouse is pressed. The interval between firings may be specified in the config but
13273 * defaults to 10 milliseconds.
13275 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13277 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13278 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13279 * Similar to an autorepeat key delay.
13280 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13281 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13282 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13283 * "interval" and "delay" are ignored. "immediate" is honored.
13284 * @cfg {Boolean} preventDefault True to prevent the default click event
13285 * @cfg {Boolean} stopDefault True to stop the default click event
13288 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13289 * 2007-02-02 jvs Renamed to ClickRepeater
13290 * 2007-02-03 jvs Modifications for FF Mac and Safari
13293 * @param {String/HTMLElement/Element} el The element to listen on
13294 * @param {Object} config
13296 Roo.util.ClickRepeater = function(el, config)
13298 this.el = Roo.get(el);
13299 this.el.unselectable();
13301 Roo.apply(this, config);
13306 * Fires when the mouse button is depressed.
13307 * @param {Roo.util.ClickRepeater} this
13309 "mousedown" : true,
13312 * Fires on a specified interval during the time the element is pressed.
13313 * @param {Roo.util.ClickRepeater} this
13318 * Fires when the mouse key is released.
13319 * @param {Roo.util.ClickRepeater} this
13324 this.el.on("mousedown", this.handleMouseDown, this);
13325 if(this.preventDefault || this.stopDefault){
13326 this.el.on("click", function(e){
13327 if(this.preventDefault){
13328 e.preventDefault();
13330 if(this.stopDefault){
13336 // allow inline handler
13338 this.on("click", this.handler, this.scope || this);
13341 Roo.util.ClickRepeater.superclass.constructor.call(this);
13344 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13347 preventDefault : true,
13348 stopDefault : false,
13352 handleMouseDown : function(){
13353 clearTimeout(this.timer);
13355 if(this.pressClass){
13356 this.el.addClass(this.pressClass);
13358 this.mousedownTime = new Date();
13360 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13361 this.el.on("mouseout", this.handleMouseOut, this);
13363 this.fireEvent("mousedown", this);
13364 this.fireEvent("click", this);
13366 this.timer = this.click.defer(this.delay || this.interval, this);
13370 click : function(){
13371 this.fireEvent("click", this);
13372 this.timer = this.click.defer(this.getInterval(), this);
13376 getInterval: function(){
13377 if(!this.accelerate){
13378 return this.interval;
13380 var pressTime = this.mousedownTime.getElapsed();
13381 if(pressTime < 500){
13383 }else if(pressTime < 1700){
13385 }else if(pressTime < 2600){
13387 }else if(pressTime < 3500){
13389 }else if(pressTime < 4400){
13391 }else if(pressTime < 5300){
13393 }else if(pressTime < 6200){
13401 handleMouseOut : function(){
13402 clearTimeout(this.timer);
13403 if(this.pressClass){
13404 this.el.removeClass(this.pressClass);
13406 this.el.on("mouseover", this.handleMouseReturn, this);
13410 handleMouseReturn : function(){
13411 this.el.un("mouseover", this.handleMouseReturn);
13412 if(this.pressClass){
13413 this.el.addClass(this.pressClass);
13419 handleMouseUp : function(){
13420 clearTimeout(this.timer);
13421 this.el.un("mouseover", this.handleMouseReturn);
13422 this.el.un("mouseout", this.handleMouseOut);
13423 Roo.get(document).un("mouseup", this.handleMouseUp);
13424 this.el.removeClass(this.pressClass);
13425 this.fireEvent("mouseup", this);
13429 * Ext JS Library 1.1.1
13430 * Copyright(c) 2006-2007, Ext JS, LLC.
13432 * Originally Released Under LGPL - original licence link has changed is not relivant.
13435 * <script type="text/javascript">
13440 * @class Roo.KeyNav
13441 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13442 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13443 * way to implement custom navigation schemes for any UI component.</p>
13444 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13445 * pageUp, pageDown, del, home, end. Usage:</p>
13447 var nav = new Roo.KeyNav("my-element", {
13448 "left" : function(e){
13449 this.moveLeft(e.ctrlKey);
13451 "right" : function(e){
13452 this.moveRight(e.ctrlKey);
13454 "enter" : function(e){
13461 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13462 * @param {Object} config The config
13464 Roo.KeyNav = function(el, config){
13465 this.el = Roo.get(el);
13466 Roo.apply(this, config);
13467 if(!this.disabled){
13468 this.disabled = true;
13473 Roo.KeyNav.prototype = {
13475 * @cfg {Boolean} disabled
13476 * True to disable this KeyNav instance (defaults to false)
13480 * @cfg {String} defaultEventAction
13481 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13482 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13483 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13485 defaultEventAction: "stopEvent",
13487 * @cfg {Boolean} forceKeyDown
13488 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13489 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13490 * handle keydown instead of keypress.
13492 forceKeyDown : false,
13495 prepareEvent : function(e){
13496 var k = e.getKey();
13497 var h = this.keyToHandler[k];
13498 //if(h && this[h]){
13499 // e.stopPropagation();
13501 if(Roo.isSafari && h && k >= 37 && k <= 40){
13507 relay : function(e){
13508 var k = e.getKey();
13509 var h = this.keyToHandler[k];
13511 if(this.doRelay(e, this[h], h) !== true){
13512 e[this.defaultEventAction]();
13518 doRelay : function(e, h, hname){
13519 return h.call(this.scope || this, e);
13522 // possible handlers
13536 // quick lookup hash
13553 * Enable this KeyNav
13555 enable: function(){
13557 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13558 // the EventObject will normalize Safari automatically
13559 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13560 this.el.on("keydown", this.relay, this);
13562 this.el.on("keydown", this.prepareEvent, this);
13563 this.el.on("keypress", this.relay, this);
13565 this.disabled = false;
13570 * Disable this KeyNav
13572 disable: function(){
13573 if(!this.disabled){
13574 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13575 this.el.un("keydown", this.relay);
13577 this.el.un("keydown", this.prepareEvent);
13578 this.el.un("keypress", this.relay);
13580 this.disabled = true;
13585 * Ext JS Library 1.1.1
13586 * Copyright(c) 2006-2007, Ext JS, LLC.
13588 * Originally Released Under LGPL - original licence link has changed is not relivant.
13591 * <script type="text/javascript">
13596 * @class Roo.KeyMap
13597 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13598 * The constructor accepts the same config object as defined by {@link #addBinding}.
13599 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13600 * combination it will call the function with this signature (if the match is a multi-key
13601 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13602 * A KeyMap can also handle a string representation of keys.<br />
13605 // map one key by key code
13606 var map = new Roo.KeyMap("my-element", {
13607 key: 13, // or Roo.EventObject.ENTER
13612 // map multiple keys to one action by string
13613 var map = new Roo.KeyMap("my-element", {
13619 // map multiple keys to multiple actions by strings and array of codes
13620 var map = new Roo.KeyMap("my-element", [
13623 fn: function(){ alert("Return was pressed"); }
13626 fn: function(){ alert('a, b or c was pressed'); }
13631 fn: function(){ alert('Control + shift + tab was pressed.'); }
13635 * <b>Note: A KeyMap starts enabled</b>
13637 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13638 * @param {Object} config The config (see {@link #addBinding})
13639 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13641 Roo.KeyMap = function(el, config, eventName){
13642 this.el = Roo.get(el);
13643 this.eventName = eventName || "keydown";
13644 this.bindings = [];
13646 this.addBinding(config);
13651 Roo.KeyMap.prototype = {
13653 * True to stop the event from bubbling and prevent the default browser action if the
13654 * key was handled by the KeyMap (defaults to false)
13660 * Add a new binding to this KeyMap. The following config object properties are supported:
13662 Property Type Description
13663 ---------- --------------- ----------------------------------------------------------------------
13664 key String/Array A single keycode or an array of keycodes to handle
13665 shift Boolean True to handle key only when shift is pressed (defaults to false)
13666 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13667 alt Boolean True to handle key only when alt is pressed (defaults to false)
13668 fn Function The function to call when KeyMap finds the expected key combination
13669 scope Object The scope of the callback function
13675 var map = new Roo.KeyMap(document, {
13676 key: Roo.EventObject.ENTER,
13681 //Add a new binding to the existing KeyMap later
13689 * @param {Object/Array} config A single KeyMap config or an array of configs
13691 addBinding : function(config){
13692 if(config instanceof Array){
13693 for(var i = 0, len = config.length; i < len; i++){
13694 this.addBinding(config[i]);
13698 var keyCode = config.key,
13699 shift = config.shift,
13700 ctrl = config.ctrl,
13703 scope = config.scope;
13704 if(typeof keyCode == "string"){
13706 var keyString = keyCode.toUpperCase();
13707 for(var j = 0, len = keyString.length; j < len; j++){
13708 ks.push(keyString.charCodeAt(j));
13712 var keyArray = keyCode instanceof Array;
13713 var handler = function(e){
13714 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13715 var k = e.getKey();
13717 for(var i = 0, len = keyCode.length; i < len; i++){
13718 if(keyCode[i] == k){
13719 if(this.stopEvent){
13722 fn.call(scope || window, k, e);
13728 if(this.stopEvent){
13731 fn.call(scope || window, k, e);
13736 this.bindings.push(handler);
13740 * Shorthand for adding a single key listener
13741 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13742 * following options:
13743 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13744 * @param {Function} fn The function to call
13745 * @param {Object} scope (optional) The scope of the function
13747 on : function(key, fn, scope){
13748 var keyCode, shift, ctrl, alt;
13749 if(typeof key == "object" && !(key instanceof Array)){
13768 handleKeyDown : function(e){
13769 if(this.enabled){ //just in case
13770 var b = this.bindings;
13771 for(var i = 0, len = b.length; i < len; i++){
13772 b[i].call(this, e);
13778 * Returns true if this KeyMap is enabled
13779 * @return {Boolean}
13781 isEnabled : function(){
13782 return this.enabled;
13786 * Enables this KeyMap
13788 enable: function(){
13790 this.el.on(this.eventName, this.handleKeyDown, this);
13791 this.enabled = true;
13796 * Disable this KeyMap
13798 disable: function(){
13800 this.el.removeListener(this.eventName, this.handleKeyDown, this);
13801 this.enabled = false;
13806 * Ext JS Library 1.1.1
13807 * Copyright(c) 2006-2007, Ext JS, LLC.
13809 * Originally Released Under LGPL - original licence link has changed is not relivant.
13812 * <script type="text/javascript">
13817 * @class Roo.util.TextMetrics
13818 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
13819 * wide, in pixels, a given block of text will be.
13822 Roo.util.TextMetrics = function(){
13826 * Measures the size of the specified text
13827 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
13828 * that can affect the size of the rendered text
13829 * @param {String} text The text to measure
13830 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13831 * in order to accurately measure the text height
13832 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13834 measure : function(el, text, fixedWidth){
13836 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
13839 shared.setFixedWidth(fixedWidth || 'auto');
13840 return shared.getSize(text);
13844 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
13845 * the overhead of multiple calls to initialize the style properties on each measurement.
13846 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
13847 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13848 * in order to accurately measure the text height
13849 * @return {Roo.util.TextMetrics.Instance} instance The new instance
13851 createInstance : function(el, fixedWidth){
13852 return Roo.util.TextMetrics.Instance(el, fixedWidth);
13857 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
13858 var ml = new Roo.Element(document.createElement('div'));
13859 document.body.appendChild(ml.dom);
13860 ml.position('absolute');
13861 ml.setLeftTop(-1000, -1000);
13865 ml.setWidth(fixedWidth);
13870 * Returns the size of the specified text based on the internal element's style and width properties
13871 * @param {String} text The text to measure
13872 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13874 getSize : function(text){
13876 var s = ml.getSize();
13882 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
13883 * that can affect the size of the rendered text
13884 * @param {String/HTMLElement} el The element, dom node or id
13886 bind : function(el){
13888 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
13893 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
13894 * to set a fixed width in order to accurately measure the text height.
13895 * @param {Number} width The width to set on the element
13897 setFixedWidth : function(width){
13898 ml.setWidth(width);
13902 * Returns the measured width of the specified text
13903 * @param {String} text The text to measure
13904 * @return {Number} width The width in pixels
13906 getWidth : function(text){
13907 ml.dom.style.width = 'auto';
13908 return this.getSize(text).width;
13912 * Returns the measured height of the specified text. For multiline text, be sure to call
13913 * {@link #setFixedWidth} if necessary.
13914 * @param {String} text The text to measure
13915 * @return {Number} height The height in pixels
13917 getHeight : function(text){
13918 return this.getSize(text).height;
13922 instance.bind(bindTo);
13927 // backwards compat
13928 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
13930 * Ext JS Library 1.1.1
13931 * Copyright(c) 2006-2007, Ext JS, LLC.
13933 * Originally Released Under LGPL - original licence link has changed is not relivant.
13936 * <script type="text/javascript">
13940 * @class Roo.state.Provider
13941 * Abstract base class for state provider implementations. This class provides methods
13942 * for encoding and decoding <b>typed</b> variables including dates and defines the
13943 * Provider interface.
13945 Roo.state.Provider = function(){
13947 * @event statechange
13948 * Fires when a state change occurs.
13949 * @param {Provider} this This state provider
13950 * @param {String} key The state key which was changed
13951 * @param {String} value The encoded value for the state
13954 "statechange": true
13957 Roo.state.Provider.superclass.constructor.call(this);
13959 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
13961 * Returns the current value for a key
13962 * @param {String} name The key name
13963 * @param {Mixed} defaultValue A default value to return if the key's value is not found
13964 * @return {Mixed} The state data
13966 get : function(name, defaultValue){
13967 return typeof this.state[name] == "undefined" ?
13968 defaultValue : this.state[name];
13972 * Clears a value from the state
13973 * @param {String} name The key name
13975 clear : function(name){
13976 delete this.state[name];
13977 this.fireEvent("statechange", this, name, null);
13981 * Sets the value for a key
13982 * @param {String} name The key name
13983 * @param {Mixed} value The value to set
13985 set : function(name, value){
13986 this.state[name] = value;
13987 this.fireEvent("statechange", this, name, value);
13991 * Decodes a string previously encoded with {@link #encodeValue}.
13992 * @param {String} value The value to decode
13993 * @return {Mixed} The decoded value
13995 decodeValue : function(cookie){
13996 var re = /^(a|n|d|b|s|o)\:(.*)$/;
13997 var matches = re.exec(unescape(cookie));
13998 if(!matches || !matches[1]) return; // non state cookie
13999 var type = matches[1];
14000 var v = matches[2];
14003 return parseFloat(v);
14005 return new Date(Date.parse(v));
14010 var values = v.split("^");
14011 for(var i = 0, len = values.length; i < len; i++){
14012 all.push(this.decodeValue(values[i]));
14017 var values = v.split("^");
14018 for(var i = 0, len = values.length; i < len; i++){
14019 var kv = values[i].split("=");
14020 all[kv[0]] = this.decodeValue(kv[1]);
14029 * Encodes a value including type information. Decode with {@link #decodeValue}.
14030 * @param {Mixed} value The value to encode
14031 * @return {String} The encoded value
14033 encodeValue : function(v){
14035 if(typeof v == "number"){
14037 }else if(typeof v == "boolean"){
14038 enc = "b:" + (v ? "1" : "0");
14039 }else if(v instanceof Date){
14040 enc = "d:" + v.toGMTString();
14041 }else if(v instanceof Array){
14043 for(var i = 0, len = v.length; i < len; i++){
14044 flat += this.encodeValue(v[i]);
14045 if(i != len-1) flat += "^";
14048 }else if(typeof v == "object"){
14051 if(typeof v[key] != "function"){
14052 flat += key + "=" + this.encodeValue(v[key]) + "^";
14055 enc = "o:" + flat.substring(0, flat.length-1);
14059 return escape(enc);
14065 * Ext JS Library 1.1.1
14066 * Copyright(c) 2006-2007, Ext JS, LLC.
14068 * Originally Released Under LGPL - original licence link has changed is not relivant.
14071 * <script type="text/javascript">
14074 * @class Roo.state.Manager
14075 * This is the global state manager. By default all components that are "state aware" check this class
14076 * for state information if you don't pass them a custom state provider. In order for this class
14077 * to be useful, it must be initialized with a provider when your application initializes.
14079 // in your initialization function
14081 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14083 // supposed you have a {@link Roo.BorderLayout}
14084 var layout = new Roo.BorderLayout(...);
14085 layout.restoreState();
14086 // or a {Roo.BasicDialog}
14087 var dialog = new Roo.BasicDialog(...);
14088 dialog.restoreState();
14092 Roo.state.Manager = function(){
14093 var provider = new Roo.state.Provider();
14097 * Configures the default state provider for your application
14098 * @param {Provider} stateProvider The state provider to set
14100 setProvider : function(stateProvider){
14101 provider = stateProvider;
14105 * Returns the current value for a key
14106 * @param {String} name The key name
14107 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14108 * @return {Mixed} The state data
14110 get : function(key, defaultValue){
14111 return provider.get(key, defaultValue);
14115 * Sets the value for a key
14116 * @param {String} name The key name
14117 * @param {Mixed} value The state data
14119 set : function(key, value){
14120 provider.set(key, value);
14124 * Clears a value from the state
14125 * @param {String} name The key name
14127 clear : function(key){
14128 provider.clear(key);
14132 * Gets the currently configured state provider
14133 * @return {Provider} The state provider
14135 getProvider : function(){
14142 * Ext JS Library 1.1.1
14143 * Copyright(c) 2006-2007, Ext JS, LLC.
14145 * Originally Released Under LGPL - original licence link has changed is not relivant.
14148 * <script type="text/javascript">
14151 * @class Roo.state.CookieProvider
14152 * @extends Roo.state.Provider
14153 * The default Provider implementation which saves state via cookies.
14156 var cp = new Roo.state.CookieProvider({
14158 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14159 domain: "roojs.com"
14161 Roo.state.Manager.setProvider(cp);
14163 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14164 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14165 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14166 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14167 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14168 * domain the page is running on including the 'www' like 'www.roojs.com')
14169 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14171 * Create a new CookieProvider
14172 * @param {Object} config The configuration object
14174 Roo.state.CookieProvider = function(config){
14175 Roo.state.CookieProvider.superclass.constructor.call(this);
14177 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14178 this.domain = null;
14179 this.secure = false;
14180 Roo.apply(this, config);
14181 this.state = this.readCookies();
14184 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14186 set : function(name, value){
14187 if(typeof value == "undefined" || value === null){
14191 this.setCookie(name, value);
14192 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14196 clear : function(name){
14197 this.clearCookie(name);
14198 Roo.state.CookieProvider.superclass.clear.call(this, name);
14202 readCookies : function(){
14204 var c = document.cookie + ";";
14205 var re = /\s?(.*?)=(.*?);/g;
14207 while((matches = re.exec(c)) != null){
14208 var name = matches[1];
14209 var value = matches[2];
14210 if(name && name.substring(0,3) == "ys-"){
14211 cookies[name.substr(3)] = this.decodeValue(value);
14218 setCookie : function(name, value){
14219 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14220 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14221 ((this.path == null) ? "" : ("; path=" + this.path)) +
14222 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14223 ((this.secure == true) ? "; secure" : "");
14227 clearCookie : function(name){
14228 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14229 ((this.path == null) ? "" : ("; path=" + this.path)) +
14230 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14231 ((this.secure == true) ? "; secure" : "");
14235 * Ext JS Library 1.1.1
14236 * Copyright(c) 2006-2007, Ext JS, LLC.
14238 * Originally Released Under LGPL - original licence link has changed is not relivant.
14241 * <script type="text/javascript">
14247 * These classes are derivatives of the similarly named classes in the YUI Library.
14248 * The original license:
14249 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
14250 * Code licensed under the BSD License:
14251 * http://developer.yahoo.net/yui/license.txt
14256 var Event=Roo.EventManager;
14257 var Dom=Roo.lib.Dom;
14260 * @class Roo.dd.DragDrop
14261 * Defines the interface and base operation of items that that can be
14262 * dragged or can be drop targets. It was designed to be extended, overriding
14263 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
14264 * Up to three html elements can be associated with a DragDrop instance:
14266 * <li>linked element: the element that is passed into the constructor.
14267 * This is the element which defines the boundaries for interaction with
14268 * other DragDrop objects.</li>
14269 * <li>handle element(s): The drag operation only occurs if the element that
14270 * was clicked matches a handle element. By default this is the linked
14271 * element, but there are times that you will want only a portion of the
14272 * linked element to initiate the drag operation, and the setHandleElId()
14273 * method provides a way to define this.</li>
14274 * <li>drag element: this represents the element that would be moved along
14275 * with the cursor during a drag operation. By default, this is the linked
14276 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
14277 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
14280 * This class should not be instantiated until the onload event to ensure that
14281 * the associated elements are available.
14282 * The following would define a DragDrop obj that would interact with any
14283 * other DragDrop obj in the "group1" group:
14285 * dd = new Roo.dd.DragDrop("div1", "group1");
14287 * Since none of the event handlers have been implemented, nothing would
14288 * actually happen if you were to run the code above. Normally you would
14289 * override this class or one of the default implementations, but you can
14290 * also override the methods you want on an instance of the class...
14292 * dd.onDragDrop = function(e, id) {
14293 * alert("dd was dropped on " + id);
14297 * @param {String} id of the element that is linked to this instance
14298 * @param {String} sGroup the group of related DragDrop objects
14299 * @param {object} config an object containing configurable attributes
14300 * Valid properties for DragDrop:
14301 * padding, isTarget, maintainOffset, primaryButtonOnly
14303 Roo.dd.DragDrop = function(id, sGroup, config) {
14305 this.init(id, sGroup, config);
14309 Roo.dd.DragDrop.prototype = {
14312 * The id of the element associated with this object. This is what we
14313 * refer to as the "linked element" because the size and position of
14314 * this element is used to determine when the drag and drop objects have
14322 * Configuration attributes passed into the constructor
14329 * The id of the element that will be dragged. By default this is same
14330 * as the linked element , but could be changed to another element. Ex:
14332 * @property dragElId
14339 * the id of the element that initiates the drag operation. By default
14340 * this is the linked element, but could be changed to be a child of this
14341 * element. This lets us do things like only starting the drag when the
14342 * header element within the linked html element is clicked.
14343 * @property handleElId
14350 * An associative array of HTML tags that will be ignored if clicked.
14351 * @property invalidHandleTypes
14352 * @type {string: string}
14354 invalidHandleTypes: null,
14357 * An associative array of ids for elements that will be ignored if clicked
14358 * @property invalidHandleIds
14359 * @type {string: string}
14361 invalidHandleIds: null,
14364 * An indexted array of css class names for elements that will be ignored
14366 * @property invalidHandleClasses
14369 invalidHandleClasses: null,
14372 * The linked element's absolute X position at the time the drag was
14374 * @property startPageX
14381 * The linked element's absolute X position at the time the drag was
14383 * @property startPageY
14390 * The group defines a logical collection of DragDrop objects that are
14391 * related. Instances only get events when interacting with other
14392 * DragDrop object in the same group. This lets us define multiple
14393 * groups using a single DragDrop subclass if we want.
14395 * @type {string: string}
14400 * Individual drag/drop instances can be locked. This will prevent
14401 * onmousedown start drag.
14409 * Lock this instance
14412 lock: function() { this.locked = true; },
14415 * Unlock this instace
14418 unlock: function() { this.locked = false; },
14421 * By default, all insances can be a drop target. This can be disabled by
14422 * setting isTarget to false.
14429 * The padding configured for this drag and drop object for calculating
14430 * the drop zone intersection with this object.
14437 * Cached reference to the linked element
14438 * @property _domRef
14444 * Internal typeof flag
14445 * @property __ygDragDrop
14448 __ygDragDrop: true,
14451 * Set to true when horizontal contraints are applied
14452 * @property constrainX
14459 * Set to true when vertical contraints are applied
14460 * @property constrainY
14467 * The left constraint
14475 * The right constraint
14483 * The up constraint
14492 * The down constraint
14500 * Maintain offsets when we resetconstraints. Set to true when you want
14501 * the position of the element relative to its parent to stay the same
14502 * when the page changes
14504 * @property maintainOffset
14507 maintainOffset: false,
14510 * Array of pixel locations the element will snap to if we specified a
14511 * horizontal graduation/interval. This array is generated automatically
14512 * when you define a tick interval.
14519 * Array of pixel locations the element will snap to if we specified a
14520 * vertical graduation/interval. This array is generated automatically
14521 * when you define a tick interval.
14528 * By default the drag and drop instance will only respond to the primary
14529 * button click (left button for a right-handed mouse). Set to true to
14530 * allow drag and drop to start with any mouse click that is propogated
14532 * @property primaryButtonOnly
14535 primaryButtonOnly: true,
14538 * The availabe property is false until the linked dom element is accessible.
14539 * @property available
14545 * By default, drags can only be initiated if the mousedown occurs in the
14546 * region the linked element is. This is done in part to work around a
14547 * bug in some browsers that mis-report the mousedown if the previous
14548 * mouseup happened outside of the window. This property is set to true
14549 * if outer handles are defined.
14551 * @property hasOuterHandles
14555 hasOuterHandles: false,
14558 * Code that executes immediately before the startDrag event
14559 * @method b4StartDrag
14562 b4StartDrag: function(x, y) { },
14565 * Abstract method called after a drag/drop object is clicked
14566 * and the drag or mousedown time thresholds have beeen met.
14567 * @method startDrag
14568 * @param {int} X click location
14569 * @param {int} Y click location
14571 startDrag: function(x, y) { /* override this */ },
14574 * Code that executes immediately before the onDrag event
14578 b4Drag: function(e) { },
14581 * Abstract method called during the onMouseMove event while dragging an
14584 * @param {Event} e the mousemove event
14586 onDrag: function(e) { /* override this */ },
14589 * Abstract method called when this element fist begins hovering over
14590 * another DragDrop obj
14591 * @method onDragEnter
14592 * @param {Event} e the mousemove event
14593 * @param {String|DragDrop[]} id In POINT mode, the element
14594 * id this is hovering over. In INTERSECT mode, an array of one or more
14595 * dragdrop items being hovered over.
14597 onDragEnter: function(e, id) { /* override this */ },
14600 * Code that executes immediately before the onDragOver event
14601 * @method b4DragOver
14604 b4DragOver: function(e) { },
14607 * Abstract method called when this element is hovering over another
14609 * @method onDragOver
14610 * @param {Event} e the mousemove event
14611 * @param {String|DragDrop[]} id In POINT mode, the element
14612 * id this is hovering over. In INTERSECT mode, an array of dd items
14613 * being hovered over.
14615 onDragOver: function(e, id) { /* override this */ },
14618 * Code that executes immediately before the onDragOut event
14619 * @method b4DragOut
14622 b4DragOut: function(e) { },
14625 * Abstract method called when we are no longer hovering over an element
14626 * @method onDragOut
14627 * @param {Event} e the mousemove event
14628 * @param {String|DragDrop[]} id In POINT mode, the element
14629 * id this was hovering over. In INTERSECT mode, an array of dd items
14630 * that the mouse is no longer over.
14632 onDragOut: function(e, id) { /* override this */ },
14635 * Code that executes immediately before the onDragDrop event
14636 * @method b4DragDrop
14639 b4DragDrop: function(e) { },
14642 * Abstract method called when this item is dropped on another DragDrop
14644 * @method onDragDrop
14645 * @param {Event} e the mouseup event
14646 * @param {String|DragDrop[]} id In POINT mode, the element
14647 * id this was dropped on. In INTERSECT mode, an array of dd items this
14650 onDragDrop: function(e, id) { /* override this */ },
14653 * Abstract method called when this item is dropped on an area with no
14655 * @method onInvalidDrop
14656 * @param {Event} e the mouseup event
14658 onInvalidDrop: function(e) { /* override this */ },
14661 * Code that executes immediately before the endDrag event
14662 * @method b4EndDrag
14665 b4EndDrag: function(e) { },
14668 * Fired when we are done dragging the object
14670 * @param {Event} e the mouseup event
14672 endDrag: function(e) { /* override this */ },
14675 * Code executed immediately before the onMouseDown event
14676 * @method b4MouseDown
14677 * @param {Event} e the mousedown event
14680 b4MouseDown: function(e) { },
14683 * Event handler that fires when a drag/drop obj gets a mousedown
14684 * @method onMouseDown
14685 * @param {Event} e the mousedown event
14687 onMouseDown: function(e) { /* override this */ },
14690 * Event handler that fires when a drag/drop obj gets a mouseup
14691 * @method onMouseUp
14692 * @param {Event} e the mouseup event
14694 onMouseUp: function(e) { /* override this */ },
14697 * Override the onAvailable method to do what is needed after the initial
14698 * position was determined.
14699 * @method onAvailable
14701 onAvailable: function () {
14705 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
14708 defaultPadding : {left:0, right:0, top:0, bottom:0},
14711 * Initializes the drag drop object's constraints to restrict movement to a certain element.
14715 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
14716 { dragElId: "existingProxyDiv" });
14717 dd.startDrag = function(){
14718 this.constrainTo("parent-id");
14721 * Or you can initalize it using the {@link Roo.Element} object:
14723 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
14724 startDrag : function(){
14725 this.constrainTo("parent-id");
14729 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
14730 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
14731 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
14732 * an object containing the sides to pad. For example: {right:10, bottom:10}
14733 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
14735 constrainTo : function(constrainTo, pad, inContent){
14736 if(typeof pad == "number"){
14737 pad = {left: pad, right:pad, top:pad, bottom:pad};
14739 pad = pad || this.defaultPadding;
14740 var b = Roo.get(this.getEl()).getBox();
14741 var ce = Roo.get(constrainTo);
14742 var s = ce.getScroll();
14743 var c, cd = ce.dom;
14744 if(cd == document.body){
14745 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
14748 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
14752 var topSpace = b.y - c.y;
14753 var leftSpace = b.x - c.x;
14755 this.resetConstraints();
14756 this.setXConstraint(leftSpace - (pad.left||0), // left
14757 c.width - leftSpace - b.width - (pad.right||0) //right
14759 this.setYConstraint(topSpace - (pad.top||0), //top
14760 c.height - topSpace - b.height - (pad.bottom||0) //bottom
14765 * Returns a reference to the linked element
14767 * @return {HTMLElement} the html element
14769 getEl: function() {
14770 if (!this._domRef) {
14771 this._domRef = Roo.getDom(this.id);
14774 return this._domRef;
14778 * Returns a reference to the actual element to drag. By default this is
14779 * the same as the html element, but it can be assigned to another
14780 * element. An example of this can be found in Roo.dd.DDProxy
14781 * @method getDragEl
14782 * @return {HTMLElement} the html element
14784 getDragEl: function() {
14785 return Roo.getDom(this.dragElId);
14789 * Sets up the DragDrop object. Must be called in the constructor of any
14790 * Roo.dd.DragDrop subclass
14792 * @param id the id of the linked element
14793 * @param {String} sGroup the group of related items
14794 * @param {object} config configuration attributes
14796 init: function(id, sGroup, config) {
14797 this.initTarget(id, sGroup, config);
14798 Event.on(this.id, "mousedown", this.handleMouseDown, this);
14799 // Event.on(this.id, "selectstart", Event.preventDefault);
14803 * Initializes Targeting functionality only... the object does not
14804 * get a mousedown handler.
14805 * @method initTarget
14806 * @param id the id of the linked element
14807 * @param {String} sGroup the group of related items
14808 * @param {object} config configuration attributes
14810 initTarget: function(id, sGroup, config) {
14812 // configuration attributes
14813 this.config = config || {};
14815 // create a local reference to the drag and drop manager
14816 this.DDM = Roo.dd.DDM;
14817 // initialize the groups array
14820 // assume that we have an element reference instead of an id if the
14821 // parameter is not a string
14822 if (typeof id !== "string") {
14829 // add to an interaction group
14830 this.addToGroup((sGroup) ? sGroup : "default");
14832 // We don't want to register this as the handle with the manager
14833 // so we just set the id rather than calling the setter.
14834 this.handleElId = id;
14836 // the linked element is the element that gets dragged by default
14837 this.setDragElId(id);
14839 // by default, clicked anchors will not start drag operations.
14840 this.invalidHandleTypes = { A: "A" };
14841 this.invalidHandleIds = {};
14842 this.invalidHandleClasses = [];
14844 this.applyConfig();
14846 this.handleOnAvailable();
14850 * Applies the configuration parameters that were passed into the constructor.
14851 * This is supposed to happen at each level through the inheritance chain. So
14852 * a DDProxy implentation will execute apply config on DDProxy, DD, and
14853 * DragDrop in order to get all of the parameters that are available in
14855 * @method applyConfig
14857 applyConfig: function() {
14859 // configurable properties:
14860 // padding, isTarget, maintainOffset, primaryButtonOnly
14861 this.padding = this.config.padding || [0, 0, 0, 0];
14862 this.isTarget = (this.config.isTarget !== false);
14863 this.maintainOffset = (this.config.maintainOffset);
14864 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
14869 * Executed when the linked element is available
14870 * @method handleOnAvailable
14873 handleOnAvailable: function() {
14874 this.available = true;
14875 this.resetConstraints();
14876 this.onAvailable();
14880 * Configures the padding for the target zone in px. Effectively expands
14881 * (or reduces) the virtual object size for targeting calculations.
14882 * Supports css-style shorthand; if only one parameter is passed, all sides
14883 * will have that padding, and if only two are passed, the top and bottom
14884 * will have the first param, the left and right the second.
14885 * @method setPadding
14886 * @param {int} iTop Top pad
14887 * @param {int} iRight Right pad
14888 * @param {int} iBot Bot pad
14889 * @param {int} iLeft Left pad
14891 setPadding: function(iTop, iRight, iBot, iLeft) {
14892 // this.padding = [iLeft, iRight, iTop, iBot];
14893 if (!iRight && 0 !== iRight) {
14894 this.padding = [iTop, iTop, iTop, iTop];
14895 } else if (!iBot && 0 !== iBot) {
14896 this.padding = [iTop, iRight, iTop, iRight];
14898 this.padding = [iTop, iRight, iBot, iLeft];
14903 * Stores the initial placement of the linked element.
14904 * @method setInitialPosition
14905 * @param {int} diffX the X offset, default 0
14906 * @param {int} diffY the Y offset, default 0
14908 setInitPosition: function(diffX, diffY) {
14909 var el = this.getEl();
14911 if (!this.DDM.verifyEl(el)) {
14915 var dx = diffX || 0;
14916 var dy = diffY || 0;
14918 var p = Dom.getXY( el );
14920 this.initPageX = p[0] - dx;
14921 this.initPageY = p[1] - dy;
14923 this.lastPageX = p[0];
14924 this.lastPageY = p[1];
14927 this.setStartPosition(p);
14931 * Sets the start position of the element. This is set when the obj
14932 * is initialized, the reset when a drag is started.
14933 * @method setStartPosition
14934 * @param pos current position (from previous lookup)
14937 setStartPosition: function(pos) {
14938 var p = pos || Dom.getXY( this.getEl() );
14939 this.deltaSetXY = null;
14941 this.startPageX = p[0];
14942 this.startPageY = p[1];
14946 * Add this instance to a group of related drag/drop objects. All
14947 * instances belong to at least one group, and can belong to as many
14948 * groups as needed.
14949 * @method addToGroup
14950 * @param sGroup {string} the name of the group
14952 addToGroup: function(sGroup) {
14953 this.groups[sGroup] = true;
14954 this.DDM.regDragDrop(this, sGroup);
14958 * Remove's this instance from the supplied interaction group
14959 * @method removeFromGroup
14960 * @param {string} sGroup The group to drop
14962 removeFromGroup: function(sGroup) {
14963 if (this.groups[sGroup]) {
14964 delete this.groups[sGroup];
14967 this.DDM.removeDDFromGroup(this, sGroup);
14971 * Allows you to specify that an element other than the linked element
14972 * will be moved with the cursor during a drag
14973 * @method setDragElId
14974 * @param id {string} the id of the element that will be used to initiate the drag
14976 setDragElId: function(id) {
14977 this.dragElId = id;
14981 * Allows you to specify a child of the linked element that should be
14982 * used to initiate the drag operation. An example of this would be if
14983 * you have a content div with text and links. Clicking anywhere in the
14984 * content area would normally start the drag operation. Use this method
14985 * to specify that an element inside of the content div is the element
14986 * that starts the drag operation.
14987 * @method setHandleElId
14988 * @param id {string} the id of the element that will be used to
14989 * initiate the drag.
14991 setHandleElId: function(id) {
14992 if (typeof id !== "string") {
14995 this.handleElId = id;
14996 this.DDM.regHandle(this.id, id);
15000 * Allows you to set an element outside of the linked element as a drag
15002 * @method setOuterHandleElId
15003 * @param id the id of the element that will be used to initiate the drag
15005 setOuterHandleElId: function(id) {
15006 if (typeof id !== "string") {
15009 Event.on(id, "mousedown",
15010 this.handleMouseDown, this);
15011 this.setHandleElId(id);
15013 this.hasOuterHandles = true;
15017 * Remove all drag and drop hooks for this element
15020 unreg: function() {
15021 Event.un(this.id, "mousedown",
15022 this.handleMouseDown);
15023 this._domRef = null;
15024 this.DDM._remove(this);
15027 destroy : function(){
15032 * Returns true if this instance is locked, or the drag drop mgr is locked
15033 * (meaning that all drag/drop is disabled on the page.)
15035 * @return {boolean} true if this obj or all drag/drop is locked, else
15038 isLocked: function() {
15039 return (this.DDM.isLocked() || this.locked);
15043 * Fired when this object is clicked
15044 * @method handleMouseDown
15046 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
15049 handleMouseDown: function(e, oDD){
15050 if (this.primaryButtonOnly && e.button != 0) {
15054 if (this.isLocked()) {
15058 this.DDM.refreshCache(this.groups);
15060 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
15061 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
15063 if (this.clickValidator(e)) {
15065 // set the initial element position
15066 this.setStartPosition();
15069 this.b4MouseDown(e);
15070 this.onMouseDown(e);
15072 this.DDM.handleMouseDown(e, this);
15074 this.DDM.stopEvent(e);
15082 clickValidator: function(e) {
15083 var target = e.getTarget();
15084 return ( this.isValidHandleChild(target) &&
15085 (this.id == this.handleElId ||
15086 this.DDM.handleWasClicked(target, this.id)) );
15090 * Allows you to specify a tag name that should not start a drag operation
15091 * when clicked. This is designed to facilitate embedding links within a
15092 * drag handle that do something other than start the drag.
15093 * @method addInvalidHandleType
15094 * @param {string} tagName the type of element to exclude
15096 addInvalidHandleType: function(tagName) {
15097 var type = tagName.toUpperCase();
15098 this.invalidHandleTypes[type] = type;
15102 * Lets you to specify an element id for a child of a drag handle
15103 * that should not initiate a drag
15104 * @method addInvalidHandleId
15105 * @param {string} id the element id of the element you wish to ignore
15107 addInvalidHandleId: function(id) {
15108 if (typeof id !== "string") {
15111 this.invalidHandleIds[id] = id;
15115 * Lets you specify a css class of elements that will not initiate a drag
15116 * @method addInvalidHandleClass
15117 * @param {string} cssClass the class of the elements you wish to ignore
15119 addInvalidHandleClass: function(cssClass) {
15120 this.invalidHandleClasses.push(cssClass);
15124 * Unsets an excluded tag name set by addInvalidHandleType
15125 * @method removeInvalidHandleType
15126 * @param {string} tagName the type of element to unexclude
15128 removeInvalidHandleType: function(tagName) {
15129 var type = tagName.toUpperCase();
15130 // this.invalidHandleTypes[type] = null;
15131 delete this.invalidHandleTypes[type];
15135 * Unsets an invalid handle id
15136 * @method removeInvalidHandleId
15137 * @param {string} id the id of the element to re-enable
15139 removeInvalidHandleId: function(id) {
15140 if (typeof id !== "string") {
15143 delete this.invalidHandleIds[id];
15147 * Unsets an invalid css class
15148 * @method removeInvalidHandleClass
15149 * @param {string} cssClass the class of the element(s) you wish to
15152 removeInvalidHandleClass: function(cssClass) {
15153 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
15154 if (this.invalidHandleClasses[i] == cssClass) {
15155 delete this.invalidHandleClasses[i];
15161 * Checks the tag exclusion list to see if this click should be ignored
15162 * @method isValidHandleChild
15163 * @param {HTMLElement} node the HTMLElement to evaluate
15164 * @return {boolean} true if this is a valid tag type, false if not
15166 isValidHandleChild: function(node) {
15169 // var n = (node.nodeName == "#text") ? node.parentNode : node;
15172 nodeName = node.nodeName.toUpperCase();
15174 nodeName = node.nodeName;
15176 valid = valid && !this.invalidHandleTypes[nodeName];
15177 valid = valid && !this.invalidHandleIds[node.id];
15179 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
15180 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
15189 * Create the array of horizontal tick marks if an interval was specified
15190 * in setXConstraint().
15191 * @method setXTicks
15194 setXTicks: function(iStartX, iTickSize) {
15196 this.xTickSize = iTickSize;
15200 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
15202 this.xTicks[this.xTicks.length] = i;
15207 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
15209 this.xTicks[this.xTicks.length] = i;
15214 this.xTicks.sort(this.DDM.numericSort) ;
15218 * Create the array of vertical tick marks if an interval was specified in
15219 * setYConstraint().
15220 * @method setYTicks
15223 setYTicks: function(iStartY, iTickSize) {
15225 this.yTickSize = iTickSize;
15229 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
15231 this.yTicks[this.yTicks.length] = i;
15236 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
15238 this.yTicks[this.yTicks.length] = i;
15243 this.yTicks.sort(this.DDM.numericSort) ;
15247 * By default, the element can be dragged any place on the screen. Use
15248 * this method to limit the horizontal travel of the element. Pass in
15249 * 0,0 for the parameters if you want to lock the drag to the y axis.
15250 * @method setXConstraint
15251 * @param {int} iLeft the number of pixels the element can move to the left
15252 * @param {int} iRight the number of pixels the element can move to the
15254 * @param {int} iTickSize optional parameter for specifying that the
15256 * should move iTickSize pixels at a time.
15258 setXConstraint: function(iLeft, iRight, iTickSize) {
15259 this.leftConstraint = iLeft;
15260 this.rightConstraint = iRight;
15262 this.minX = this.initPageX - iLeft;
15263 this.maxX = this.initPageX + iRight;
15264 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
15266 this.constrainX = true;
15270 * Clears any constraints applied to this instance. Also clears ticks
15271 * since they can't exist independent of a constraint at this time.
15272 * @method clearConstraints
15274 clearConstraints: function() {
15275 this.constrainX = false;
15276 this.constrainY = false;
15281 * Clears any tick interval defined for this instance
15282 * @method clearTicks
15284 clearTicks: function() {
15285 this.xTicks = null;
15286 this.yTicks = null;
15287 this.xTickSize = 0;
15288 this.yTickSize = 0;
15292 * By default, the element can be dragged any place on the screen. Set
15293 * this to limit the vertical travel of the element. Pass in 0,0 for the
15294 * parameters if you want to lock the drag to the x axis.
15295 * @method setYConstraint
15296 * @param {int} iUp the number of pixels the element can move up
15297 * @param {int} iDown the number of pixels the element can move down
15298 * @param {int} iTickSize optional parameter for specifying that the
15299 * element should move iTickSize pixels at a time.
15301 setYConstraint: function(iUp, iDown, iTickSize) {
15302 this.topConstraint = iUp;
15303 this.bottomConstraint = iDown;
15305 this.minY = this.initPageY - iUp;
15306 this.maxY = this.initPageY + iDown;
15307 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
15309 this.constrainY = true;
15314 * resetConstraints must be called if you manually reposition a dd element.
15315 * @method resetConstraints
15316 * @param {boolean} maintainOffset
15318 resetConstraints: function() {
15321 // Maintain offsets if necessary
15322 if (this.initPageX || this.initPageX === 0) {
15323 // figure out how much this thing has moved
15324 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
15325 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
15327 this.setInitPosition(dx, dy);
15329 // This is the first time we have detected the element's position
15331 this.setInitPosition();
15334 if (this.constrainX) {
15335 this.setXConstraint( this.leftConstraint,
15336 this.rightConstraint,
15340 if (this.constrainY) {
15341 this.setYConstraint( this.topConstraint,
15342 this.bottomConstraint,
15348 * Normally the drag element is moved pixel by pixel, but we can specify
15349 * that it move a number of pixels at a time. This method resolves the
15350 * location when we have it set up like this.
15352 * @param {int} val where we want to place the object
15353 * @param {int[]} tickArray sorted array of valid points
15354 * @return {int} the closest tick
15357 getTick: function(val, tickArray) {
15360 // If tick interval is not defined, it is effectively 1 pixel,
15361 // so we return the value passed to us.
15363 } else if (tickArray[0] >= val) {
15364 // The value is lower than the first tick, so we return the first
15366 return tickArray[0];
15368 for (var i=0, len=tickArray.length; i<len; ++i) {
15370 if (tickArray[next] && tickArray[next] >= val) {
15371 var diff1 = val - tickArray[i];
15372 var diff2 = tickArray[next] - val;
15373 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
15377 // The value is larger than the last tick, so we return the last
15379 return tickArray[tickArray.length - 1];
15386 * @return {string} string representation of the dd obj
15388 toString: function() {
15389 return ("DragDrop " + this.id);
15397 * Ext JS Library 1.1.1
15398 * Copyright(c) 2006-2007, Ext JS, LLC.
15400 * Originally Released Under LGPL - original licence link has changed is not relivant.
15403 * <script type="text/javascript">
15408 * The drag and drop utility provides a framework for building drag and drop
15409 * applications. In addition to enabling drag and drop for specific elements,
15410 * the drag and drop elements are tracked by the manager class, and the
15411 * interactions between the various elements are tracked during the drag and
15412 * the implementing code is notified about these important moments.
15415 // Only load the library once. Rewriting the manager class would orphan
15416 // existing drag and drop instances.
15417 if (!Roo.dd.DragDropMgr) {
15420 * @class Roo.dd.DragDropMgr
15421 * DragDropMgr is a singleton that tracks the element interaction for
15422 * all DragDrop items in the window. Generally, you will not call
15423 * this class directly, but it does have helper methods that could
15424 * be useful in your DragDrop implementations.
15427 Roo.dd.DragDropMgr = function() {
15429 var Event = Roo.EventManager;
15434 * Two dimensional Array of registered DragDrop objects. The first
15435 * dimension is the DragDrop item group, the second the DragDrop
15438 * @type {string: string}
15445 * Array of element ids defined as drag handles. Used to determine
15446 * if the element that generated the mousedown event is actually the
15447 * handle and not the html element itself.
15448 * @property handleIds
15449 * @type {string: string}
15456 * the DragDrop object that is currently being dragged
15457 * @property dragCurrent
15465 * the DragDrop object(s) that are being hovered over
15466 * @property dragOvers
15474 * the X distance between the cursor and the object being dragged
15483 * the Y distance between the cursor and the object being dragged
15492 * Flag to determine if we should prevent the default behavior of the
15493 * events we define. By default this is true, but this can be set to
15494 * false if you need the default behavior (not recommended)
15495 * @property preventDefault
15499 preventDefault: true,
15502 * Flag to determine if we should stop the propagation of the events
15503 * we generate. This is true by default but you may want to set it to
15504 * false if the html element contains other features that require the
15506 * @property stopPropagation
15510 stopPropagation: true,
15513 * Internal flag that is set to true when drag and drop has been
15515 * @property initialized
15522 * All drag and drop can be disabled.
15530 * Called the first time an element is registered.
15536 this.initialized = true;
15540 * In point mode, drag and drop interaction is defined by the
15541 * location of the cursor during the drag/drop
15549 * In intersect mode, drag and drop interactio nis defined by the
15550 * overlap of two or more drag and drop objects.
15551 * @property INTERSECT
15558 * The current drag and drop mode. Default: POINT
15566 * Runs method on all drag and drop objects
15567 * @method _execOnAll
15571 _execOnAll: function(sMethod, args) {
15572 for (var i in this.ids) {
15573 for (var j in this.ids[i]) {
15574 var oDD = this.ids[i][j];
15575 if (! this.isTypeOfDD(oDD)) {
15578 oDD[sMethod].apply(oDD, args);
15584 * Drag and drop initialization. Sets up the global event handlers
15589 _onLoad: function() {
15594 Event.on(document, "mouseup", this.handleMouseUp, this, true);
15595 Event.on(document, "mousemove", this.handleMouseMove, this, true);
15596 Event.on(window, "unload", this._onUnload, this, true);
15597 Event.on(window, "resize", this._onResize, this, true);
15598 // Event.on(window, "mouseout", this._test);
15603 * Reset constraints on all drag and drop objs
15604 * @method _onResize
15608 _onResize: function(e) {
15609 this._execOnAll("resetConstraints", []);
15613 * Lock all drag and drop functionality
15617 lock: function() { this.locked = true; },
15620 * Unlock all drag and drop functionality
15624 unlock: function() { this.locked = false; },
15627 * Is drag and drop locked?
15629 * @return {boolean} True if drag and drop is locked, false otherwise.
15632 isLocked: function() { return this.locked; },
15635 * Location cache that is set for all drag drop objects when a drag is
15636 * initiated, cleared when the drag is finished.
15637 * @property locationCache
15644 * Set useCache to false if you want to force object the lookup of each
15645 * drag and drop linked element constantly during a drag.
15646 * @property useCache
15653 * The number of pixels that the mouse needs to move after the
15654 * mousedown before the drag is initiated. Default=3;
15655 * @property clickPixelThresh
15659 clickPixelThresh: 3,
15662 * The number of milliseconds after the mousedown event to initiate the
15663 * drag if we don't get a mouseup event. Default=1000
15664 * @property clickTimeThresh
15668 clickTimeThresh: 350,
15671 * Flag that indicates that either the drag pixel threshold or the
15672 * mousdown time threshold has been met
15673 * @property dragThreshMet
15678 dragThreshMet: false,
15681 * Timeout used for the click time threshold
15682 * @property clickTimeout
15687 clickTimeout: null,
15690 * The X position of the mousedown event stored for later use when a
15691 * drag threshold is met.
15700 * The Y position of the mousedown event stored for later use when a
15701 * drag threshold is met.
15710 * Each DragDrop instance must be registered with the DragDropMgr.
15711 * This is executed in DragDrop.init()
15712 * @method regDragDrop
15713 * @param {DragDrop} oDD the DragDrop object to register
15714 * @param {String} sGroup the name of the group this element belongs to
15717 regDragDrop: function(oDD, sGroup) {
15718 if (!this.initialized) { this.init(); }
15720 if (!this.ids[sGroup]) {
15721 this.ids[sGroup] = {};
15723 this.ids[sGroup][oDD.id] = oDD;
15727 * Removes the supplied dd instance from the supplied group. Executed
15728 * by DragDrop.removeFromGroup, so don't call this function directly.
15729 * @method removeDDFromGroup
15733 removeDDFromGroup: function(oDD, sGroup) {
15734 if (!this.ids[sGroup]) {
15735 this.ids[sGroup] = {};
15738 var obj = this.ids[sGroup];
15739 if (obj && obj[oDD.id]) {
15740 delete obj[oDD.id];
15745 * Unregisters a drag and drop item. This is executed in
15746 * DragDrop.unreg, use that method instead of calling this directly.
15751 _remove: function(oDD) {
15752 for (var g in oDD.groups) {
15753 if (g && this.ids[g][oDD.id]) {
15754 delete this.ids[g][oDD.id];
15757 delete this.handleIds[oDD.id];
15761 * Each DragDrop handle element must be registered. This is done
15762 * automatically when executing DragDrop.setHandleElId()
15763 * @method regHandle
15764 * @param {String} sDDId the DragDrop id this element is a handle for
15765 * @param {String} sHandleId the id of the element that is the drag
15769 regHandle: function(sDDId, sHandleId) {
15770 if (!this.handleIds[sDDId]) {
15771 this.handleIds[sDDId] = {};
15773 this.handleIds[sDDId][sHandleId] = sHandleId;
15777 * Utility function to determine if a given element has been
15778 * registered as a drag drop item.
15779 * @method isDragDrop
15780 * @param {String} id the element id to check
15781 * @return {boolean} true if this element is a DragDrop item,
15785 isDragDrop: function(id) {
15786 return ( this.getDDById(id) ) ? true : false;
15790 * Returns the drag and drop instances that are in all groups the
15791 * passed in instance belongs to.
15792 * @method getRelated
15793 * @param {DragDrop} p_oDD the obj to get related data for
15794 * @param {boolean} bTargetsOnly if true, only return targetable objs
15795 * @return {DragDrop[]} the related instances
15798 getRelated: function(p_oDD, bTargetsOnly) {
15800 for (var i in p_oDD.groups) {
15801 for (j in this.ids[i]) {
15802 var dd = this.ids[i][j];
15803 if (! this.isTypeOfDD(dd)) {
15806 if (!bTargetsOnly || dd.isTarget) {
15807 oDDs[oDDs.length] = dd;
15816 * Returns true if the specified dd target is a legal target for
15817 * the specifice drag obj
15818 * @method isLegalTarget
15819 * @param {DragDrop} the drag obj
15820 * @param {DragDrop} the target
15821 * @return {boolean} true if the target is a legal target for the
15825 isLegalTarget: function (oDD, oTargetDD) {
15826 var targets = this.getRelated(oDD, true);
15827 for (var i=0, len=targets.length;i<len;++i) {
15828 if (targets[i].id == oTargetDD.id) {
15837 * My goal is to be able to transparently determine if an object is
15838 * typeof DragDrop, and the exact subclass of DragDrop. typeof
15839 * returns "object", oDD.constructor.toString() always returns
15840 * "DragDrop" and not the name of the subclass. So for now it just
15841 * evaluates a well-known variable in DragDrop.
15842 * @method isTypeOfDD
15843 * @param {Object} the object to evaluate
15844 * @return {boolean} true if typeof oDD = DragDrop
15847 isTypeOfDD: function (oDD) {
15848 return (oDD && oDD.__ygDragDrop);
15852 * Utility function to determine if a given element has been
15853 * registered as a drag drop handle for the given Drag Drop object.
15855 * @param {String} id the element id to check
15856 * @return {boolean} true if this element is a DragDrop handle, false
15860 isHandle: function(sDDId, sHandleId) {
15861 return ( this.handleIds[sDDId] &&
15862 this.handleIds[sDDId][sHandleId] );
15866 * Returns the DragDrop instance for a given id
15867 * @method getDDById
15868 * @param {String} id the id of the DragDrop object
15869 * @return {DragDrop} the drag drop object, null if it is not found
15872 getDDById: function(id) {
15873 for (var i in this.ids) {
15874 if (this.ids[i][id]) {
15875 return this.ids[i][id];
15882 * Fired after a registered DragDrop object gets the mousedown event.
15883 * Sets up the events required to track the object being dragged
15884 * @method handleMouseDown
15885 * @param {Event} e the event
15886 * @param oDD the DragDrop object being dragged
15890 handleMouseDown: function(e, oDD) {
15892 Roo.QuickTips.disable();
15894 this.currentTarget = e.getTarget();
15896 this.dragCurrent = oDD;
15898 var el = oDD.getEl();
15900 // track start position
15901 this.startX = e.getPageX();
15902 this.startY = e.getPageY();
15904 this.deltaX = this.startX - el.offsetLeft;
15905 this.deltaY = this.startY - el.offsetTop;
15907 this.dragThreshMet = false;
15909 this.clickTimeout = setTimeout(
15911 var DDM = Roo.dd.DDM;
15912 DDM.startDrag(DDM.startX, DDM.startY);
15914 this.clickTimeThresh );
15918 * Fired when either the drag pixel threshol or the mousedown hold
15919 * time threshold has been met.
15920 * @method startDrag
15921 * @param x {int} the X position of the original mousedown
15922 * @param y {int} the Y position of the original mousedown
15925 startDrag: function(x, y) {
15926 clearTimeout(this.clickTimeout);
15927 if (this.dragCurrent) {
15928 this.dragCurrent.b4StartDrag(x, y);
15929 this.dragCurrent.startDrag(x, y);
15931 this.dragThreshMet = true;
15935 * Internal function to handle the mouseup event. Will be invoked
15936 * from the context of the document.
15937 * @method handleMouseUp
15938 * @param {Event} e the event
15942 handleMouseUp: function(e) {
15945 Roo.QuickTips.enable();
15947 if (! this.dragCurrent) {
15951 clearTimeout(this.clickTimeout);
15953 if (this.dragThreshMet) {
15954 this.fireEvents(e, true);
15964 * Utility to stop event propagation and event default, if these
15965 * features are turned on.
15966 * @method stopEvent
15967 * @param {Event} e the event as returned by this.getEvent()
15970 stopEvent: function(e){
15971 if(this.stopPropagation) {
15972 e.stopPropagation();
15975 if (this.preventDefault) {
15976 e.preventDefault();
15981 * Internal function to clean up event handlers after the drag
15982 * operation is complete
15984 * @param {Event} e the event
15988 stopDrag: function(e) {
15989 // Fire the drag end event for the item that was dragged
15990 if (this.dragCurrent) {
15991 if (this.dragThreshMet) {
15992 this.dragCurrent.b4EndDrag(e);
15993 this.dragCurrent.endDrag(e);
15996 this.dragCurrent.onMouseUp(e);
15999 this.dragCurrent = null;
16000 this.dragOvers = {};
16004 * Internal function to handle the mousemove event. Will be invoked
16005 * from the context of the html element.
16007 * @TODO figure out what we can do about mouse events lost when the
16008 * user drags objects beyond the window boundary. Currently we can
16009 * detect this in internet explorer by verifying that the mouse is
16010 * down during the mousemove event. Firefox doesn't give us the
16011 * button state on the mousemove event.
16012 * @method handleMouseMove
16013 * @param {Event} e the event
16017 handleMouseMove: function(e) {
16018 if (! this.dragCurrent) {
16022 // var button = e.which || e.button;
16024 // check for IE mouseup outside of page boundary
16025 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
16027 return this.handleMouseUp(e);
16030 if (!this.dragThreshMet) {
16031 var diffX = Math.abs(this.startX - e.getPageX());
16032 var diffY = Math.abs(this.startY - e.getPageY());
16033 if (diffX > this.clickPixelThresh ||
16034 diffY > this.clickPixelThresh) {
16035 this.startDrag(this.startX, this.startY);
16039 if (this.dragThreshMet) {
16040 this.dragCurrent.b4Drag(e);
16041 this.dragCurrent.onDrag(e);
16042 if(!this.dragCurrent.moveOnly){
16043 this.fireEvents(e, false);
16053 * Iterates over all of the DragDrop elements to find ones we are
16054 * hovering over or dropping on
16055 * @method fireEvents
16056 * @param {Event} e the event
16057 * @param {boolean} isDrop is this a drop op or a mouseover op?
16061 fireEvents: function(e, isDrop) {
16062 var dc = this.dragCurrent;
16064 // If the user did the mouse up outside of the window, we could
16065 // get here even though we have ended the drag.
16066 if (!dc || dc.isLocked()) {
16070 var pt = e.getPoint();
16072 // cache the previous dragOver array
16078 var enterEvts = [];
16080 // Check to see if the object(s) we were hovering over is no longer
16081 // being hovered over so we can fire the onDragOut event
16082 for (var i in this.dragOvers) {
16084 var ddo = this.dragOvers[i];
16086 if (! this.isTypeOfDD(ddo)) {
16090 if (! this.isOverTarget(pt, ddo, this.mode)) {
16091 outEvts.push( ddo );
16094 oldOvers[i] = true;
16095 delete this.dragOvers[i];
16098 for (var sGroup in dc.groups) {
16100 if ("string" != typeof sGroup) {
16104 for (i in this.ids[sGroup]) {
16105 var oDD = this.ids[sGroup][i];
16106 if (! this.isTypeOfDD(oDD)) {
16110 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
16111 if (this.isOverTarget(pt, oDD, this.mode)) {
16112 // look for drop interactions
16114 dropEvts.push( oDD );
16115 // look for drag enter and drag over interactions
16118 // initial drag over: dragEnter fires
16119 if (!oldOvers[oDD.id]) {
16120 enterEvts.push( oDD );
16121 // subsequent drag overs: dragOver fires
16123 overEvts.push( oDD );
16126 this.dragOvers[oDD.id] = oDD;
16134 if (outEvts.length) {
16135 dc.b4DragOut(e, outEvts);
16136 dc.onDragOut(e, outEvts);
16139 if (enterEvts.length) {
16140 dc.onDragEnter(e, enterEvts);
16143 if (overEvts.length) {
16144 dc.b4DragOver(e, overEvts);
16145 dc.onDragOver(e, overEvts);
16148 if (dropEvts.length) {
16149 dc.b4DragDrop(e, dropEvts);
16150 dc.onDragDrop(e, dropEvts);
16154 // fire dragout events
16156 for (i=0, len=outEvts.length; i<len; ++i) {
16157 dc.b4DragOut(e, outEvts[i].id);
16158 dc.onDragOut(e, outEvts[i].id);
16161 // fire enter events
16162 for (i=0,len=enterEvts.length; i<len; ++i) {
16163 // dc.b4DragEnter(e, oDD.id);
16164 dc.onDragEnter(e, enterEvts[i].id);
16167 // fire over events
16168 for (i=0,len=overEvts.length; i<len; ++i) {
16169 dc.b4DragOver(e, overEvts[i].id);
16170 dc.onDragOver(e, overEvts[i].id);
16173 // fire drop events
16174 for (i=0, len=dropEvts.length; i<len; ++i) {
16175 dc.b4DragDrop(e, dropEvts[i].id);
16176 dc.onDragDrop(e, dropEvts[i].id);
16181 // notify about a drop that did not find a target
16182 if (isDrop && !dropEvts.length) {
16183 dc.onInvalidDrop(e);
16189 * Helper function for getting the best match from the list of drag
16190 * and drop objects returned by the drag and drop events when we are
16191 * in INTERSECT mode. It returns either the first object that the
16192 * cursor is over, or the object that has the greatest overlap with
16193 * the dragged element.
16194 * @method getBestMatch
16195 * @param {DragDrop[]} dds The array of drag and drop objects
16197 * @return {DragDrop} The best single match
16200 getBestMatch: function(dds) {
16202 // Return null if the input is not what we expect
16203 //if (!dds || !dds.length || dds.length == 0) {
16205 // If there is only one item, it wins
16206 //} else if (dds.length == 1) {
16208 var len = dds.length;
16213 // Loop through the targeted items
16214 for (var i=0; i<len; ++i) {
16216 // If the cursor is over the object, it wins. If the
16217 // cursor is over multiple matches, the first one we come
16219 if (dd.cursorIsOver) {
16222 // Otherwise the object with the most overlap wins
16225 winner.overlap.getArea() < dd.overlap.getArea()) {
16236 * Refreshes the cache of the top-left and bottom-right points of the
16237 * drag and drop objects in the specified group(s). This is in the
16238 * format that is stored in the drag and drop instance, so typical
16241 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
16245 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
16247 * @TODO this really should be an indexed array. Alternatively this
16248 * method could accept both.
16249 * @method refreshCache
16250 * @param {Object} groups an associative array of groups to refresh
16253 refreshCache: function(groups) {
16254 for (var sGroup in groups) {
16255 if ("string" != typeof sGroup) {
16258 for (var i in this.ids[sGroup]) {
16259 var oDD = this.ids[sGroup][i];
16261 if (this.isTypeOfDD(oDD)) {
16262 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
16263 var loc = this.getLocation(oDD);
16265 this.locationCache[oDD.id] = loc;
16267 delete this.locationCache[oDD.id];
16268 // this will unregister the drag and drop object if
16269 // the element is not in a usable state
16278 * This checks to make sure an element exists and is in the DOM. The
16279 * main purpose is to handle cases where innerHTML is used to remove
16280 * drag and drop objects from the DOM. IE provides an 'unspecified
16281 * error' when trying to access the offsetParent of such an element
16283 * @param {HTMLElement} el the element to check
16284 * @return {boolean} true if the element looks usable
16287 verifyEl: function(el) {
16292 parent = el.offsetParent;
16295 parent = el.offsetParent;
16306 * Returns a Region object containing the drag and drop element's position
16307 * and size, including the padding configured for it
16308 * @method getLocation
16309 * @param {DragDrop} oDD the drag and drop object to get the
16311 * @return {Roo.lib.Region} a Region object representing the total area
16312 * the element occupies, including any padding
16313 * the instance is configured for.
16316 getLocation: function(oDD) {
16317 if (! this.isTypeOfDD(oDD)) {
16321 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
16324 pos= Roo.lib.Dom.getXY(el);
16332 x2 = x1 + el.offsetWidth;
16334 y2 = y1 + el.offsetHeight;
16336 t = y1 - oDD.padding[0];
16337 r = x2 + oDD.padding[1];
16338 b = y2 + oDD.padding[2];
16339 l = x1 - oDD.padding[3];
16341 return new Roo.lib.Region( t, r, b, l );
16345 * Checks the cursor location to see if it over the target
16346 * @method isOverTarget
16347 * @param {Roo.lib.Point} pt The point to evaluate
16348 * @param {DragDrop} oTarget the DragDrop object we are inspecting
16349 * @return {boolean} true if the mouse is over the target
16353 isOverTarget: function(pt, oTarget, intersect) {
16354 // use cache if available
16355 var loc = this.locationCache[oTarget.id];
16356 if (!loc || !this.useCache) {
16357 loc = this.getLocation(oTarget);
16358 this.locationCache[oTarget.id] = loc;
16366 oTarget.cursorIsOver = loc.contains( pt );
16368 // DragDrop is using this as a sanity check for the initial mousedown
16369 // in this case we are done. In POINT mode, if the drag obj has no
16370 // contraints, we are also done. Otherwise we need to evaluate the
16371 // location of the target as related to the actual location of the
16372 // dragged element.
16373 var dc = this.dragCurrent;
16374 if (!dc || !dc.getTargetCoord ||
16375 (!intersect && !dc.constrainX && !dc.constrainY)) {
16376 return oTarget.cursorIsOver;
16379 oTarget.overlap = null;
16381 // Get the current location of the drag element, this is the
16382 // location of the mouse event less the delta that represents
16383 // where the original mousedown happened on the element. We
16384 // need to consider constraints and ticks as well.
16385 var pos = dc.getTargetCoord(pt.x, pt.y);
16387 var el = dc.getDragEl();
16388 var curRegion = new Roo.lib.Region( pos.y,
16389 pos.x + el.offsetWidth,
16390 pos.y + el.offsetHeight,
16393 var overlap = curRegion.intersect(loc);
16396 oTarget.overlap = overlap;
16397 return (intersect) ? true : oTarget.cursorIsOver;
16404 * unload event handler
16405 * @method _onUnload
16409 _onUnload: function(e, me) {
16410 Roo.dd.DragDropMgr.unregAll();
16414 * Cleans up the drag and drop events and objects.
16419 unregAll: function() {
16421 if (this.dragCurrent) {
16423 this.dragCurrent = null;
16426 this._execOnAll("unreg", []);
16428 for (i in this.elementCache) {
16429 delete this.elementCache[i];
16432 this.elementCache = {};
16437 * A cache of DOM elements
16438 * @property elementCache
16445 * Get the wrapper for the DOM element specified
16446 * @method getElWrapper
16447 * @param {String} id the id of the element to get
16448 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
16450 * @deprecated This wrapper isn't that useful
16453 getElWrapper: function(id) {
16454 var oWrapper = this.elementCache[id];
16455 if (!oWrapper || !oWrapper.el) {
16456 oWrapper = this.elementCache[id] =
16457 new this.ElementWrapper(Roo.getDom(id));
16463 * Returns the actual DOM element
16464 * @method getElement
16465 * @param {String} id the id of the elment to get
16466 * @return {Object} The element
16467 * @deprecated use Roo.getDom instead
16470 getElement: function(id) {
16471 return Roo.getDom(id);
16475 * Returns the style property for the DOM element (i.e.,
16476 * document.getElById(id).style)
16478 * @param {String} id the id of the elment to get
16479 * @return {Object} The style property of the element
16480 * @deprecated use Roo.getDom instead
16483 getCss: function(id) {
16484 var el = Roo.getDom(id);
16485 return (el) ? el.style : null;
16489 * Inner class for cached elements
16490 * @class DragDropMgr.ElementWrapper
16495 ElementWrapper: function(el) {
16500 this.el = el || null;
16505 this.id = this.el && el.id;
16507 * A reference to the style property
16510 this.css = this.el && el.style;
16514 * Returns the X position of an html element
16516 * @param el the element for which to get the position
16517 * @return {int} the X coordinate
16519 * @deprecated use Roo.lib.Dom.getX instead
16522 getPosX: function(el) {
16523 return Roo.lib.Dom.getX(el);
16527 * Returns the Y position of an html element
16529 * @param el the element for which to get the position
16530 * @return {int} the Y coordinate
16531 * @deprecated use Roo.lib.Dom.getY instead
16534 getPosY: function(el) {
16535 return Roo.lib.Dom.getY(el);
16539 * Swap two nodes. In IE, we use the native method, for others we
16540 * emulate the IE behavior
16542 * @param n1 the first node to swap
16543 * @param n2 the other node to swap
16546 swapNode: function(n1, n2) {
16550 var p = n2.parentNode;
16551 var s = n2.nextSibling;
16554 p.insertBefore(n1, n2);
16555 } else if (n2 == n1.nextSibling) {
16556 p.insertBefore(n2, n1);
16558 n1.parentNode.replaceChild(n2, n1);
16559 p.insertBefore(n1, s);
16565 * Returns the current scroll position
16566 * @method getScroll
16570 getScroll: function () {
16571 var t, l, dde=document.documentElement, db=document.body;
16572 if (dde && (dde.scrollTop || dde.scrollLeft)) {
16574 l = dde.scrollLeft;
16581 return { top: t, left: l };
16585 * Returns the specified element style property
16587 * @param {HTMLElement} el the element
16588 * @param {string} styleProp the style property
16589 * @return {string} The value of the style property
16590 * @deprecated use Roo.lib.Dom.getStyle
16593 getStyle: function(el, styleProp) {
16594 return Roo.fly(el).getStyle(styleProp);
16598 * Gets the scrollTop
16599 * @method getScrollTop
16600 * @return {int} the document's scrollTop
16603 getScrollTop: function () { return this.getScroll().top; },
16606 * Gets the scrollLeft
16607 * @method getScrollLeft
16608 * @return {int} the document's scrollTop
16611 getScrollLeft: function () { return this.getScroll().left; },
16614 * Sets the x/y position of an element to the location of the
16617 * @param {HTMLElement} moveEl The element to move
16618 * @param {HTMLElement} targetEl The position reference element
16621 moveToEl: function (moveEl, targetEl) {
16622 var aCoord = Roo.lib.Dom.getXY(targetEl);
16623 Roo.lib.Dom.setXY(moveEl, aCoord);
16627 * Numeric array sort function
16628 * @method numericSort
16631 numericSort: function(a, b) { return (a - b); },
16635 * @property _timeoutCount
16642 * Trying to make the load order less important. Without this we get
16643 * an error if this file is loaded before the Event Utility.
16644 * @method _addListeners
16648 _addListeners: function() {
16649 var DDM = Roo.dd.DDM;
16650 if ( Roo.lib.Event && document ) {
16653 if (DDM._timeoutCount > 2000) {
16655 setTimeout(DDM._addListeners, 10);
16656 if (document && document.body) {
16657 DDM._timeoutCount += 1;
16664 * Recursively searches the immediate parent and all child nodes for
16665 * the handle element in order to determine wheter or not it was
16667 * @method handleWasClicked
16668 * @param node the html element to inspect
16671 handleWasClicked: function(node, id) {
16672 if (this.isHandle(id, node.id)) {
16675 // check to see if this is a text node child of the one we want
16676 var p = node.parentNode;
16679 if (this.isHandle(id, p.id)) {
16694 // shorter alias, save a few bytes
16695 Roo.dd.DDM = Roo.dd.DragDropMgr;
16696 Roo.dd.DDM._addListeners();