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 if (Roo.debug) 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);
848 * Map (JS 1.6 compatibility)
849 * @param {Function} function to call
853 var len = this.length >>> 0;
854 if (typeof fun != "function")
855 throw new TypeError();
857 var res = new Array(len);
858 var thisp = arguments[1];
859 for (var i = 0; i < len; i++)
862 res[i] = fun.call(thisp, this[i], i, this);
873 * Ext JS Library 1.1.1
874 * Copyright(c) 2006-2007, Ext JS, LLC.
876 * Originally Released Under LGPL - original licence link has changed is not relivant.
879 * <script type="text/javascript">
885 * The date parsing and format syntax is a subset of
886 * <a href="http://www.php.net/date">PHP's date() function</a>, and the formats that are
887 * supported will provide results equivalent to their PHP versions.
889 * Following is the list of all currently supported formats:
892 'Wed Jan 10 2007 15:05:01 GMT-0600 (Central Standard Time)'
894 Format Output Description
895 ------ ---------- --------------------------------------------------------------
896 d 10 Day of the month, 2 digits with leading zeros
897 D Wed A textual representation of a day, three letters
898 j 10 Day of the month without leading zeros
899 l Wednesday A full textual representation of the day of the week
900 S th English ordinal day of month suffix, 2 chars (use with j)
901 w 3 Numeric representation of the day of the week
902 z 9 The julian date, or day of the year (0-365)
903 W 01 ISO-8601 2-digit week number of year, weeks starting on Monday (00-52)
904 F January A full textual representation of the month
905 m 01 Numeric representation of a month, with leading zeros
906 M Jan Month name abbreviation, three letters
907 n 1 Numeric representation of a month, without leading zeros
908 t 31 Number of days in the given month
909 L 0 Whether it's a leap year (1 if it is a leap year, else 0)
910 Y 2007 A full numeric representation of a year, 4 digits
911 y 07 A two digit representation of a year
912 a pm Lowercase Ante meridiem and Post meridiem
913 A PM Uppercase Ante meridiem and Post meridiem
914 g 3 12-hour format of an hour without leading zeros
915 G 15 24-hour format of an hour without leading zeros
916 h 03 12-hour format of an hour with leading zeros
917 H 15 24-hour format of an hour with leading zeros
918 i 05 Minutes with leading zeros
919 s 01 Seconds, with leading zeros
920 O -0600 Difference to Greenwich time (GMT) in hours
921 T CST Timezone setting of the machine running the code
922 Z -21600 Timezone offset in seconds (negative if west of UTC, positive if east)
925 * Example usage (note that you must escape format specifiers with '\\' to render them as character literals):
927 var dt = new Date('1/10/2007 03:05:01 PM GMT-0600');
928 document.write(dt.format('Y-m-d')); //2007-01-10
929 document.write(dt.format('F j, Y, g:i a')); //January 10, 2007, 3:05 pm
930 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
933 * Here are some standard date/time patterns that you might find helpful. They
934 * are not part of the source of Date.js, but to use them you can simply copy this
935 * block of code into any script that is included after Date.js and they will also become
936 * globally available on the Date object. Feel free to add or remove patterns as needed in your code.
939 ISO8601Long:"Y-m-d H:i:s",
940 ISO8601Short:"Y-m-d",
942 LongDate: "l, F d, Y",
943 FullDateTime: "l, F d, Y g:i:s A",
947 SortableDateTime: "Y-m-d\\TH:i:s",
948 UniversalSortableDateTime: "Y-m-d H:i:sO",
956 document.write(dt.format(Date.patterns.ShortDate));
961 * Most of the date-formatting functions below are the excellent work of Baron Schwartz.
962 * They generate precompiled functions from date formats instead of parsing and
963 * processing the pattern every time you format a date. These functions are available
964 * on every Date object (any javascript function).
966 * The original article and download are here:
967 * http://www.xaprb.com/blog/2005/12/12/javascript-closures-for-runtime-efficiency/
974 Returns the number of milliseconds between this date and date
975 @param {Date} date (optional) Defaults to now
976 @return {Number} The diff in milliseconds
977 @member Date getElapsed
979 Date.prototype.getElapsed = function(date) {
980 return Math.abs((date || new Date()).getTime()-this.getTime());
982 // was in date file..
986 Date.parseFunctions = {count:0};
988 Date.parseRegexes = [];
990 Date.formatFunctions = {count:0};
993 Date.prototype.dateFormat = function(format) {
994 if (Date.formatFunctions[format] == null) {
995 Date.createNewFormat(format);
997 var func = Date.formatFunctions[format];
1003 * Formats a date given the supplied format string
1004 * @param {String} format The format string
1005 * @return {String} The formatted date
1008 Date.prototype.format = Date.prototype.dateFormat;
1011 Date.createNewFormat = function(format) {
1012 var funcName = "format" + Date.formatFunctions.count++;
1013 Date.formatFunctions[format] = funcName;
1014 var code = "Date.prototype." + funcName + " = function(){return ";
1015 var special = false;
1017 for (var i = 0; i < format.length; ++i) {
1018 ch = format.charAt(i);
1019 if (!special && ch == "\\") {
1024 code += "'" + String.escape(ch) + "' + ";
1027 code += Date.getFormatCode(ch);
1030 /** eval:var:zzzzzzzzzzzzz */
1031 eval(code.substring(0, code.length - 3) + ";}");
1035 Date.getFormatCode = function(character) {
1036 switch (character) {
1038 return "String.leftPad(this.getDate(), 2, '0') + ";
1040 return "Date.dayNames[this.getDay()].substring(0, 3) + ";
1042 return "this.getDate() + ";
1044 return "Date.dayNames[this.getDay()] + ";
1046 return "this.getSuffix() + ";
1048 return "this.getDay() + ";
1050 return "this.getDayOfYear() + ";
1052 return "this.getWeekOfYear() + ";
1054 return "Date.monthNames[this.getMonth()] + ";
1056 return "String.leftPad(this.getMonth() + 1, 2, '0') + ";
1058 return "Date.monthNames[this.getMonth()].substring(0, 3) + ";
1060 return "(this.getMonth() + 1) + ";
1062 return "this.getDaysInMonth() + ";
1064 return "(this.isLeapYear() ? 1 : 0) + ";
1066 return "this.getFullYear() + ";
1068 return "('' + this.getFullYear()).substring(2, 4) + ";
1070 return "(this.getHours() < 12 ? 'am' : 'pm') + ";
1072 return "(this.getHours() < 12 ? 'AM' : 'PM') + ";
1074 return "((this.getHours() % 12) ? this.getHours() % 12 : 12) + ";
1076 return "this.getHours() + ";
1078 return "String.leftPad((this.getHours() % 12) ? this.getHours() % 12 : 12, 2, '0') + ";
1080 return "String.leftPad(this.getHours(), 2, '0') + ";
1082 return "String.leftPad(this.getMinutes(), 2, '0') + ";
1084 return "String.leftPad(this.getSeconds(), 2, '0') + ";
1086 return "this.getGMTOffset() + ";
1088 return "this.getTimezone() + ";
1090 return "(this.getTimezoneOffset() * -60) + ";
1092 return "'" + String.escape(character) + "' + ";
1097 * Parses the passed string using the specified format. Note that this function expects dates in normal calendar
1098 * format, meaning that months are 1-based (1 = January) and not zero-based like in JavaScript dates. Any part of
1099 * the date format that is not specified will default to the current date value for that part. Time parts can also
1100 * be specified, but default to 0. Keep in mind that the input date string must precisely match the specified format
1101 * string or the parse operation will fail.
1104 //dt = Fri May 25 2007 (current date)
1105 var dt = new Date();
1107 //dt = Thu May 25 2006 (today's month/day in 2006)
1108 dt = Date.parseDate("2006", "Y");
1110 //dt = Sun Jan 15 2006 (all date parts specified)
1111 dt = Date.parseDate("2006-1-15", "Y-m-d");
1113 //dt = Sun Jan 15 2006 15:20:01 GMT-0600 (CST)
1114 dt = Date.parseDate("2006-1-15 3:20:01 PM", "Y-m-d h:i:s A" );
1116 * @param {String} input The unparsed date as a string
1117 * @param {String} format The format the date is in
1118 * @return {Date} The parsed date
1121 Date.parseDate = function(input, format) {
1122 if (Date.parseFunctions[format] == null) {
1123 Date.createParser(format);
1125 var func = Date.parseFunctions[format];
1126 return Date[func](input);
1131 Date.createParser = function(format) {
1132 var funcName = "parse" + Date.parseFunctions.count++;
1133 var regexNum = Date.parseRegexes.length;
1134 var currentGroup = 1;
1135 Date.parseFunctions[format] = funcName;
1137 var code = "Date." + funcName + " = function(input){\n"
1138 + "var y = -1, m = -1, d = -1, h = -1, i = -1, s = -1, o, z, v;\n"
1139 + "var d = new Date();\n"
1140 + "y = d.getFullYear();\n"
1141 + "m = d.getMonth();\n"
1142 + "d = d.getDate();\n"
1143 + "var results = input.match(Date.parseRegexes[" + regexNum + "]);\n"
1144 + "if (results && results.length > 0) {";
1147 var special = false;
1149 for (var i = 0; i < format.length; ++i) {
1150 ch = format.charAt(i);
1151 if (!special && ch == "\\") {
1156 regex += String.escape(ch);
1159 var obj = Date.formatCodeToRegex(ch, currentGroup);
1160 currentGroup += obj.g;
1162 if (obj.g && obj.c) {
1168 code += "if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0 && s >= 0)\n"
1169 + "{v = new Date(y, m, d, h, i, s);}\n"
1170 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0 && i >= 0)\n"
1171 + "{v = new Date(y, m, d, h, i);}\n"
1172 + "else if (y >= 0 && m >= 0 && d > 0 && h >= 0)\n"
1173 + "{v = new Date(y, m, d, h);}\n"
1174 + "else if (y >= 0 && m >= 0 && d > 0)\n"
1175 + "{v = new Date(y, m, d);}\n"
1176 + "else if (y >= 0 && m >= 0)\n"
1177 + "{v = new Date(y, m);}\n"
1178 + "else if (y >= 0)\n"
1179 + "{v = new Date(y);}\n"
1180 + "}return (v && (z || o))?\n" // favour UTC offset over GMT offset
1181 + " ((z)? v.add(Date.SECOND, (v.getTimezoneOffset() * 60) + (z*1)) :\n" // reset to UTC, then add offset
1182 + " v.add(Date.HOUR, (v.getGMTOffset() / 100) + (o / -100))) : v\n" // reset to GMT, then add offset
1185 Date.parseRegexes[regexNum] = new RegExp("^" + regex + "$");
1186 /** eval:var:zzzzzzzzzzzzz */
1191 Date.formatCodeToRegex = function(character, currentGroup) {
1192 switch (character) {
1196 s:"(?:Sun|Mon|Tue|Wed|Thu|Fri|Sat)"};
1199 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1200 s:"(\\d{1,2})"}; // day of month without leading zeroes
1203 c:"d = parseInt(results[" + currentGroup + "], 10);\n",
1204 s:"(\\d{2})"}; // day of month with leading zeroes
1208 s:"(?:" + Date.dayNames.join("|") + ")"};
1212 s:"(?:st|nd|rd|th)"};
1227 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "].substring(0, 3)], 10);\n",
1228 s:"(" + Date.monthNames.join("|") + ")"};
1231 c:"m = parseInt(Date.monthNumbers[results[" + currentGroup + "]], 10);\n",
1232 s:"(Jan|Feb|Mar|Apr|May|Jun|Jul|Aug|Sep|Oct|Nov|Dec)"};
1235 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1236 s:"(\\d{1,2})"}; // Numeric representation of a month, without leading zeros
1239 c:"m = parseInt(results[" + currentGroup + "], 10) - 1;\n",
1240 s:"(\\d{2})"}; // Numeric representation of a month, with leading zeros
1251 c:"y = parseInt(results[" + currentGroup + "], 10);\n",
1255 c:"var ty = parseInt(results[" + currentGroup + "], 10);\n"
1256 + "y = ty > Date.y2kYear ? 1900 + ty : 2000 + ty;\n",
1260 c:"if (results[" + currentGroup + "] == 'am') {\n"
1261 + "if (h == 12) { h = 0; }\n"
1262 + "} else { if (h < 12) { h += 12; }}",
1266 c:"if (results[" + currentGroup + "] == 'AM') {\n"
1267 + "if (h == 12) { h = 0; }\n"
1268 + "} else { if (h < 12) { h += 12; }}",
1273 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1274 s:"(\\d{1,2})"}; // 12/24-hr format format of an hour without leading zeroes
1278 c:"h = parseInt(results[" + currentGroup + "], 10);\n",
1279 s:"(\\d{2})"}; // 12/24-hr format format of an hour with leading zeroes
1282 c:"i = parseInt(results[" + currentGroup + "], 10);\n",
1286 c:"s = parseInt(results[" + currentGroup + "], 10);\n",
1291 "o = results[", currentGroup, "];\n",
1292 "var sn = o.substring(0,1);\n", // get + / - sign
1293 "var hr = o.substring(1,3)*1 + Math.floor(o.substring(3,5) / 60);\n", // get hours (performs minutes-to-hour conversion also)
1294 "var mn = o.substring(3,5) % 60;\n", // get minutes
1295 "o = ((-12 <= (hr*60 + mn)/60) && ((hr*60 + mn)/60 <= 14))?\n", // -12hrs <= GMT offset <= 14hrs
1296 " (sn + String.leftPad(hr, 2, 0) + String.leftPad(mn, 2, 0)) : null;\n"
1302 s:"[A-Z]{1,4}"}; // timezone abbrev. may be between 1 - 4 chars
1305 c:"z = results[" + currentGroup + "];\n" // -43200 <= UTC offset <= 50400
1306 + "z = (-43200 <= z*1 && z*1 <= 50400)? z : null;\n",
1307 s:"([+\-]?\\d{1,5})"}; // leading '+' sign is optional for UTC offset
1311 s:String.escape(character)};
1316 * Get the timezone abbreviation of the current date (equivalent to the format specifier 'T').
1317 * @return {String} The abbreviated timezone name (e.g. 'CST')
1319 Date.prototype.getTimezone = function() {
1320 return this.toString().replace(/^.*? ([A-Z]{1,4})[\-+][0-9]{4} .*$/, "$1");
1324 * Get the offset from GMT of the current date (equivalent to the format specifier 'O').
1325 * @return {String} The 4-character offset string prefixed with + or - (e.g. '-0600')
1327 Date.prototype.getGMTOffset = function() {
1328 return (this.getTimezoneOffset() > 0 ? "-" : "+")
1329 + String.leftPad(Math.abs(Math.floor(this.getTimezoneOffset() / 60)), 2, "0")
1330 + String.leftPad(this.getTimezoneOffset() % 60, 2, "0");
1334 * Get the numeric day number of the year, adjusted for leap year.
1335 * @return {Number} 0 through 364 (365 in leap years)
1337 Date.prototype.getDayOfYear = function() {
1339 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1340 for (var i = 0; i < this.getMonth(); ++i) {
1341 num += Date.daysInMonth[i];
1343 return num + this.getDate() - 1;
1347 * Get the string representation of the numeric week number of the year
1348 * (equivalent to the format specifier 'W').
1349 * @return {String} '00' through '52'
1351 Date.prototype.getWeekOfYear = function() {
1352 // Skip to Thursday of this week
1353 var now = this.getDayOfYear() + (4 - this.getDay());
1354 // Find the first Thursday of the year
1355 var jan1 = new Date(this.getFullYear(), 0, 1);
1356 var then = (7 - jan1.getDay() + 4);
1357 return String.leftPad(((now - then) / 7) + 1, 2, "0");
1361 * Whether or not the current date is in a leap year.
1362 * @return {Boolean} True if the current date is in a leap year, else false
1364 Date.prototype.isLeapYear = function() {
1365 var year = this.getFullYear();
1366 return ((year & 3) == 0 && (year % 100 || (year % 400 == 0 && year)));
1370 * Get the first day of the current month, adjusted for leap year. The returned value
1371 * is the numeric day index within the week (0-6) which can be used in conjunction with
1372 * the {@link #monthNames} array to retrieve the textual day name.
1375 var dt = new Date('1/10/2007');
1376 document.write(Date.dayNames[dt.getFirstDayOfMonth()]); //output: 'Monday'
1378 * @return {Number} The day number (0-6)
1380 Date.prototype.getFirstDayOfMonth = function() {
1381 var day = (this.getDay() - (this.getDate() - 1)) % 7;
1382 return (day < 0) ? (day + 7) : day;
1386 * Get the last day of the current month, adjusted for leap year. The returned value
1387 * is the numeric day index within the week (0-6) which can be used in conjunction with
1388 * the {@link #monthNames} array to retrieve the textual day name.
1391 var dt = new Date('1/10/2007');
1392 document.write(Date.dayNames[dt.getLastDayOfMonth()]); //output: 'Wednesday'
1394 * @return {Number} The day number (0-6)
1396 Date.prototype.getLastDayOfMonth = function() {
1397 var day = (this.getDay() + (Date.daysInMonth[this.getMonth()] - this.getDate())) % 7;
1398 return (day < 0) ? (day + 7) : day;
1403 * Get the first date of this date's month
1406 Date.prototype.getFirstDateOfMonth = function() {
1407 return new Date(this.getFullYear(), this.getMonth(), 1);
1411 * Get the last date of this date's month
1414 Date.prototype.getLastDateOfMonth = function() {
1415 return new Date(this.getFullYear(), this.getMonth(), this.getDaysInMonth());
1418 * Get the number of days in the current month, adjusted for leap year.
1419 * @return {Number} The number of days in the month
1421 Date.prototype.getDaysInMonth = function() {
1422 Date.daysInMonth[1] = this.isLeapYear() ? 29 : 28;
1423 return Date.daysInMonth[this.getMonth()];
1427 * Get the English ordinal suffix of the current day (equivalent to the format specifier 'S').
1428 * @return {String} 'st, 'nd', 'rd' or 'th'
1430 Date.prototype.getSuffix = function() {
1431 switch (this.getDate()) {
1448 Date.daysInMonth = [31,28,31,30,31,30,31,31,30,31,30,31];
1451 * An array of textual month names.
1452 * Override these values for international dates, for example...
1453 * Date.monthNames = ['JanInYourLang', 'FebInYourLang', ...];
1472 * An array of textual day names.
1473 * Override these values for international dates, for example...
1474 * Date.dayNames = ['SundayInYourLang', 'MondayInYourLang', ...];
1490 Date.monthNumbers = {
1505 * Creates and returns a new Date instance with the exact same date value as the called instance.
1506 * Dates are copied and passed by reference, so if a copied date variable is modified later, the original
1507 * variable will also be changed. When the intention is to create a new variable that will not
1508 * modify the original instance, you should create a clone.
1510 * Example of correctly cloning a date:
1513 var orig = new Date('10/1/2006');
1516 document.write(orig); //returns 'Thu Oct 05 2006'!
1519 var orig = new Date('10/1/2006');
1520 var copy = orig.clone();
1522 document.write(orig); //returns 'Thu Oct 01 2006'
1524 * @return {Date} The new Date instance
1526 Date.prototype.clone = function() {
1527 return new Date(this.getTime());
1531 * Clears any time information from this date
1532 @param {Boolean} clone true to create a clone of this date, clear the time and return it
1533 @return {Date} this or the clone
1535 Date.prototype.clearTime = function(clone){
1537 return this.clone().clearTime();
1542 this.setMilliseconds(0);
1547 // safari setMonth is broken
1549 Date.brokenSetMonth = Date.prototype.setMonth;
1550 Date.prototype.setMonth = function(num){
1552 var n = Math.ceil(-num);
1553 var back_year = Math.ceil(n/12);
1554 var month = (n % 12) ? 12 - n % 12 : 0 ;
1555 this.setFullYear(this.getFullYear() - back_year);
1556 return Date.brokenSetMonth.call(this, month);
1558 return Date.brokenSetMonth.apply(this, arguments);
1563 /** Date interval constant
1567 /** Date interval constant
1571 /** Date interval constant
1575 /** Date interval constant
1579 /** Date interval constant
1583 /** Date interval constant
1587 /** Date interval constant
1593 * Provides a convenient method of performing basic date arithmetic. This method
1594 * does not modify the Date instance being called - it creates and returns
1595 * a new Date instance containing the resulting date value.
1600 var dt = new Date('10/29/2006').add(Date.DAY, 5);
1601 document.write(dt); //returns 'Fri Oct 06 2006 00:00:00'
1603 //Negative values will subtract correctly:
1604 var dt2 = new Date('10/1/2006').add(Date.DAY, -5);
1605 document.write(dt2); //returns 'Tue Sep 26 2006 00:00:00'
1607 //You can even chain several calls together in one line!
1608 var dt3 = new Date('10/1/2006').add(Date.DAY, 5).add(Date.HOUR, 8).add(Date.MINUTE, -30);
1609 document.write(dt3); //returns 'Fri Oct 06 2006 07:30:00'
1612 * @param {String} interval A valid date interval enum value
1613 * @param {Number} value The amount to add to the current date
1614 * @return {Date} The new Date instance
1616 Date.prototype.add = function(interval, value){
1617 var d = this.clone();
1618 if (!interval || value === 0) return d;
1619 switch(interval.toLowerCase()){
1621 d.setMilliseconds(this.getMilliseconds() + value);
1624 d.setSeconds(this.getSeconds() + value);
1627 d.setMinutes(this.getMinutes() + value);
1630 d.setHours(this.getHours() + value);
1633 d.setDate(this.getDate() + value);
1636 var day = this.getDate();
1638 day = Math.min(day, this.getFirstDateOfMonth().add('mo', value).getLastDateOfMonth().getDate());
1641 d.setMonth(this.getMonth() + value);
1644 d.setFullYear(this.getFullYear() + value);
1650 * Ext JS Library 1.1.1
1651 * Copyright(c) 2006-2007, Ext JS, LLC.
1653 * Originally Released Under LGPL - original licence link has changed is not relivant.
1656 * <script type="text/javascript">
1660 getViewWidth : function(full) {
1661 return full ? this.getDocumentWidth() : this.getViewportWidth();
1664 getViewHeight : function(full) {
1665 return full ? this.getDocumentHeight() : this.getViewportHeight();
1668 getDocumentHeight: function() {
1669 var scrollHeight = (document.compatMode != "CSS1Compat") ? document.body.scrollHeight : document.documentElement.scrollHeight;
1670 return Math.max(scrollHeight, this.getViewportHeight());
1673 getDocumentWidth: function() {
1674 var scrollWidth = (document.compatMode != "CSS1Compat") ? document.body.scrollWidth : document.documentElement.scrollWidth;
1675 return Math.max(scrollWidth, this.getViewportWidth());
1678 getViewportHeight: function() {
1679 var height = self.innerHeight;
1680 var mode = document.compatMode;
1682 if ((mode || Roo.isIE) && !Roo.isOpera) {
1683 height = (mode == "CSS1Compat") ?
1684 document.documentElement.clientHeight :
1685 document.body.clientHeight;
1691 getViewportWidth: function() {
1692 var width = self.innerWidth;
1693 var mode = document.compatMode;
1695 if (mode || Roo.isIE) {
1696 width = (mode == "CSS1Compat") ?
1697 document.documentElement.clientWidth :
1698 document.body.clientWidth;
1703 isAncestor : function(p, c) {
1710 if (p.contains && !Roo.isSafari) {
1711 return p.contains(c);
1712 } else if (p.compareDocumentPosition) {
1713 return !!(p.compareDocumentPosition(c) & 16);
1715 var parent = c.parentNode;
1720 else if (!parent.tagName || parent.tagName.toUpperCase() == "HTML") {
1723 parent = parent.parentNode;
1729 getRegion : function(el) {
1730 return Roo.lib.Region.getRegion(el);
1733 getY : function(el) {
1734 return this.getXY(el)[1];
1737 getX : function(el) {
1738 return this.getXY(el)[0];
1741 getXY : function(el) {
1742 var p, pe, b, scroll, bd = document.body;
1743 el = Roo.getDom(el);
1744 var fly = Roo.lib.AnimBase.fly;
1745 if (el.getBoundingClientRect) {
1746 b = el.getBoundingClientRect();
1747 scroll = fly(document).getScroll();
1748 return [b.left + scroll.left, b.top + scroll.top];
1754 var hasAbsolute = fly(el).getStyle("position") == "absolute";
1761 if (!hasAbsolute && fly(p).getStyle("position") == "absolute") {
1768 var bt = parseInt(pe.getStyle("borderTopWidth"), 10) || 0;
1769 var bl = parseInt(pe.getStyle("borderLeftWidth"), 10) || 0;
1776 if (p != el && pe.getStyle('overflow') != 'visible') {
1784 if (Roo.isSafari && hasAbsolute) {
1789 if (Roo.isGecko && !hasAbsolute) {
1791 x += parseInt(dbd.getStyle("borderLeftWidth"), 10) || 0;
1792 y += parseInt(dbd.getStyle("borderTopWidth"), 10) || 0;
1796 while (p && p != bd) {
1797 if (!Roo.isOpera || (p.tagName != 'TR' && fly(p).getStyle("display") != "inline")) {
1809 setXY : function(el, xy) {
1810 el = Roo.fly(el, '_setXY');
1812 var pts = el.translatePoints(xy);
1813 if (xy[0] !== false) {
1814 el.dom.style.left = pts.left + "px";
1816 if (xy[1] !== false) {
1817 el.dom.style.top = pts.top + "px";
1821 setX : function(el, x) {
1822 this.setXY(el, [x, false]);
1825 setY : function(el, y) {
1826 this.setXY(el, [false, y]);
1830 * Portions of this file are based on pieces of Yahoo User Interface Library
1831 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
1832 * YUI licensed under the BSD License:
1833 * http://developer.yahoo.net/yui/license.txt
1834 * <script type="text/javascript">
1838 Roo.lib.Event = function() {
1839 var loadComplete = false;
1841 var unloadListeners = [];
1843 var onAvailStack = [];
1845 var lastError = null;
1858 startInterval: function() {
1859 if (!this._interval) {
1861 var callback = function() {
1862 self._tryPreloadAttach();
1864 this._interval = setInterval(callback, this.POLL_INTERVAL);
1869 onAvailable: function(p_id, p_fn, p_obj, p_override) {
1870 onAvailStack.push({ id: p_id,
1873 override: p_override,
1874 checkReady: false });
1876 retryCount = this.POLL_RETRYS;
1877 this.startInterval();
1881 addListener: function(el, eventName, fn) {
1882 el = Roo.getDom(el);
1887 if ("unload" == eventName) {
1888 unloadListeners[unloadListeners.length] =
1889 [el, eventName, fn];
1893 var wrappedFn = function(e) {
1894 return fn(Roo.lib.Event.getEvent(e));
1897 var li = [el, eventName, fn, wrappedFn];
1899 var index = listeners.length;
1900 listeners[index] = li;
1902 this.doAdd(el, eventName, wrappedFn, false);
1908 removeListener: function(el, eventName, fn) {
1911 el = Roo.getDom(el);
1914 return this.purgeElement(el, false, eventName);
1918 if ("unload" == eventName) {
1920 for (i = 0,len = unloadListeners.length; i < len; i++) {
1921 var li = unloadListeners[i];
1924 li[1] == eventName &&
1926 unloadListeners.splice(i, 1);
1934 var cacheItem = null;
1937 var index = arguments[3];
1939 if ("undefined" == typeof index) {
1940 index = this._getCacheIndex(el, eventName, fn);
1944 cacheItem = listeners[index];
1947 if (!el || !cacheItem) {
1951 this.doRemove(el, eventName, cacheItem[this.WFN], false);
1953 delete listeners[index][this.WFN];
1954 delete listeners[index][this.FN];
1955 listeners.splice(index, 1);
1962 getTarget: function(ev, resolveTextNode) {
1963 ev = ev.browserEvent || ev;
1964 var t = ev.target || ev.srcElement;
1965 return this.resolveTextNode(t);
1969 resolveTextNode: function(node) {
1970 if (Roo.isSafari && node && 3 == node.nodeType) {
1971 return node.parentNode;
1978 getPageX: function(ev) {
1979 ev = ev.browserEvent || ev;
1981 if (!x && 0 !== x) {
1982 x = ev.clientX || 0;
1985 x += this.getScroll()[1];
1993 getPageY: function(ev) {
1994 ev = ev.browserEvent || ev;
1996 if (!y && 0 !== y) {
1997 y = ev.clientY || 0;
2000 y += this.getScroll()[0];
2009 getXY: function(ev) {
2010 ev = ev.browserEvent || ev;
2011 return [this.getPageX(ev), this.getPageY(ev)];
2015 getRelatedTarget: function(ev) {
2016 ev = ev.browserEvent || ev;
2017 var t = ev.relatedTarget;
2019 if (ev.type == "mouseout") {
2021 } else if (ev.type == "mouseover") {
2026 return this.resolveTextNode(t);
2030 getTime: function(ev) {
2031 ev = ev.browserEvent || ev;
2033 var t = new Date().getTime();
2037 this.lastError = ex;
2046 stopEvent: function(ev) {
2047 this.stopPropagation(ev);
2048 this.preventDefault(ev);
2052 stopPropagation: function(ev) {
2053 ev = ev.browserEvent || ev;
2054 if (ev.stopPropagation) {
2055 ev.stopPropagation();
2057 ev.cancelBubble = true;
2062 preventDefault: function(ev) {
2063 ev = ev.browserEvent || ev;
2064 if(ev.preventDefault) {
2065 ev.preventDefault();
2067 ev.returnValue = false;
2072 getEvent: function(e) {
2073 var ev = e || window.event;
2075 var c = this.getEvent.caller;
2077 ev = c.arguments[0];
2078 if (ev && Event == ev.constructor) {
2088 getCharCode: function(ev) {
2089 ev = ev.browserEvent || ev;
2090 return ev.charCode || ev.keyCode || 0;
2094 _getCacheIndex: function(el, eventName, fn) {
2095 for (var i = 0,len = listeners.length; i < len; ++i) {
2096 var li = listeners[i];
2098 li[this.FN] == fn &&
2099 li[this.EL] == el &&
2100 li[this.TYPE] == eventName) {
2112 getEl: function(id) {
2113 return document.getElementById(id);
2117 clearCache: function() {
2121 _load: function(e) {
2122 loadComplete = true;
2123 var EU = Roo.lib.Event;
2127 EU.doRemove(window, "load", EU._load);
2132 _tryPreloadAttach: function() {
2141 var tryAgain = !loadComplete;
2143 tryAgain = (retryCount > 0);
2148 for (var i = 0,len = onAvailStack.length; i < len; ++i) {
2149 var item = onAvailStack[i];
2151 var el = this.getEl(item.id);
2154 if (!item.checkReady ||
2157 (document && document.body)) {
2160 if (item.override) {
2161 if (item.override === true) {
2164 scope = item.override;
2167 item.fn.call(scope, item.obj);
2168 onAvailStack[i] = null;
2171 notAvail.push(item);
2176 retryCount = (notAvail.length === 0) ? 0 : retryCount - 1;
2180 this.startInterval();
2182 clearInterval(this._interval);
2183 this._interval = null;
2186 this.locked = false;
2193 purgeElement: function(el, recurse, eventName) {
2194 var elListeners = this.getListeners(el, eventName);
2196 for (var i = 0,len = elListeners.length; i < len; ++i) {
2197 var l = elListeners[i];
2198 this.removeListener(el, l.type, l.fn);
2202 if (recurse && el && el.childNodes) {
2203 for (i = 0,len = el.childNodes.length; i < len; ++i) {
2204 this.purgeElement(el.childNodes[i], recurse, eventName);
2210 getListeners: function(el, eventName) {
2211 var results = [], searchLists;
2213 searchLists = [listeners, unloadListeners];
2214 } else if (eventName == "unload") {
2215 searchLists = [unloadListeners];
2217 searchLists = [listeners];
2220 for (var j = 0; j < searchLists.length; ++j) {
2221 var searchList = searchLists[j];
2222 if (searchList && searchList.length > 0) {
2223 for (var i = 0,len = searchList.length; i < len; ++i) {
2224 var l = searchList[i];
2225 if (l && l[this.EL] === el &&
2226 (!eventName || eventName === l[this.TYPE])) {
2231 adjust: l[this.ADJ_SCOPE],
2239 return (results.length) ? results : null;
2243 _unload: function(e) {
2245 var EU = Roo.lib.Event, i, j, l, len, index;
2247 for (i = 0,len = unloadListeners.length; i < len; ++i) {
2248 l = unloadListeners[i];
2251 if (l[EU.ADJ_SCOPE]) {
2252 if (l[EU.ADJ_SCOPE] === true) {
2255 scope = l[EU.ADJ_SCOPE];
2258 l[EU.FN].call(scope, EU.getEvent(e), l[EU.OBJ]);
2259 unloadListeners[i] = null;
2265 unloadListeners = null;
2267 if (listeners && listeners.length > 0) {
2268 j = listeners.length;
2271 l = listeners[index];
2273 EU.removeListener(l[EU.EL], l[EU.TYPE],
2283 EU.doRemove(window, "unload", EU._unload);
2288 getScroll: function() {
2289 var dd = document.documentElement, db = document.body;
2290 if (dd && (dd.scrollTop || dd.scrollLeft)) {
2291 return [dd.scrollTop, dd.scrollLeft];
2293 return [db.scrollTop, db.scrollLeft];
2300 doAdd: function () {
2301 if (window.addEventListener) {
2302 return function(el, eventName, fn, capture) {
2303 el.addEventListener(eventName, fn, (capture));
2305 } else if (window.attachEvent) {
2306 return function(el, eventName, fn, capture) {
2307 el.attachEvent("on" + eventName, fn);
2316 doRemove: function() {
2317 if (window.removeEventListener) {
2318 return function (el, eventName, fn, capture) {
2319 el.removeEventListener(eventName, fn, (capture));
2321 } else if (window.detachEvent) {
2322 return function (el, eventName, fn) {
2323 el.detachEvent("on" + eventName, fn);
2335 var E = Roo.lib.Event;
2336 E.on = E.addListener;
2337 E.un = E.removeListener;
2339 if (document && document.body) {
2342 E.doAdd(window, "load", E._load);
2344 E.doAdd(window, "unload", E._unload);
2345 E._tryPreloadAttach();
2349 * Portions of this file are based on pieces of Yahoo User Interface Library
2350 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2351 * YUI licensed under the BSD License:
2352 * http://developer.yahoo.net/yui/license.txt
2353 * <script type="text/javascript">
2360 request : function(method, uri, cb, data, options) {
2362 var hs = options.headers;
2365 if(hs.hasOwnProperty(h)){
2366 this.initHeader(h, hs[h], false);
2370 if(options.xmlData){
2371 this.initHeader('Content-Type', 'text/xml', false);
2373 data = options.xmlData;
2377 return this.asyncRequest(method, uri, cb, data);
2380 serializeForm : function(form) {
2381 if(typeof form == 'string') {
2382 form = (document.getElementById(form) || document.forms[form]);
2385 var el, name, val, disabled, data = '', hasSubmit = false;
2386 for (var i = 0; i < form.elements.length; i++) {
2387 el = form.elements[i];
2388 disabled = form.elements[i].disabled;
2389 name = form.elements[i].name;
2390 val = form.elements[i].value;
2392 if (!disabled && name){
2396 case 'select-multiple':
2397 for (var j = 0; j < el.options.length; j++) {
2398 if (el.options[j].selected) {
2400 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].attributes['value'].specified ? el.options[j].value : el.options[j].text) + '&';
2403 data += encodeURIComponent(name) + '=' + encodeURIComponent(el.options[j].hasAttribute('value') ? el.options[j].value : el.options[j].text) + '&';
2411 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2424 if(hasSubmit == false) {
2425 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2430 data += encodeURIComponent(name) + '=' + encodeURIComponent(val) + '&';
2435 data = data.substr(0, data.length - 1);
2443 useDefaultHeader:true,
2445 defaultPostHeader:'application/x-www-form-urlencoded',
2447 useDefaultXhrHeader:true,
2449 defaultXhrHeader:'XMLHttpRequest',
2451 hasDefaultHeaders:true,
2463 setProgId:function(id)
2465 this.activeX.unshift(id);
2468 setDefaultPostHeader:function(b)
2470 this.useDefaultHeader = b;
2473 setDefaultXhrHeader:function(b)
2475 this.useDefaultXhrHeader = b;
2478 setPollingInterval:function(i)
2480 if (typeof i == 'number' && isFinite(i)) {
2481 this.pollInterval = i;
2485 createXhrObject:function(transactionId)
2491 http = new XMLHttpRequest();
2493 obj = { conn:http, tId:transactionId };
2497 for (var i = 0; i < this.activeX.length; ++i) {
2501 http = new ActiveXObject(this.activeX[i]);
2503 obj = { conn:http, tId:transactionId };
2516 getConnectionObject:function()
2519 var tId = this.transactionId;
2523 o = this.createXhrObject(tId);
2525 this.transactionId++;
2536 asyncRequest:function(method, uri, callback, postData)
2538 var o = this.getConnectionObject();
2544 o.conn.open(method, uri, true);
2546 if (this.useDefaultXhrHeader) {
2547 if (!this.defaultHeaders['X-Requested-With']) {
2548 this.initHeader('X-Requested-With', this.defaultXhrHeader, true);
2552 if(postData && this.useDefaultHeader){
2553 this.initHeader('Content-Type', this.defaultPostHeader);
2556 if (this.hasDefaultHeaders || this.hasHeaders) {
2560 this.handleReadyState(o, callback);
2561 o.conn.send(postData || null);
2567 handleReadyState:function(o, callback)
2571 if (callback && callback.timeout) {
2572 this.timeout[o.tId] = window.setTimeout(function() {
2573 oConn.abort(o, callback, true);
2574 }, callback.timeout);
2577 this.poll[o.tId] = window.setInterval(
2579 if (o.conn && o.conn.readyState == 4) {
2580 window.clearInterval(oConn.poll[o.tId]);
2581 delete oConn.poll[o.tId];
2583 if(callback && callback.timeout) {
2584 window.clearTimeout(oConn.timeout[o.tId]);
2585 delete oConn.timeout[o.tId];
2588 oConn.handleTransactionResponse(o, callback);
2591 , this.pollInterval);
2594 handleTransactionResponse:function(o, callback, isAbort)
2598 this.releaseObject(o);
2602 var httpStatus, responseObject;
2606 if (o.conn.status !== undefined && o.conn.status != 0) {
2607 httpStatus = o.conn.status;
2619 if (httpStatus >= 200 && httpStatus < 300) {
2620 responseObject = this.createResponseObject(o, callback.argument);
2621 if (callback.success) {
2622 if (!callback.scope) {
2623 callback.success(responseObject);
2628 callback.success.apply(callback.scope, [responseObject]);
2633 switch (httpStatus) {
2641 responseObject = this.createExceptionObject(o.tId, callback.argument, (isAbort ? isAbort : false));
2642 if (callback.failure) {
2643 if (!callback.scope) {
2644 callback.failure(responseObject);
2647 callback.failure.apply(callback.scope, [responseObject]);
2652 responseObject = this.createResponseObject(o, callback.argument);
2653 if (callback.failure) {
2654 if (!callback.scope) {
2655 callback.failure(responseObject);
2658 callback.failure.apply(callback.scope, [responseObject]);
2664 this.releaseObject(o);
2665 responseObject = null;
2668 createResponseObject:function(o, callbackArg)
2675 var headerStr = o.conn.getAllResponseHeaders();
2676 var header = headerStr.split('\n');
2677 for (var i = 0; i < header.length; i++) {
2678 var delimitPos = header[i].indexOf(':');
2679 if (delimitPos != -1) {
2680 headerObj[header[i].substring(0, delimitPos)] = header[i].substring(delimitPos + 2);
2688 obj.status = o.conn.status;
2689 obj.statusText = o.conn.statusText;
2690 obj.getResponseHeader = headerObj;
2691 obj.getAllResponseHeaders = headerStr;
2692 obj.responseText = o.conn.responseText;
2693 obj.responseXML = o.conn.responseXML;
2695 if (typeof callbackArg !== undefined) {
2696 obj.argument = callbackArg;
2702 createExceptionObject:function(tId, callbackArg, isAbort)
2705 var COMM_ERROR = 'communication failure';
2706 var ABORT_CODE = -1;
2707 var ABORT_ERROR = 'transaction aborted';
2713 obj.status = ABORT_CODE;
2714 obj.statusText = ABORT_ERROR;
2717 obj.status = COMM_CODE;
2718 obj.statusText = COMM_ERROR;
2722 obj.argument = callbackArg;
2728 initHeader:function(label, value, isDefault)
2730 var headerObj = (isDefault) ? this.defaultHeaders : this.headers;
2732 if (headerObj[label] === undefined) {
2733 headerObj[label] = value;
2738 headerObj[label] = value + "," + headerObj[label];
2742 this.hasDefaultHeaders = true;
2745 this.hasHeaders = true;
2750 setHeader:function(o)
2752 if (this.hasDefaultHeaders) {
2753 for (var prop in this.defaultHeaders) {
2754 if (this.defaultHeaders.hasOwnProperty(prop)) {
2755 o.conn.setRequestHeader(prop, this.defaultHeaders[prop]);
2760 if (this.hasHeaders) {
2761 for (var prop in this.headers) {
2762 if (this.headers.hasOwnProperty(prop)) {
2763 o.conn.setRequestHeader(prop, this.headers[prop]);
2767 this.hasHeaders = false;
2771 resetDefaultHeaders:function() {
2772 delete this.defaultHeaders;
2773 this.defaultHeaders = {};
2774 this.hasDefaultHeaders = false;
2777 abort:function(o, callback, isTimeout)
2779 if(this.isCallInProgress(o)) {
2781 window.clearInterval(this.poll[o.tId]);
2782 delete this.poll[o.tId];
2784 delete this.timeout[o.tId];
2787 this.handleTransactionResponse(o, callback, true);
2797 isCallInProgress:function(o)
2800 return o.conn.readyState != 4 && o.conn.readyState != 0;
2809 releaseObject:function(o)
2818 'MSXML2.XMLHTTP.3.0',
2826 * Portions of this file are based on pieces of Yahoo User Interface Library
2827 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2828 * YUI licensed under the BSD License:
2829 * http://developer.yahoo.net/yui/license.txt
2830 * <script type="text/javascript">
2834 Roo.lib.Region = function(t, r, b, l) {
2844 Roo.lib.Region.prototype = {
2845 contains : function(region) {
2846 return ( region.left >= this.left &&
2847 region.right <= this.right &&
2848 region.top >= this.top &&
2849 region.bottom <= this.bottom );
2853 getArea : function() {
2854 return ( (this.bottom - this.top) * (this.right - this.left) );
2857 intersect : function(region) {
2858 var t = Math.max(this.top, region.top);
2859 var r = Math.min(this.right, region.right);
2860 var b = Math.min(this.bottom, region.bottom);
2861 var l = Math.max(this.left, region.left);
2863 if (b >= t && r >= l) {
2864 return new Roo.lib.Region(t, r, b, l);
2869 union : function(region) {
2870 var t = Math.min(this.top, region.top);
2871 var r = Math.max(this.right, region.right);
2872 var b = Math.max(this.bottom, region.bottom);
2873 var l = Math.min(this.left, region.left);
2875 return new Roo.lib.Region(t, r, b, l);
2878 adjust : function(t, l, b, r) {
2887 Roo.lib.Region.getRegion = function(el) {
2888 var p = Roo.lib.Dom.getXY(el);
2891 var r = p[0] + el.offsetWidth;
2892 var b = p[1] + el.offsetHeight;
2895 return new Roo.lib.Region(t, r, b, l);
2898 * Portions of this file are based on pieces of Yahoo User Interface Library
2899 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2900 * YUI licensed under the BSD License:
2901 * http://developer.yahoo.net/yui/license.txt
2902 * <script type="text/javascript">
2905 //@@dep Roo.lib.Region
2908 Roo.lib.Point = function(x, y) {
2909 if (x instanceof Array) {
2913 this.x = this.right = this.left = this[0] = x;
2914 this.y = this.top = this.bottom = this[1] = y;
2917 Roo.lib.Point.prototype = new Roo.lib.Region();
2919 * Portions of this file are based on pieces of Yahoo User Interface Library
2920 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2921 * YUI licensed under the BSD License:
2922 * http://developer.yahoo.net/yui/license.txt
2923 * <script type="text/javascript">
2930 scroll : function(el, args, duration, easing, cb, scope) {
2931 this.run(el, args, duration, easing, cb, scope, Roo.lib.Scroll);
2934 motion : function(el, args, duration, easing, cb, scope) {
2935 this.run(el, args, duration, easing, cb, scope, Roo.lib.Motion);
2938 color : function(el, args, duration, easing, cb, scope) {
2939 this.run(el, args, duration, easing, cb, scope, Roo.lib.ColorAnim);
2942 run : function(el, args, duration, easing, cb, scope, type) {
2943 type = type || Roo.lib.AnimBase;
2944 if (typeof easing == "string") {
2945 easing = Roo.lib.Easing[easing];
2947 var anim = new type(el, args, duration, easing);
2948 anim.animateX(function() {
2949 Roo.callback(cb, scope);
2955 * Portions of this file are based on pieces of Yahoo User Interface Library
2956 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
2957 * YUI licensed under the BSD License:
2958 * http://developer.yahoo.net/yui/license.txt
2959 * <script type="text/javascript">
2967 if (!libFlyweight) {
2968 libFlyweight = new Roo.Element.Flyweight();
2970 libFlyweight.dom = el;
2971 return libFlyweight;
2974 // since this uses fly! - it cant be in DOM (which does not have fly yet..)
2978 Roo.lib.AnimBase = function(el, attributes, duration, method) {
2980 this.init(el, attributes, duration, method);
2984 Roo.lib.AnimBase.fly = fly;
2988 Roo.lib.AnimBase.prototype = {
2990 toString: function() {
2991 var el = this.getEl();
2992 var id = el.id || el.tagName;
2993 return ("Anim " + id);
2997 noNegatives: /width|height|opacity|padding/i,
2998 offsetAttribute: /^((width|height)|(top|left))$/,
2999 defaultUnit: /width|height|top$|bottom$|left$|right$/i,
3000 offsetUnit: /\d+(em|%|en|ex|pt|in|cm|mm|pc)$/i
3004 doMethod: function(attr, start, end) {
3005 return this.method(this.currentFrame, start, end - start, this.totalFrames);
3009 setAttribute: function(attr, val, unit) {
3010 if (this.patterns.noNegatives.test(attr)) {
3011 val = (val > 0) ? val : 0;
3014 Roo.fly(this.getEl(), '_anim').setStyle(attr, val + unit);
3018 getAttribute: function(attr) {
3019 var el = this.getEl();
3020 var val = fly(el).getStyle(attr);
3022 if (val !== 'auto' && !this.patterns.offsetUnit.test(val)) {
3023 return parseFloat(val);
3026 var a = this.patterns.offsetAttribute.exec(attr) || [];
3027 var pos = !!( a[3] );
3028 var box = !!( a[2] );
3031 if (box || (fly(el).getStyle('position') == 'absolute' && pos)) {
3032 val = el['offset' + a[0].charAt(0).toUpperCase() + a[0].substr(1)];
3041 getDefaultUnit: function(attr) {
3042 if (this.patterns.defaultUnit.test(attr)) {
3049 animateX : function(callback, scope) {
3050 var f = function() {
3051 this.onComplete.removeListener(f);
3052 if (typeof callback == "function") {
3053 callback.call(scope || this, this);
3056 this.onComplete.addListener(f, this);
3061 setRuntimeAttribute: function(attr) {
3064 var attributes = this.attributes;
3066 this.runtimeAttributes[attr] = {};
3068 var isset = function(prop) {
3069 return (typeof prop !== 'undefined');
3072 if (!isset(attributes[attr]['to']) && !isset(attributes[attr]['by'])) {
3076 start = ( isset(attributes[attr]['from']) ) ? attributes[attr]['from'] : this.getAttribute(attr);
3079 if (isset(attributes[attr]['to'])) {
3080 end = attributes[attr]['to'];
3081 } else if (isset(attributes[attr]['by'])) {
3082 if (start.constructor == Array) {
3084 for (var i = 0, len = start.length; i < len; ++i) {
3085 end[i] = start[i] + attributes[attr]['by'][i];
3088 end = start + attributes[attr]['by'];
3092 this.runtimeAttributes[attr].start = start;
3093 this.runtimeAttributes[attr].end = end;
3096 this.runtimeAttributes[attr].unit = ( isset(attributes[attr].unit) ) ? attributes[attr]['unit'] : this.getDefaultUnit(attr);
3100 init: function(el, attributes, duration, method) {
3102 var isAnimated = false;
3105 var startTime = null;
3108 var actualFrames = 0;
3111 el = Roo.getDom(el);
3114 this.attributes = attributes || {};
3117 this.duration = duration || 1;
3120 this.method = method || Roo.lib.Easing.easeNone;
3123 this.useSeconds = true;
3126 this.currentFrame = 0;
3129 this.totalFrames = Roo.lib.AnimMgr.fps;
3132 this.getEl = function() {
3137 this.isAnimated = function() {
3142 this.getStartTime = function() {
3146 this.runtimeAttributes = {};
3149 this.animate = function() {
3150 if (this.isAnimated()) {
3154 this.currentFrame = 0;
3156 this.totalFrames = ( this.useSeconds ) ? Math.ceil(Roo.lib.AnimMgr.fps * this.duration) : this.duration;
3158 Roo.lib.AnimMgr.registerElement(this);
3162 this.stop = function(finish) {
3164 this.currentFrame = this.totalFrames;
3165 this._onTween.fire();
3167 Roo.lib.AnimMgr.stop(this);
3170 var onStart = function() {
3171 this.onStart.fire();
3173 this.runtimeAttributes = {};
3174 for (var attr in this.attributes) {
3175 this.setRuntimeAttribute(attr);
3180 startTime = new Date();
3184 var onTween = function() {
3186 duration: new Date() - this.getStartTime(),
3187 currentFrame: this.currentFrame
3190 data.toString = function() {
3192 'duration: ' + data.duration +
3193 ', currentFrame: ' + data.currentFrame
3197 this.onTween.fire(data);
3199 var runtimeAttributes = this.runtimeAttributes;
3201 for (var attr in runtimeAttributes) {
3202 this.setAttribute(attr, this.doMethod(attr, runtimeAttributes[attr].start, runtimeAttributes[attr].end), runtimeAttributes[attr].unit);
3208 var onComplete = function() {
3209 var actual_duration = (new Date() - startTime) / 1000 ;
3212 duration: actual_duration,
3213 frames: actualFrames,
3214 fps: actualFrames / actual_duration
3217 data.toString = function() {
3219 'duration: ' + data.duration +
3220 ', frames: ' + data.frames +
3221 ', fps: ' + data.fps
3227 this.onComplete.fire(data);
3231 this._onStart = new Roo.util.Event(this);
3232 this.onStart = new Roo.util.Event(this);
3233 this.onTween = new Roo.util.Event(this);
3234 this._onTween = new Roo.util.Event(this);
3235 this.onComplete = new Roo.util.Event(this);
3236 this._onComplete = new Roo.util.Event(this);
3237 this._onStart.addListener(onStart);
3238 this._onTween.addListener(onTween);
3239 this._onComplete.addListener(onComplete);
3244 * Portions of this file are based on pieces of Yahoo User Interface Library
3245 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3246 * YUI licensed under the BSD License:
3247 * http://developer.yahoo.net/yui/license.txt
3248 * <script type="text/javascript">
3252 Roo.lib.AnimMgr = new function() {
3269 this.registerElement = function(tween) {
3270 queue[queue.length] = tween;
3272 tween._onStart.fire();
3277 this.unRegister = function(tween, index) {
3278 tween._onComplete.fire();
3279 index = index || getIndex(tween);
3281 queue.splice(index, 1);
3285 if (tweenCount <= 0) {
3291 this.start = function() {
3292 if (thread === null) {
3293 thread = setInterval(this.run, this.delay);
3298 this.stop = function(tween) {
3300 clearInterval(thread);
3302 for (var i = 0, len = queue.length; i < len; ++i) {
3303 if (queue[0].isAnimated()) {
3304 this.unRegister(queue[0], 0);
3313 this.unRegister(tween);
3318 this.run = function() {
3319 for (var i = 0, len = queue.length; i < len; ++i) {
3320 var tween = queue[i];
3321 if (!tween || !tween.isAnimated()) {
3325 if (tween.currentFrame < tween.totalFrames || tween.totalFrames === null)
3327 tween.currentFrame += 1;
3329 if (tween.useSeconds) {
3330 correctFrame(tween);
3332 tween._onTween.fire();
3335 Roo.lib.AnimMgr.stop(tween, i);
3340 var getIndex = function(anim) {
3341 for (var i = 0, len = queue.length; i < len; ++i) {
3342 if (queue[i] == anim) {
3350 var correctFrame = function(tween) {
3351 var frames = tween.totalFrames;
3352 var frame = tween.currentFrame;
3353 var expected = (tween.currentFrame * tween.duration * 1000 / tween.totalFrames);
3354 var elapsed = (new Date() - tween.getStartTime());
3357 if (elapsed < tween.duration * 1000) {
3358 tweak = Math.round((elapsed / expected - 1) * tween.currentFrame);
3360 tweak = frames - (frame + 1);
3362 if (tweak > 0 && isFinite(tweak)) {
3363 if (tween.currentFrame + tweak >= frames) {
3364 tweak = frames - (frame + 1);
3367 tween.currentFrame += tweak;
3371 * Portions of this file are based on pieces of Yahoo User Interface Library
3372 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3373 * YUI licensed under the BSD License:
3374 * http://developer.yahoo.net/yui/license.txt
3375 * <script type="text/javascript">
3378 Roo.lib.Bezier = new function() {
3380 this.getPosition = function(points, t) {
3381 var n = points.length;
3384 for (var i = 0; i < n; ++i) {
3385 tmp[i] = [points[i][0], points[i][1]];
3388 for (var j = 1; j < n; ++j) {
3389 for (i = 0; i < n - j; ++i) {
3390 tmp[i][0] = (1 - t) * tmp[i][0] + t * tmp[parseInt(i + 1, 10)][0];
3391 tmp[i][1] = (1 - t) * tmp[i][1] + t * tmp[parseInt(i + 1, 10)][1];
3395 return [ tmp[0][0], tmp[0][1] ];
3399 * Portions of this file are based on pieces of Yahoo User Interface Library
3400 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3401 * YUI licensed under the BSD License:
3402 * http://developer.yahoo.net/yui/license.txt
3403 * <script type="text/javascript">
3408 Roo.lib.ColorAnim = function(el, attributes, duration, method) {
3409 Roo.lib.ColorAnim.superclass.constructor.call(this, el, attributes, duration, method);
3412 Roo.extend(Roo.lib.ColorAnim, Roo.lib.AnimBase);
3414 var fly = Roo.lib.AnimBase.fly;
3416 var superclass = Y.ColorAnim.superclass;
3417 var proto = Y.ColorAnim.prototype;
3419 proto.toString = function() {
3420 var el = this.getEl();
3421 var id = el.id || el.tagName;
3422 return ("ColorAnim " + id);
3425 proto.patterns.color = /color$/i;
3426 proto.patterns.rgb = /^rgb\(([0-9]+)\s*,\s*([0-9]+)\s*,\s*([0-9]+)\)$/i;
3427 proto.patterns.hex = /^#?([0-9A-F]{2})([0-9A-F]{2})([0-9A-F]{2})$/i;
3428 proto.patterns.hex3 = /^#?([0-9A-F]{1})([0-9A-F]{1})([0-9A-F]{1})$/i;
3429 proto.patterns.transparent = /^transparent|rgba\(0, 0, 0, 0\)$/;
3432 proto.parseColor = function(s) {
3433 if (s.length == 3) {
3437 var c = this.patterns.hex.exec(s);
3438 if (c && c.length == 4) {
3439 return [ parseInt(c[1], 16), parseInt(c[2], 16), parseInt(c[3], 16) ];
3442 c = this.patterns.rgb.exec(s);
3443 if (c && c.length == 4) {
3444 return [ parseInt(c[1], 10), parseInt(c[2], 10), parseInt(c[3], 10) ];
3447 c = this.patterns.hex3.exec(s);
3448 if (c && c.length == 4) {
3449 return [ parseInt(c[1] + c[1], 16), parseInt(c[2] + c[2], 16), parseInt(c[3] + c[3], 16) ];
3454 // since this uses fly! - it cant be in ColorAnim (which does not have fly yet..)
3455 proto.getAttribute = function(attr) {
3456 var el = this.getEl();
3457 if (this.patterns.color.test(attr)) {
3458 var val = fly(el).getStyle(attr);
3460 if (this.patterns.transparent.test(val)) {
3461 var parent = el.parentNode;
3462 val = fly(parent).getStyle(attr);
3464 while (parent && this.patterns.transparent.test(val)) {
3465 parent = parent.parentNode;
3466 val = fly(parent).getStyle(attr);
3467 if (parent.tagName.toUpperCase() == 'HTML') {
3473 val = superclass.getAttribute.call(this, attr);
3478 proto.getAttribute = function(attr) {
3479 var el = this.getEl();
3480 if (this.patterns.color.test(attr)) {
3481 var val = fly(el).getStyle(attr);
3483 if (this.patterns.transparent.test(val)) {
3484 var parent = el.parentNode;
3485 val = fly(parent).getStyle(attr);
3487 while (parent && this.patterns.transparent.test(val)) {
3488 parent = parent.parentNode;
3489 val = fly(parent).getStyle(attr);
3490 if (parent.tagName.toUpperCase() == 'HTML') {
3496 val = superclass.getAttribute.call(this, attr);
3502 proto.doMethod = function(attr, start, end) {
3505 if (this.patterns.color.test(attr)) {
3507 for (var i = 0, len = start.length; i < len; ++i) {
3508 val[i] = superclass.doMethod.call(this, attr, start[i], end[i]);
3511 val = 'rgb(' + Math.floor(val[0]) + ',' + Math.floor(val[1]) + ',' + Math.floor(val[2]) + ')';
3514 val = superclass.doMethod.call(this, attr, start, end);
3520 proto.setRuntimeAttribute = function(attr) {
3521 superclass.setRuntimeAttribute.call(this, attr);
3523 if (this.patterns.color.test(attr)) {
3524 var attributes = this.attributes;
3525 var start = this.parseColor(this.runtimeAttributes[attr].start);
3526 var end = this.parseColor(this.runtimeAttributes[attr].end);
3528 if (typeof attributes[attr]['to'] === 'undefined' && typeof attributes[attr]['by'] !== 'undefined') {
3529 end = this.parseColor(attributes[attr].by);
3531 for (var i = 0, len = start.length; i < len; ++i) {
3532 end[i] = start[i] + end[i];
3536 this.runtimeAttributes[attr].start = start;
3537 this.runtimeAttributes[attr].end = end;
3543 * Portions of this file are based on pieces of Yahoo User Interface Library
3544 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3545 * YUI licensed under the BSD License:
3546 * http://developer.yahoo.net/yui/license.txt
3547 * <script type="text/javascript">
3553 easeNone: function (t, b, c, d) {
3554 return c * t / d + b;
3558 easeIn: function (t, b, c, d) {
3559 return c * (t /= d) * t + b;
3563 easeOut: function (t, b, c, d) {
3564 return -c * (t /= d) * (t - 2) + b;
3568 easeBoth: function (t, b, c, d) {
3569 if ((t /= d / 2) < 1) {
3570 return c / 2 * t * t + b;
3573 return -c / 2 * ((--t) * (t - 2) - 1) + b;
3577 easeInStrong: function (t, b, c, d) {
3578 return c * (t /= d) * t * t * t + b;
3582 easeOutStrong: function (t, b, c, d) {
3583 return -c * ((t = t / d - 1) * t * t * t - 1) + b;
3587 easeBothStrong: function (t, b, c, d) {
3588 if ((t /= d / 2) < 1) {
3589 return c / 2 * t * t * t * t + b;
3592 return -c / 2 * ((t -= 2) * t * t * t - 2) + b;
3597 elasticIn: function (t, b, c, d, a, p) {
3601 if ((t /= d) == 1) {
3608 if (!a || a < Math.abs(c)) {
3613 var s = p / (2 * Math.PI) * Math.asin(c / a);
3616 return -(a * Math.pow(2, 10 * (t -= 1)) * Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3620 elasticOut: function (t, b, c, d, a, p) {
3624 if ((t /= d) == 1) {
3631 if (!a || a < Math.abs(c)) {
3636 var s = p / (2 * Math.PI) * Math.asin(c / a);
3639 return a * Math.pow(2, -10 * t) * Math.sin((t * d - s) * (2 * Math.PI) / p) + c + b;
3643 elasticBoth: function (t, b, c, d, a, p) {
3648 if ((t /= d / 2) == 2) {
3656 if (!a || a < Math.abs(c)) {
3661 var s = p / (2 * Math.PI) * Math.asin(c / a);
3665 return -.5 * (a * Math.pow(2, 10 * (t -= 1)) *
3666 Math.sin((t * d - s) * (2 * Math.PI) / p)) + b;
3668 return a * Math.pow(2, -10 * (t -= 1)) *
3669 Math.sin((t * d - s) * (2 * Math.PI) / p) * .5 + c + b;
3674 backIn: function (t, b, c, d, s) {
3675 if (typeof s == 'undefined') {
3678 return c * (t /= d) * t * ((s + 1) * t - s) + b;
3682 backOut: function (t, b, c, d, s) {
3683 if (typeof s == 'undefined') {
3686 return c * ((t = t / d - 1) * t * ((s + 1) * t + s) + 1) + b;
3690 backBoth: function (t, b, c, d, s) {
3691 if (typeof s == 'undefined') {
3695 if ((t /= d / 2 ) < 1) {
3696 return c / 2 * (t * t * (((s *= (1.525)) + 1) * t - s)) + b;
3698 return c / 2 * ((t -= 2) * t * (((s *= (1.525)) + 1) * t + s) + 2) + b;
3702 bounceIn: function (t, b, c, d) {
3703 return c - Roo.lib.Easing.bounceOut(d - t, 0, c, d) + b;
3707 bounceOut: function (t, b, c, d) {
3708 if ((t /= d) < (1 / 2.75)) {
3709 return c * (7.5625 * t * t) + b;
3710 } else if (t < (2 / 2.75)) {
3711 return c * (7.5625 * (t -= (1.5 / 2.75)) * t + .75) + b;
3712 } else if (t < (2.5 / 2.75)) {
3713 return c * (7.5625 * (t -= (2.25 / 2.75)) * t + .9375) + b;
3715 return c * (7.5625 * (t -= (2.625 / 2.75)) * t + .984375) + b;
3719 bounceBoth: function (t, b, c, d) {
3721 return Roo.lib.Easing.bounceIn(t * 2, 0, c, d) * .5 + b;
3723 return Roo.lib.Easing.bounceOut(t * 2 - d, 0, c, d) * .5 + c * .5 + b;
3726 * Portions of this file are based on pieces of Yahoo User Interface Library
3727 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3728 * YUI licensed under the BSD License:
3729 * http://developer.yahoo.net/yui/license.txt
3730 * <script type="text/javascript">
3734 Roo.lib.Motion = function(el, attributes, duration, method) {
3736 Roo.lib.Motion.superclass.constructor.call(this, el, attributes, duration, method);
3740 Roo.extend(Roo.lib.Motion, Roo.lib.ColorAnim);
3744 var superclass = Y.Motion.superclass;
3745 var proto = Y.Motion.prototype;
3747 proto.toString = function() {
3748 var el = this.getEl();
3749 var id = el.id || el.tagName;
3750 return ("Motion " + id);
3753 proto.patterns.points = /^points$/i;
3755 proto.setAttribute = function(attr, val, unit) {
3756 if (this.patterns.points.test(attr)) {
3757 unit = unit || 'px';
3758 superclass.setAttribute.call(this, 'left', val[0], unit);
3759 superclass.setAttribute.call(this, 'top', val[1], unit);
3761 superclass.setAttribute.call(this, attr, val, unit);
3765 proto.getAttribute = function(attr) {
3766 if (this.patterns.points.test(attr)) {
3768 superclass.getAttribute.call(this, 'left'),
3769 superclass.getAttribute.call(this, 'top')
3772 val = superclass.getAttribute.call(this, attr);
3778 proto.doMethod = function(attr, start, end) {
3781 if (this.patterns.points.test(attr)) {
3782 var t = this.method(this.currentFrame, 0, 100, this.totalFrames) / 100;
3783 val = Y.Bezier.getPosition(this.runtimeAttributes[attr], t);
3785 val = superclass.doMethod.call(this, attr, start, end);
3790 proto.setRuntimeAttribute = function(attr) {
3791 if (this.patterns.points.test(attr)) {
3792 var el = this.getEl();
3793 var attributes = this.attributes;
3795 var control = attributes['points']['control'] || [];
3799 if (control.length > 0 && !(control[0] instanceof Array)) {
3800 control = [control];
3803 for (i = 0,len = control.length; i < len; ++i) {
3804 tmp[i] = control[i];
3809 Roo.fly(el).position();
3811 if (isset(attributes['points']['from'])) {
3812 Roo.lib.Dom.setXY(el, attributes['points']['from']);
3815 Roo.lib.Dom.setXY(el, Roo.lib.Dom.getXY(el));
3818 start = this.getAttribute('points');
3821 if (isset(attributes['points']['to'])) {
3822 end = translateValues.call(this, attributes['points']['to'], start);
3824 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3825 for (i = 0,len = control.length; i < len; ++i) {
3826 control[i] = translateValues.call(this, control[i], start);
3830 } else if (isset(attributes['points']['by'])) {
3831 end = [ start[0] + attributes['points']['by'][0], start[1] + attributes['points']['by'][1] ];
3833 for (i = 0,len = control.length; i < len; ++i) {
3834 control[i] = [ start[0] + control[i][0], start[1] + control[i][1] ];
3838 this.runtimeAttributes[attr] = [start];
3840 if (control.length > 0) {
3841 this.runtimeAttributes[attr] = this.runtimeAttributes[attr].concat(control);
3844 this.runtimeAttributes[attr][this.runtimeAttributes[attr].length] = end;
3847 superclass.setRuntimeAttribute.call(this, attr);
3851 var translateValues = function(val, start) {
3852 var pageXY = Roo.lib.Dom.getXY(this.getEl());
3853 val = [ val[0] - pageXY[0] + start[0], val[1] - pageXY[1] + start[1] ];
3858 var isset = function(prop) {
3859 return (typeof prop !== 'undefined');
3863 * Portions of this file are based on pieces of Yahoo User Interface Library
3864 * Copyright (c) 2007, Yahoo! Inc. All rights reserved.
3865 * YUI licensed under the BSD License:
3866 * http://developer.yahoo.net/yui/license.txt
3867 * <script type="text/javascript">
3871 Roo.lib.Scroll = function(el, attributes, duration, method) {
3873 Roo.lib.Scroll.superclass.constructor.call(this, el, attributes, duration, method);
3877 Roo.extend(Roo.lib.Scroll, Roo.lib.ColorAnim);
3881 var superclass = Y.Scroll.superclass;
3882 var proto = Y.Scroll.prototype;
3884 proto.toString = function() {
3885 var el = this.getEl();
3886 var id = el.id || el.tagName;
3887 return ("Scroll " + id);
3890 proto.doMethod = function(attr, start, end) {
3893 if (attr == 'scroll') {
3895 this.method(this.currentFrame, start[0], end[0] - start[0], this.totalFrames),
3896 this.method(this.currentFrame, start[1], end[1] - start[1], this.totalFrames)
3900 val = superclass.doMethod.call(this, attr, start, end);
3905 proto.getAttribute = function(attr) {
3907 var el = this.getEl();
3909 if (attr == 'scroll') {
3910 val = [ el.scrollLeft, el.scrollTop ];
3912 val = superclass.getAttribute.call(this, attr);
3918 proto.setAttribute = function(attr, val, unit) {
3919 var el = this.getEl();
3921 if (attr == 'scroll') {
3922 el.scrollLeft = val[0];
3923 el.scrollTop = val[1];
3925 superclass.setAttribute.call(this, attr, val, unit);
3931 * Ext JS Library 1.1.1
3932 * Copyright(c) 2006-2007, Ext JS, LLC.
3934 * Originally Released Under LGPL - original licence link has changed is not relivant.
3937 * <script type="text/javascript">
3942 * @class Roo.DomHelper
3943 * Utility class for working with DOM and/or Templates. It transparently supports using HTML fragments or DOM.
3944 * 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>.
3947 Roo.DomHelper = function(){
3948 var tempTableEl = null;
3949 var emptyTags = /^(?:br|frame|hr|img|input|link|meta|range|spacer|wbr|area|param|col)$/i;
3950 var tableRe = /^table|tbody|tr|td$/i;
3952 // build as innerHTML where available
3954 var createHtml = function(o){
3955 if(typeof o == 'string'){
3964 if(attr == "tag" || attr == "children" || attr == "cn" || attr == "html" || typeof o[attr] == "function") continue;
3965 if(attr == "style"){
3967 if(typeof s == "function"){
3970 if(typeof s == "string"){
3971 b += ' style="' + s + '"';
3972 }else if(typeof s == "object"){
3975 if(typeof s[key] != "function"){
3976 b += key + ":" + s[key] + ";";
3983 b += ' class="' + o["cls"] + '"';
3984 }else if(attr == "htmlFor"){
3985 b += ' for="' + o["htmlFor"] + '"';
3987 b += " " + attr + '="' + o[attr] + '"';
3991 if(emptyTags.test(o.tag)){
3995 var cn = o.children || o.cn;
3997 //http://bugs.kde.org/show_bug.cgi?id=71506
3998 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
3999 for(var i = 0, len = cn.length; i < len; i++) {
4000 b += createHtml(cn[i], b);
4003 b += createHtml(cn, b);
4009 b += "</" + o.tag + ">";
4016 var createDom = function(o, parentNode){
4018 // defininition craeted..
4020 if (o.ns && o.ns != 'html') {
4022 if (o.xmlns && typeof(xmlns[o.ns]) == 'undefined') {
4023 xmlns[o.ns] = o.xmlns;
4026 if (typeof(xmlns[o.ns]) == 'undefined') {
4027 console.log("Trying to create namespace element " + o.ns + ", however no xmlns was sent to builder previously");
4033 if (typeof(o) == 'string') {
4034 return parentNode.appendChild(document.createTextNode(o));
4036 o.tag = o.tag || div;
4037 if (o.ns && Roo.isIE) {
4039 o.tag = o.ns + ':' + o.tag;
4042 var el = ns ? document.createElementNS( ns, o.tag||'div') : document.createElement(o.tag||'div');
4043 var useSet = el.setAttribute ? true : false; // In IE some elements don't have setAttribute
4046 if(attr == "tag" || attr == "ns" ||attr == "xmlns" ||attr == "children" || attr == "cn" || attr == "html" ||
4047 attr == "style" || typeof o[attr] == "function") continue;
4049 if(attr=="cls" && Roo.isIE){
4050 el.className = o["cls"];
4052 if(useSet) el.setAttribute(attr=="cls" ? 'class' : attr, o[attr]);
4053 else el[attr] = o[attr];
4056 Roo.DomHelper.applyStyles(el, o.style);
4057 var cn = o.children || o.cn;
4059 //http://bugs.kde.org/show_bug.cgi?id=71506
4060 if((cn instanceof Array) || (Roo.isSafari && typeof(cn.join) == "function")){
4061 for(var i = 0, len = cn.length; i < len; i++) {
4062 createDom(cn[i], el);
4069 el.innerHTML = o.html;
4072 parentNode.appendChild(el);
4077 var ieTable = function(depth, s, h, e){
4078 tempTableEl.innerHTML = [s, h, e].join('');
4079 var i = -1, el = tempTableEl;
4086 // kill repeat to save bytes
4090 tbe = '</tbody>'+te,
4096 * Nasty code for IE's broken table implementation
4098 var insertIntoTable = function(tag, where, el, html){
4100 tempTableEl = document.createElement('div');
4105 if(where == 'afterbegin' || where == 'beforeend'){ // INTO a TD
4108 if(where == 'beforebegin'){
4112 before = el.nextSibling;
4115 node = ieTable(4, trs, html, tre);
4117 else if(tag == 'tr'){
4118 if(where == 'beforebegin'){
4121 node = ieTable(3, tbs, html, tbe);
4122 } else if(where == 'afterend'){
4123 before = el.nextSibling;
4125 node = ieTable(3, tbs, html, tbe);
4126 } else{ // INTO a TR
4127 if(where == 'afterbegin'){
4128 before = el.firstChild;
4130 node = ieTable(4, trs, html, tre);
4132 } else if(tag == 'tbody'){
4133 if(where == 'beforebegin'){
4136 node = ieTable(2, ts, html, te);
4137 } else if(where == 'afterend'){
4138 before = el.nextSibling;
4140 node = ieTable(2, ts, html, te);
4142 if(where == 'afterbegin'){
4143 before = el.firstChild;
4145 node = ieTable(3, tbs, html, tbe);
4148 if(where == 'beforebegin' || where == 'afterend'){ // OUTSIDE the table
4151 if(where == 'afterbegin'){
4152 before = el.firstChild;
4154 node = ieTable(2, ts, html, te);
4156 el.insertBefore(node, before);
4161 /** True to force the use of DOM instead of html fragments @type Boolean */
4165 * Returns the markup for the passed Element(s) config
4166 * @param {Object} o The Dom object spec (and children)
4169 markup : function(o){
4170 return createHtml(o);
4174 * Applies a style specification to an element
4175 * @param {String/HTMLElement} el The element to apply styles to
4176 * @param {String/Object/Function} styles A style specification string eg "width:100px", or object in the form {width:"100px"}, or
4177 * a function which returns such a specification.
4179 applyStyles : function(el, styles){
4182 if(typeof styles == "string"){
4183 var re = /\s?([a-z\-]*)\:\s?([^;]*);?/gi;
4185 while ((matches = re.exec(styles)) != null){
4186 el.setStyle(matches[1], matches[2]);
4188 }else if (typeof styles == "object"){
4189 for (var style in styles){
4190 el.setStyle(style, styles[style]);
4192 }else if (typeof styles == "function"){
4193 Roo.DomHelper.applyStyles(el, styles.call());
4199 * Inserts an HTML fragment into the Dom
4200 * @param {String} where Where to insert the html in relation to el - beforeBegin, afterBegin, beforeEnd, afterEnd.
4201 * @param {HTMLElement} el The context element
4202 * @param {String} html The HTML fragmenet
4203 * @return {HTMLElement} The new node
4205 insertHtml : function(where, el, html){
4206 where = where.toLowerCase();
4207 if(el.insertAdjacentHTML){
4208 if(tableRe.test(el.tagName)){
4210 if(rs = insertIntoTable(el.tagName.toLowerCase(), where, el, html)){
4216 el.insertAdjacentHTML('BeforeBegin', html);
4217 return el.previousSibling;
4219 el.insertAdjacentHTML('AfterBegin', html);
4220 return el.firstChild;
4222 el.insertAdjacentHTML('BeforeEnd', html);
4223 return el.lastChild;
4225 el.insertAdjacentHTML('AfterEnd', html);
4226 return el.nextSibling;
4228 throw 'Illegal insertion point -> "' + where + '"';
4230 var range = el.ownerDocument.createRange();
4234 range.setStartBefore(el);
4235 frag = range.createContextualFragment(html);
4236 el.parentNode.insertBefore(frag, el);
4237 return el.previousSibling;
4240 range.setStartBefore(el.firstChild);
4241 frag = range.createContextualFragment(html);
4242 el.insertBefore(frag, el.firstChild);
4243 return el.firstChild;
4245 el.innerHTML = html;
4246 return el.firstChild;
4250 range.setStartAfter(el.lastChild);
4251 frag = range.createContextualFragment(html);
4252 el.appendChild(frag);
4253 return el.lastChild;
4255 el.innerHTML = html;
4256 return el.lastChild;
4259 range.setStartAfter(el);
4260 frag = range.createContextualFragment(html);
4261 el.parentNode.insertBefore(frag, el.nextSibling);
4262 return el.nextSibling;
4264 throw 'Illegal insertion point -> "' + where + '"';
4268 * Creates new Dom element(s) and inserts them before el
4269 * @param {String/HTMLElement/Element} el The context element
4270 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4271 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4272 * @return {HTMLElement/Roo.Element} The new node
4274 insertBefore : function(el, o, returnElement){
4275 return this.doInsert(el, o, returnElement, "beforeBegin");
4279 * Creates new Dom element(s) and inserts them after el
4280 * @param {String/HTMLElement/Element} el The context element
4281 * @param {Object} o The Dom object spec (and children)
4282 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4283 * @return {HTMLElement/Roo.Element} The new node
4285 insertAfter : function(el, o, returnElement){
4286 return this.doInsert(el, o, returnElement, "afterEnd", "nextSibling");
4290 * Creates new Dom element(s) and inserts them as the first child of 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 insertFirst : function(el, o, returnElement){
4297 return this.doInsert(el, o, returnElement, "afterBegin");
4301 doInsert : function(el, o, returnElement, pos, sibling){
4302 el = Roo.getDom(el);
4304 if(this.useDom || o.ns){
4305 newNode = createDom(o, null);
4306 el.parentNode.insertBefore(newNode, sibling ? el[sibling] : el);
4308 var html = createHtml(o);
4309 newNode = this.insertHtml(pos, el, html);
4311 return returnElement ? Roo.get(newNode, true) : newNode;
4315 * Creates new Dom element(s) and appends them to el
4316 * @param {String/HTMLElement/Element} el The context element
4317 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4318 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4319 * @return {HTMLElement/Roo.Element} The new node
4321 append : function(el, o, returnElement){
4322 el = Roo.getDom(el);
4324 if(this.useDom || o.ns){
4325 newNode = createDom(o, null);
4326 el.appendChild(newNode);
4328 var html = createHtml(o);
4329 newNode = this.insertHtml("beforeEnd", el, html);
4331 return returnElement ? Roo.get(newNode, true) : newNode;
4335 * Creates new Dom element(s) and overwrites the contents of el with them
4336 * @param {String/HTMLElement/Element} el The context element
4337 * @param {Object/String} o The Dom object spec (and children) or raw HTML blob
4338 * @param {Boolean} returnElement (optional) true to return a Roo.Element
4339 * @return {HTMLElement/Roo.Element} The new node
4341 overwrite : function(el, o, returnElement){
4342 el = Roo.getDom(el);
4345 while (el.childNodes.length) {
4346 el.removeChild(el.firstChild);
4350 el.innerHTML = createHtml(o);
4353 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4357 * Creates a new Roo.DomHelper.Template from the Dom object spec
4358 * @param {Object} o The Dom object spec (and children)
4359 * @return {Roo.DomHelper.Template} The new template
4361 createTemplate : function(o){
4362 var html = createHtml(o);
4363 return new Roo.Template(html);
4369 * Ext JS Library 1.1.1
4370 * Copyright(c) 2006-2007, Ext JS, LLC.
4372 * Originally Released Under LGPL - original licence link has changed is not relivant.
4375 * <script type="text/javascript">
4379 * @class Roo.Template
4380 * Represents an HTML fragment template. Templates can be precompiled for greater performance.
4381 * For a list of available format functions, see {@link Roo.util.Format}.<br />
4384 var t = new Roo.Template(
4385 '<div name="{id}">',
4386 '<span class="{cls}">{name:trim} {value:ellipsis(10)}</span>',
4389 t.append('some-element', {id: 'myid', cls: 'myclass', name: 'foo', value: 'bar'});
4391 * 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>.
4393 * @param {String/Array} html The HTML fragment or an array of fragments to join("") or multiple arguments to join("")
4395 Roo.Template = function(html){
4396 if(html instanceof Array){
4397 html = html.join("");
4398 }else if(arguments.length > 1){
4399 html = Array.prototype.join.call(arguments, "");
4405 Roo.Template.prototype = {
4407 * Returns an HTML fragment of this template with the specified values applied.
4408 * @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'})
4409 * @return {String} The HTML fragment
4411 applyTemplate : function(values){
4413 return this.compiled(values);
4415 var useF = this.disableFormats !== true;
4416 var fm = Roo.util.Format, tpl = this;
4417 var fn = function(m, name, format, args){
4419 if(format.substr(0, 5) == "this."){
4420 return tpl.call(format.substr(5), values[name], values);
4423 // quoted values are required for strings in compiled templates,
4424 // but for non compiled we need to strip them
4425 // quoted reversed for jsmin
4426 var re = /^\s*['"](.*)["']\s*$/;
4427 args = args.split(',');
4428 for(var i = 0, len = args.length; i < len; i++){
4429 args[i] = args[i].replace(re, "$1");
4431 args = [values[name]].concat(args);
4433 args = [values[name]];
4435 return fm[format].apply(fm, args);
4438 return values[name] !== undefined ? values[name] : "";
4441 return this.html.replace(this.re, fn);
4445 * Sets the HTML used as the template and optionally compiles it.
4446 * @param {String} html
4447 * @param {Boolean} compile (optional) True to compile the template (defaults to undefined)
4448 * @return {Roo.Template} this
4450 set : function(html, compile){
4452 this.compiled = null;
4460 * True to disable format functions (defaults to false)
4463 disableFormats : false,
4466 * The regular expression used to match template variables
4470 re : /\{([\w-]+)(?:\:([\w\.]*)(?:\((.*?)?\))?)?\}/g,
4473 * Compiles the template into an internal function, eliminating the RegEx overhead.
4474 * @return {Roo.Template} this
4476 compile : function(){
4477 var fm = Roo.util.Format;
4478 var useF = this.disableFormats !== true;
4479 var sep = Roo.isGecko ? "+" : ",";
4480 var fn = function(m, name, format, args){
4482 args = args ? ',' + args : "";
4483 if(format.substr(0, 5) != "this."){
4484 format = "fm." + format + '(';
4486 format = 'this.call("'+ format.substr(5) + '", ';
4490 args= ''; format = "(values['" + name + "'] == undefined ? '' : ";
4492 return "'"+ sep + format + "values['" + name + "']" + args + ")"+sep+"'";
4495 // branched to use + in gecko and [].join() in others
4497 body = "this.compiled = function(values){ return '" +
4498 this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn) +
4501 body = ["this.compiled = function(values){ return ['"];
4502 body.push(this.html.replace(/\\/g, '\\\\').replace(/(\r\n|\n)/g, '\\n').replace(/'/g, "\\'").replace(this.re, fn));
4503 body.push("'].join('');};");
4504 body = body.join('');
4514 // private function used to call members
4515 call : function(fnName, value, allValues){
4516 return this[fnName](value, allValues);
4520 * Applies the supplied values to the template and inserts the new node(s) as the first child of el.
4521 * @param {String/HTMLElement/Roo.Element} el The context element
4522 * @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'})
4523 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4524 * @return {HTMLElement/Roo.Element} The new node or Element
4526 insertFirst: function(el, values, returnElement){
4527 return this.doInsert('afterBegin', el, values, returnElement);
4531 * Applies the supplied values to the template and inserts the new node(s) before el.
4532 * @param {String/HTMLElement/Roo.Element} el The context element
4533 * @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'})
4534 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4535 * @return {HTMLElement/Roo.Element} The new node or Element
4537 insertBefore: function(el, values, returnElement){
4538 return this.doInsert('beforeBegin', el, values, returnElement);
4542 * Applies the supplied values to the template and inserts the new node(s) after el.
4543 * @param {String/HTMLElement/Roo.Element} el The context element
4544 * @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'})
4545 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4546 * @return {HTMLElement/Roo.Element} The new node or Element
4548 insertAfter : function(el, values, returnElement){
4549 return this.doInsert('afterEnd', el, values, returnElement);
4553 * Applies the supplied values to the template and appends the new node(s) to el.
4554 * @param {String/HTMLElement/Roo.Element} el The context element
4555 * @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'})
4556 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4557 * @return {HTMLElement/Roo.Element} The new node or Element
4559 append : function(el, values, returnElement){
4560 return this.doInsert('beforeEnd', el, values, returnElement);
4563 doInsert : function(where, el, values, returnEl){
4564 el = Roo.getDom(el);
4565 var newNode = Roo.DomHelper.insertHtml(where, el, this.applyTemplate(values));
4566 return returnEl ? Roo.get(newNode, true) : newNode;
4570 * Applies the supplied values to the template and overwrites the content of el with the new node(s).
4571 * @param {String/HTMLElement/Roo.Element} el The context element
4572 * @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'})
4573 * @param {Boolean} returnElement (optional) true to return a Roo.Element (defaults to undefined)
4574 * @return {HTMLElement/Roo.Element} The new node or Element
4576 overwrite : function(el, values, returnElement){
4577 el = Roo.getDom(el);
4578 el.innerHTML = this.applyTemplate(values);
4579 return returnElement ? Roo.get(el.firstChild, true) : el.firstChild;
4583 * Alias for {@link #applyTemplate}
4586 Roo.Template.prototype.apply = Roo.Template.prototype.applyTemplate;
4589 Roo.DomHelper.Template = Roo.Template;
4592 * Creates a template from the passed element's value (<i>display:none</i> textarea, preferred) or innerHTML.
4593 * @param {String/HTMLElement} el A DOM element or its id
4594 * @returns {Roo.Template} The created template
4597 Roo.Template.from = function(el){
4598 el = Roo.getDom(el);
4599 return new Roo.Template(el.value || el.innerHTML);
4602 * Ext JS Library 1.1.1
4603 * Copyright(c) 2006-2007, Ext JS, LLC.
4605 * Originally Released Under LGPL - original licence link has changed is not relivant.
4608 * <script type="text/javascript">
4613 * This is code is also distributed under MIT license for use
4614 * with jQuery and prototype JavaScript libraries.
4617 * @class Roo.DomQuery
4618 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).
4620 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>
4623 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.
4625 <h4>Element Selectors:</h4>
4627 <li> <b>*</b> any element</li>
4628 <li> <b>E</b> an element with the tag E</li>
4629 <li> <b>E F</b> All descendent elements of E that have the tag F</li>
4630 <li> <b>E > F</b> or <b>E/F</b> all direct children elements of E that have the tag F</li>
4631 <li> <b>E + F</b> all elements with the tag F that are immediately preceded by an element with the tag E</li>
4632 <li> <b>E ~ F</b> all elements with the tag F that are preceded by a sibling element with the tag E</li>
4634 <h4>Attribute Selectors:</h4>
4635 <p>The use of @ and quotes are optional. For example, div[@foo='bar'] is also a valid attribute selector.</p>
4637 <li> <b>E[foo]</b> has an attribute "foo"</li>
4638 <li> <b>E[foo=bar]</b> has an attribute "foo" that equals "bar"</li>
4639 <li> <b>E[foo^=bar]</b> has an attribute "foo" that starts with "bar"</li>
4640 <li> <b>E[foo$=bar]</b> has an attribute "foo" that ends with "bar"</li>
4641 <li> <b>E[foo*=bar]</b> has an attribute "foo" that contains the substring "bar"</li>
4642 <li> <b>E[foo%=2]</b> has an attribute "foo" that is evenly divisible by 2</li>
4643 <li> <b>E[foo!=bar]</b> has an attribute "foo" that does not equal "bar"</li>
4645 <h4>Pseudo Classes:</h4>
4647 <li> <b>E:first-child</b> E is the first child of its parent</li>
4648 <li> <b>E:last-child</b> E is the last child of its parent</li>
4649 <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>
4650 <li> <b>E:nth-child(odd)</b> E is an odd child of its parent</li>
4651 <li> <b>E:nth-child(even)</b> E is an even child of its parent</li>
4652 <li> <b>E:only-child</b> E is the only child of its parent</li>
4653 <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>
4654 <li> <b>E:first</b> the first E in the resultset</li>
4655 <li> <b>E:last</b> the last E in the resultset</li>
4656 <li> <b>E:nth(<i>n</i>)</b> the <i>n</i>th E in the resultset (1 based)</li>
4657 <li> <b>E:odd</b> shortcut for :nth-child(odd)</li>
4658 <li> <b>E:even</b> shortcut for :nth-child(even)</li>
4659 <li> <b>E:contains(foo)</b> E's innerHTML contains the substring "foo"</li>
4660 <li> <b>E:nodeValue(foo)</b> E contains a textNode with a nodeValue that equals "foo"</li>
4661 <li> <b>E:not(S)</b> an E element that does not match simple selector S</li>
4662 <li> <b>E:has(S)</b> an E element that has a descendent that matches simple selector S</li>
4663 <li> <b>E:next(S)</b> an E element whose next sibling matches simple selector S</li>
4664 <li> <b>E:prev(S)</b> an E element whose previous sibling matches simple selector S</li>
4666 <h4>CSS Value Selectors:</h4>
4668 <li> <b>E{display=none}</b> css value "display" that equals "none"</li>
4669 <li> <b>E{display^=none}</b> css value "display" that starts with "none"</li>
4670 <li> <b>E{display$=none}</b> css value "display" that ends with "none"</li>
4671 <li> <b>E{display*=none}</b> css value "display" that contains the substring "none"</li>
4672 <li> <b>E{display%=2}</b> css value "display" that is evenly divisible by 2</li>
4673 <li> <b>E{display!=none}</b> css value "display" that does not equal "none"</li>
4677 Roo.DomQuery = function(){
4678 var cache = {}, simpleCache = {}, valueCache = {};
4679 var nonSpace = /\S/;
4680 var trimRe = /^\s+|\s+$/g;
4681 var tplRe = /\{(\d+)\}/g;
4682 var modeRe = /^(\s?[\/>+~]\s?|\s|$)/;
4683 var tagTokenRe = /^(#)?([\w-\*]+)/;
4684 var nthRe = /(\d*)n\+?(\d*)/, nthRe2 = /\D/;
4686 function child(p, index){
4688 var n = p.firstChild;
4690 if(n.nodeType == 1){
4701 while((n = n.nextSibling) && n.nodeType != 1);
4706 while((n = n.previousSibling) && n.nodeType != 1);
4710 function children(d){
4711 var n = d.firstChild, ni = -1;
4713 var nx = n.nextSibling;
4714 if(n.nodeType == 3 && !nonSpace.test(n.nodeValue)){
4724 function byClassName(c, a, v){
4728 var r = [], ri = -1, cn;
4729 for(var i = 0, ci; ci = c[i]; i++){
4730 if((' '+ci.className+' ').indexOf(v) != -1){
4737 function attrValue(n, attr){
4738 if(!n.tagName && typeof n.length != "undefined"){
4747 if(attr == "class" || attr == "className"){
4750 return n.getAttribute(attr) || n[attr];
4754 function getNodes(ns, mode, tagName){
4755 var result = [], ri = -1, cs;
4759 tagName = tagName || "*";
4760 if(typeof ns.getElementsByTagName != "undefined"){
4764 for(var i = 0, ni; ni = ns[i]; i++){
4765 cs = ni.getElementsByTagName(tagName);
4766 for(var j = 0, ci; ci = cs[j]; j++){
4770 }else if(mode == "/" || mode == ">"){
4771 var utag = tagName.toUpperCase();
4772 for(var i = 0, ni, cn; ni = ns[i]; i++){
4773 cn = ni.children || ni.childNodes;
4774 for(var j = 0, cj; cj = cn[j]; j++){
4775 if(cj.nodeName == utag || cj.nodeName == tagName || tagName == '*'){
4780 }else if(mode == "+"){
4781 var utag = tagName.toUpperCase();
4782 for(var i = 0, n; n = ns[i]; i++){
4783 while((n = n.nextSibling) && n.nodeType != 1);
4784 if(n && (n.nodeName == utag || n.nodeName == tagName || tagName == '*')){
4788 }else if(mode == "~"){
4789 for(var i = 0, n; n = ns[i]; i++){
4790 while((n = n.nextSibling) && (n.nodeType != 1 || (tagName == '*' || n.tagName.toLowerCase()!=tagName)));
4799 function concat(a, b){
4803 for(var i = 0, l = b.length; i < l; i++){
4809 function byTag(cs, tagName){
4810 if(cs.tagName || cs == document){
4816 var r = [], ri = -1;
4817 tagName = tagName.toLowerCase();
4818 for(var i = 0, ci; ci = cs[i]; i++){
4819 if(ci.nodeType == 1 && ci.tagName.toLowerCase()==tagName){
4826 function byId(cs, attr, id){
4827 if(cs.tagName || cs == document){
4833 var r = [], ri = -1;
4834 for(var i = 0,ci; ci = cs[i]; i++){
4835 if(ci && ci.id == id){
4843 function byAttribute(cs, attr, value, op, custom){
4844 var r = [], ri = -1, st = custom=="{";
4845 var f = Roo.DomQuery.operators[op];
4846 for(var i = 0, ci; ci = cs[i]; i++){
4849 a = Roo.DomQuery.getStyle(ci, attr);
4851 else if(attr == "class" || attr == "className"){
4853 }else if(attr == "for"){
4855 }else if(attr == "href"){
4856 a = ci.getAttribute("href", 2);
4858 a = ci.getAttribute(attr);
4860 if((f && f(a, value)) || (!f && a)){
4867 function byPseudo(cs, name, value){
4868 return Roo.DomQuery.pseudos[name](cs, value);
4871 // This is for IE MSXML which does not support expandos.
4872 // IE runs the same speed using setAttribute, however FF slows way down
4873 // and Safari completely fails so they need to continue to use expandos.
4874 var isIE = window.ActiveXObject ? true : false;
4876 // this eval is stop the compressor from
4877 // renaming the variable to something shorter
4879 /** eval:var:batch */
4884 function nodupIEXml(cs){
4886 cs[0].setAttribute("_nodup", d);
4888 for(var i = 1, len = cs.length; i < len; i++){
4890 if(!c.getAttribute("_nodup") != d){
4891 c.setAttribute("_nodup", d);
4895 for(var i = 0, len = cs.length; i < len; i++){
4896 cs[i].removeAttribute("_nodup");
4905 var len = cs.length, c, i, r = cs, cj, ri = -1;
4906 if(!len || typeof cs.nodeType != "undefined" || len == 1){
4909 if(isIE && typeof cs[0].selectSingleNode != "undefined"){
4910 return nodupIEXml(cs);
4914 for(i = 1; c = cs[i]; i++){
4919 for(var j = 0; j < i; j++){
4922 for(j = i+1; cj = cs[j]; j++){
4934 function quickDiffIEXml(c1, c2){
4936 for(var i = 0, len = c1.length; i < len; i++){
4937 c1[i].setAttribute("_qdiff", d);
4940 for(var i = 0, len = c2.length; i < len; i++){
4941 if(c2[i].getAttribute("_qdiff") != d){
4942 r[r.length] = c2[i];
4945 for(var i = 0, len = c1.length; i < len; i++){
4946 c1[i].removeAttribute("_qdiff");
4951 function quickDiff(c1, c2){
4952 var len1 = c1.length;
4956 if(isIE && c1[0].selectSingleNode){
4957 return quickDiffIEXml(c1, c2);
4960 for(var i = 0; i < len1; i++){
4964 for(var i = 0, len = c2.length; i < len; i++){
4965 if(c2[i]._qdiff != d){
4966 r[r.length] = c2[i];
4972 function quickId(ns, mode, root, id){
4974 var d = root.ownerDocument || root;
4975 return d.getElementById(id);
4977 ns = getNodes(ns, mode, "*");
4978 return byId(ns, null, id);
4982 getStyle : function(el, name){
4983 return Roo.fly(el).getStyle(name);
4986 * Compiles a selector/xpath query into a reusable function. The returned function
4987 * takes one parameter "root" (optional), which is the context node from where the query should start.
4988 * @param {String} selector The selector/xpath query
4989 * @param {String} type (optional) Either "select" (the default) or "simple" for a simple selector match
4990 * @return {Function}
4992 compile : function(path, type){
4993 type = type || "select";
4995 var fn = ["var f = function(root){\n var mode; ++batch; var n = root || document;\n"];
4996 var q = path, mode, lq;
4997 var tk = Roo.DomQuery.matchers;
4998 var tklen = tk.length;
5001 // accept leading mode switch
5002 var lmode = q.match(modeRe);
5003 if(lmode && lmode[1]){
5004 fn[fn.length] = 'mode="'+lmode[1].replace(trimRe, "")+'";';
5005 q = q.replace(lmode[1], "");
5007 // strip leading slashes
5008 while(path.substr(0, 1)=="/"){
5009 path = path.substr(1);
5012 while(q && lq != q){
5014 var tm = q.match(tagTokenRe);
5015 if(type == "select"){
5018 fn[fn.length] = 'n = quickId(n, mode, root, "'+tm[2]+'");';
5020 fn[fn.length] = 'n = getNodes(n, mode, "'+tm[2]+'");';
5022 q = q.replace(tm[0], "");
5023 }else if(q.substr(0, 1) != '@'){
5024 fn[fn.length] = 'n = getNodes(n, mode, "*");';
5029 fn[fn.length] = 'n = byId(n, null, "'+tm[2]+'");';
5031 fn[fn.length] = 'n = byTag(n, "'+tm[2]+'");';
5033 q = q.replace(tm[0], "");
5036 while(!(mm = q.match(modeRe))){
5037 var matched = false;
5038 for(var j = 0; j < tklen; j++){
5040 var m = q.match(t.re);
5042 fn[fn.length] = t.select.replace(tplRe, function(x, i){
5045 q = q.replace(m[0], "");
5050 // prevent infinite loop on bad selector
5052 throw 'Error parsing selector, parsing failed at "' + q + '"';
5056 fn[fn.length] = 'mode="'+mm[1].replace(trimRe, "")+'";';
5057 q = q.replace(mm[1], "");
5060 fn[fn.length] = "return nodup(n);\n}";
5063 * list of variables that need from compression as they are used by eval.
5073 * eval:var:byClassName
5075 * eval:var:byAttribute
5076 * eval:var:attrValue
5084 * Selects a group of elements.
5085 * @param {String} selector The selector/xpath query (can be a comma separated list of selectors)
5086 * @param {Node} root (optional) The start of the query (defaults to document).
5089 select : function(path, root, type){
5090 if(!root || root == document){
5093 if(typeof root == "string"){
5094 root = document.getElementById(root);
5096 var paths = path.split(",");
5098 for(var i = 0, len = paths.length; i < len; i++){
5099 var p = paths[i].replace(trimRe, "");
5101 cache[p] = Roo.DomQuery.compile(p);
5103 throw p + " is not a valid selector";
5106 var result = cache[p](root);
5107 if(result && result != document){
5108 results = results.concat(result);
5111 if(paths.length > 1){
5112 return nodup(results);
5118 * Selects a single element.
5119 * @param {String} selector The selector/xpath query
5120 * @param {Node} root (optional) The start of the query (defaults to document).
5123 selectNode : function(path, root){
5124 return Roo.DomQuery.select(path, root)[0];
5128 * Selects the value of a node, optionally replacing null with the defaultValue.
5129 * @param {String} selector The selector/xpath query
5130 * @param {Node} root (optional) The start of the query (defaults to document).
5131 * @param {String} defaultValue
5133 selectValue : function(path, root, defaultValue){
5134 path = path.replace(trimRe, "");
5135 if(!valueCache[path]){
5136 valueCache[path] = Roo.DomQuery.compile(path, "select");
5138 var n = valueCache[path](root);
5139 n = n[0] ? n[0] : n;
5140 var v = (n && n.firstChild ? n.firstChild.nodeValue : null);
5141 return ((v === null||v === undefined||v==='') ? defaultValue : v);
5145 * Selects the value of a node, parsing integers and floats.
5146 * @param {String} selector The selector/xpath query
5147 * @param {Node} root (optional) The start of the query (defaults to document).
5148 * @param {Number} defaultValue
5151 selectNumber : function(path, root, defaultValue){
5152 var v = Roo.DomQuery.selectValue(path, root, defaultValue || 0);
5153 return parseFloat(v);
5157 * Returns true if the passed element(s) match the passed simple selector (e.g. div.some-class or span:first-child)
5158 * @param {String/HTMLElement/Array} el An element id, element or array of elements
5159 * @param {String} selector The simple selector to test
5162 is : function(el, ss){
5163 if(typeof el == "string"){
5164 el = document.getElementById(el);
5166 var isArray = (el instanceof Array);
5167 var result = Roo.DomQuery.filter(isArray ? el : [el], ss);
5168 return isArray ? (result.length == el.length) : (result.length > 0);
5172 * Filters an array of elements to only include matches of a simple selector (e.g. div.some-class or span:first-child)
5173 * @param {Array} el An array of elements to filter
5174 * @param {String} selector The simple selector to test
5175 * @param {Boolean} nonMatches If true, it returns the elements that DON'T match
5176 * the selector instead of the ones that match
5179 filter : function(els, ss, nonMatches){
5180 ss = ss.replace(trimRe, "");
5181 if(!simpleCache[ss]){
5182 simpleCache[ss] = Roo.DomQuery.compile(ss, "simple");
5184 var result = simpleCache[ss](els);
5185 return nonMatches ? quickDiff(result, els) : result;
5189 * Collection of matching regular expressions and code snippets.
5193 select: 'n = byClassName(n, null, " {1} ");'
5195 re: /^\:([\w-]+)(?:\(((?:[^\s>\/]*|.*?))\))?/,
5196 select: 'n = byPseudo(n, "{1}", "{2}");'
5198 re: /^(?:([\[\{])(?:@)?([\w-]+)\s?(?:(=|.=)\s?['"]?(.*?)["']?)?[\]\}])/,
5199 select: 'n = byAttribute(n, "{2}", "{4}", "{3}", "{1}");'
5202 select: 'n = byId(n, null, "{1}");'
5205 select: 'return {firstChild:{nodeValue:attrValue(n, "{1}")}};'
5210 * Collection of operator comparison functions. The default operators are =, !=, ^=, $=, *=, %=, |= and ~=.
5211 * 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, > <.
5214 "=" : function(a, v){
5217 "!=" : function(a, v){
5220 "^=" : function(a, v){
5221 return a && a.substr(0, v.length) == v;
5223 "$=" : function(a, v){
5224 return a && a.substr(a.length-v.length) == v;
5226 "*=" : function(a, v){
5227 return a && a.indexOf(v) !== -1;
5229 "%=" : function(a, v){
5230 return (a % v) == 0;
5232 "|=" : function(a, v){
5233 return a && (a == v || a.substr(0, v.length+1) == v+'-');
5235 "~=" : function(a, v){
5236 return a && (' '+a+' ').indexOf(' '+v+' ') != -1;
5241 * Collection of "pseudo class" processors. Each processor is passed the current nodeset (array)
5242 * and the argument (if any) supplied in the selector.
5245 "first-child" : function(c){
5246 var r = [], ri = -1, n;
5247 for(var i = 0, ci; ci = n = c[i]; i++){
5248 while((n = n.previousSibling) && n.nodeType != 1);
5256 "last-child" : function(c){
5257 var r = [], ri = -1, n;
5258 for(var i = 0, ci; ci = n = c[i]; i++){
5259 while((n = n.nextSibling) && n.nodeType != 1);
5267 "nth-child" : function(c, a) {
5268 var r = [], ri = -1;
5269 var m = nthRe.exec(a == "even" && "2n" || a == "odd" && "2n+1" || !nthRe2.test(a) && "n+" + a || a);
5270 var f = (m[1] || 1) - 0, l = m[2] - 0;
5271 for(var i = 0, n; n = c[i]; i++){
5272 var pn = n.parentNode;
5273 if (batch != pn._batch) {
5275 for(var cn = pn.firstChild; cn; cn = cn.nextSibling){
5276 if(cn.nodeType == 1){
5283 if (l == 0 || n.nodeIndex == l){
5286 } else if ((n.nodeIndex + l) % f == 0){
5294 "only-child" : function(c){
5295 var r = [], ri = -1;;
5296 for(var i = 0, ci; ci = c[i]; i++){
5297 if(!prev(ci) && !next(ci)){
5304 "empty" : function(c){
5305 var r = [], ri = -1;
5306 for(var i = 0, ci; ci = c[i]; i++){
5307 var cns = ci.childNodes, j = 0, cn, empty = true;
5310 if(cn.nodeType == 1 || cn.nodeType == 3){
5322 "contains" : function(c, v){
5323 var r = [], ri = -1;
5324 for(var i = 0, ci; ci = c[i]; i++){
5325 if((ci.textContent||ci.innerText||'').indexOf(v) != -1){
5332 "nodeValue" : function(c, v){
5333 var r = [], ri = -1;
5334 for(var i = 0, ci; ci = c[i]; i++){
5335 if(ci.firstChild && ci.firstChild.nodeValue == v){
5342 "checked" : function(c){
5343 var r = [], ri = -1;
5344 for(var i = 0, ci; ci = c[i]; i++){
5345 if(ci.checked == true){
5352 "not" : function(c, ss){
5353 return Roo.DomQuery.filter(c, ss, true);
5356 "odd" : function(c){
5357 return this["nth-child"](c, "odd");
5360 "even" : function(c){
5361 return this["nth-child"](c, "even");
5364 "nth" : function(c, a){
5365 return c[a-1] || [];
5368 "first" : function(c){
5372 "last" : function(c){
5373 return c[c.length-1] || [];
5376 "has" : function(c, ss){
5377 var s = Roo.DomQuery.select;
5378 var r = [], ri = -1;
5379 for(var i = 0, ci; ci = c[i]; i++){
5380 if(s(ss, ci).length > 0){
5387 "next" : function(c, ss){
5388 var is = Roo.DomQuery.is;
5389 var r = [], ri = -1;
5390 for(var i = 0, ci; ci = c[i]; i++){
5399 "prev" : function(c, ss){
5400 var is = Roo.DomQuery.is;
5401 var r = [], ri = -1;
5402 for(var i = 0, ci; ci = c[i]; i++){
5415 * Selects an array of DOM nodes by CSS/XPath selector. Shorthand of {@link Roo.DomQuery#select}
5416 * @param {String} path The selector/xpath query
5417 * @param {Node} root (optional) The start of the query (defaults to document).
5422 Roo.query = Roo.DomQuery.select;
5425 * Ext JS Library 1.1.1
5426 * Copyright(c) 2006-2007, Ext JS, LLC.
5428 * Originally Released Under LGPL - original licence link has changed is not relivant.
5431 * <script type="text/javascript">
5435 * @class Roo.util.Observable
5436 * Base class that provides a common interface for publishing events. Subclasses are expected to
5437 * to have a property "events" with all the events defined.<br>
5440 Employee = function(name){
5447 Roo.extend(Employee, Roo.util.Observable);
5449 * @param {Object} config properties to use (incuding events / listeners)
5452 Roo.util.Observable = function(cfg){
5455 this.addEvents(cfg.events || {});
5457 delete cfg.events; // make sure
5460 Roo.apply(this, cfg);
5463 this.on(this.listeners);
5464 delete this.listeners;
5467 Roo.util.Observable.prototype = {
5469 * @cfg {Object} listeners list of events and functions to call for this object,
5473 'click' : function(e) {
5483 * Fires the specified event with the passed parameters (minus the event name).
5484 * @param {String} eventName
5485 * @param {Object...} args Variable number of parameters are passed to handlers
5486 * @return {Boolean} returns false if any of the handlers return false otherwise it returns true
5488 fireEvent : function(){
5489 var ce = this.events[arguments[0].toLowerCase()];
5490 if(typeof ce == "object"){
5491 return ce.fire.apply(ce, Array.prototype.slice.call(arguments, 1));
5498 filterOptRe : /^(?:scope|delay|buffer|single)$/,
5501 * Appends an event handler to this component
5502 * @param {String} eventName The type of event to listen for
5503 * @param {Function} handler The method the event invokes
5504 * @param {Object} scope (optional) The scope in which to execute the handler
5505 * function. The handler function's "this" context.
5506 * @param {Object} options (optional) An object containing handler configuration
5507 * properties. This may contain any of the following properties:<ul>
5508 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
5509 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
5510 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
5511 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
5512 * by the specified number of milliseconds. If the event fires again within that time, the original
5513 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
5516 * <b>Combining Options</b><br>
5517 * Using the options argument, it is possible to combine different types of listeners:<br>
5519 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)
5521 el.on('click', this.onClick, this, {
5528 * <b>Attaching multiple handlers in 1 call</b><br>
5529 * The method also allows for a single argument to be passed which is a config object containing properties
5530 * which specify multiple handlers.
5539 fn: this.onMouseOver,
5543 fn: this.onMouseOut,
5549 * Or a shorthand syntax which passes the same scope object to all handlers:
5552 'click': this.onClick,
5553 'mouseover': this.onMouseOver,
5554 'mouseout': this.onMouseOut,
5559 addListener : function(eventName, fn, scope, o){
5560 if(typeof eventName == "object"){
5563 if(this.filterOptRe.test(e)){
5566 if(typeof o[e] == "function"){
5568 this.addListener(e, o[e], o.scope, o);
5570 // individual options
5571 this.addListener(e, o[e].fn, o[e].scope, o[e]);
5576 o = (!o || typeof o == "boolean") ? {} : o;
5577 eventName = eventName.toLowerCase();
5578 var ce = this.events[eventName] || true;
5579 if(typeof ce == "boolean"){
5580 ce = new Roo.util.Event(this, eventName);
5581 this.events[eventName] = ce;
5583 ce.addListener(fn, scope, o);
5587 * Removes a listener
5588 * @param {String} eventName The type of event to listen for
5589 * @param {Function} handler The handler to remove
5590 * @param {Object} scope (optional) The scope (this object) for the handler
5592 removeListener : function(eventName, fn, scope){
5593 var ce = this.events[eventName.toLowerCase()];
5594 if(typeof ce == "object"){
5595 ce.removeListener(fn, scope);
5600 * Removes all listeners for this object
5602 purgeListeners : function(){
5603 for(var evt in this.events){
5604 if(typeof this.events[evt] == "object"){
5605 this.events[evt].clearListeners();
5610 relayEvents : function(o, events){
5611 var createHandler = function(ename){
5613 return this.fireEvent.apply(this, Roo.combine(ename, Array.prototype.slice.call(arguments, 0)));
5616 for(var i = 0, len = events.length; i < len; i++){
5617 var ename = events[i];
5618 if(!this.events[ename]){ this.events[ename] = true; };
5619 o.on(ename, createHandler(ename), this);
5624 * Used to define events on this Observable
5625 * @param {Object} object The object with the events defined
5627 addEvents : function(o){
5631 Roo.applyIf(this.events, o);
5635 * Checks to see if this object has any listeners for a specified event
5636 * @param {String} eventName The name of the event to check for
5637 * @return {Boolean} True if the event is being listened for, else false
5639 hasListener : function(eventName){
5640 var e = this.events[eventName];
5641 return typeof e == "object" && e.listeners.length > 0;
5645 * Appends an event handler to this element (shorthand for addListener)
5646 * @param {String} eventName The type of event to listen for
5647 * @param {Function} handler The method the event invokes
5648 * @param {Object} scope (optional) The scope in which to execute the handler
5649 * function. The handler function's "this" context.
5650 * @param {Object} options (optional)
5653 Roo.util.Observable.prototype.on = Roo.util.Observable.prototype.addListener;
5655 * Removes a listener (shorthand for removeListener)
5656 * @param {String} eventName The type of event to listen for
5657 * @param {Function} handler The handler to remove
5658 * @param {Object} scope (optional) The scope (this object) for the handler
5661 Roo.util.Observable.prototype.un = Roo.util.Observable.prototype.removeListener;
5664 * Starts capture on the specified Observable. All events will be passed
5665 * to the supplied function with the event name + standard signature of the event
5666 * <b>before</b> the event is fired. If the supplied function returns false,
5667 * the event will not fire.
5668 * @param {Observable} o The Observable to capture
5669 * @param {Function} fn The function to call
5670 * @param {Object} scope (optional) The scope (this object) for the fn
5673 Roo.util.Observable.capture = function(o, fn, scope){
5674 o.fireEvent = o.fireEvent.createInterceptor(fn, scope);
5678 * Removes <b>all</b> added captures from the Observable.
5679 * @param {Observable} o The Observable to release
5682 Roo.util.Observable.releaseCapture = function(o){
5683 o.fireEvent = Roo.util.Observable.prototype.fireEvent;
5688 var createBuffered = function(h, o, scope){
5689 var task = new Roo.util.DelayedTask();
5691 task.delay(o.buffer, h, scope, Array.prototype.slice.call(arguments, 0));
5695 var createSingle = function(h, e, fn, scope){
5697 e.removeListener(fn, scope);
5698 return h.apply(scope, arguments);
5702 var createDelayed = function(h, o, scope){
5704 var args = Array.prototype.slice.call(arguments, 0);
5705 setTimeout(function(){
5706 h.apply(scope, args);
5711 Roo.util.Event = function(obj, name){
5714 this.listeners = [];
5717 Roo.util.Event.prototype = {
5718 addListener : function(fn, scope, options){
5719 var o = options || {};
5720 scope = scope || this.obj;
5721 if(!this.isListening(fn, scope)){
5722 var l = {fn: fn, scope: scope, options: o};
5725 h = createDelayed(h, o, scope);
5728 h = createSingle(h, this, fn, scope);
5731 h = createBuffered(h, o, scope);
5734 if(!this.firing){ // if we are currently firing this event, don't disturb the listener loop
5735 this.listeners.push(l);
5737 this.listeners = this.listeners.slice(0);
5738 this.listeners.push(l);
5743 findListener : function(fn, scope){
5744 scope = scope || this.obj;
5745 var ls = this.listeners;
5746 for(var i = 0, len = ls.length; i < len; i++){
5748 if(l.fn == fn && l.scope == scope){
5755 isListening : function(fn, scope){
5756 return this.findListener(fn, scope) != -1;
5759 removeListener : function(fn, scope){
5761 if((index = this.findListener(fn, scope)) != -1){
5763 this.listeners.splice(index, 1);
5765 this.listeners = this.listeners.slice(0);
5766 this.listeners.splice(index, 1);
5773 clearListeners : function(){
5774 this.listeners = [];
5778 var ls = this.listeners, scope, len = ls.length;
5781 var args = Array.prototype.slice.call(arguments, 0);
5782 for(var i = 0; i < len; i++){
5784 if(l.fireFn.apply(l.scope||this.obj||window, arguments) === false){
5785 this.firing = false;
5789 this.firing = false;
5796 * Ext JS Library 1.1.1
5797 * Copyright(c) 2006-2007, Ext JS, LLC.
5799 * Originally Released Under LGPL - original licence link has changed is not relivant.
5802 * <script type="text/javascript">
5806 * @class Roo.EventManager
5807 * Registers event handlers that want to receive a normalized EventObject instead of the standard browser event and provides
5808 * several useful events directly.
5809 * See {@link Roo.EventObject} for more details on normalized event objects.
5812 Roo.EventManager = function(){
5813 var docReadyEvent, docReadyProcId, docReadyState = false;
5814 var resizeEvent, resizeTask, textEvent, textSize;
5815 var E = Roo.lib.Event;
5816 var D = Roo.lib.Dom;
5819 var fireDocReady = function(){
5821 docReadyState = true;
5824 clearInterval(docReadyProcId);
5826 if(Roo.isGecko || Roo.isOpera) {
5827 document.removeEventListener("DOMContentLoaded", fireDocReady, false);
5830 var defer = document.getElementById("ie-deferred-loader");
5832 defer.onreadystatechange = null;
5833 defer.parentNode.removeChild(defer);
5837 docReadyEvent.fire();
5838 docReadyEvent.clearListeners();
5843 var initDocReady = function(){
5844 docReadyEvent = new Roo.util.Event();
5845 if(Roo.isGecko || Roo.isOpera) {
5846 document.addEventListener("DOMContentLoaded", fireDocReady, false);
5848 document.write("<s"+'cript id="ie-deferred-loader" defer="defer" src="/'+'/:"></s'+"cript>");
5849 var defer = document.getElementById("ie-deferred-loader");
5850 defer.onreadystatechange = function(){
5851 if(this.readyState == "complete"){
5855 }else if(Roo.isSafari){
5856 docReadyProcId = setInterval(function(){
5857 var rs = document.readyState;
5858 if(rs == "complete") {
5863 // no matter what, make sure it fires on load
5864 E.on(window, "load", fireDocReady);
5867 var createBuffered = function(h, o){
5868 var task = new Roo.util.DelayedTask(h);
5870 // create new event object impl so new events don't wipe out properties
5871 e = new Roo.EventObjectImpl(e);
5872 task.delay(o.buffer, h, null, [e]);
5876 var createSingle = function(h, el, ename, fn){
5878 Roo.EventManager.removeListener(el, ename, fn);
5883 var createDelayed = function(h, o){
5885 // create new event object impl so new events don't wipe out properties
5886 e = new Roo.EventObjectImpl(e);
5887 setTimeout(function(){
5893 var listen = function(element, ename, opt, fn, scope){
5894 var o = (!opt || typeof opt == "boolean") ? {} : opt;
5895 fn = fn || o.fn; scope = scope || o.scope;
5896 var el = Roo.getDom(element);
5898 throw "Error listening for \"" + ename + '\". Element "' + element + '" doesn\'t exist.';
5900 var h = function(e){
5901 e = Roo.EventObject.setEvent(e);
5904 t = e.getTarget(o.delegate, el);
5911 if(o.stopEvent === true){
5914 if(o.preventDefault === true){
5917 if(o.stopPropagation === true){
5918 e.stopPropagation();
5921 if(o.normalized === false){
5925 fn.call(scope || el, e, t, o);
5928 h = createDelayed(h, o);
5931 h = createSingle(h, el, ename, fn);
5934 h = createBuffered(h, o);
5936 fn._handlers = fn._handlers || [];
5937 fn._handlers.push([Roo.id(el), ename, h]);
5940 if(ename == "mousewheel" && el.addEventListener){ // workaround for jQuery
5941 el.addEventListener("DOMMouseScroll", h, false);
5942 E.on(window, 'unload', function(){
5943 el.removeEventListener("DOMMouseScroll", h, false);
5946 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5947 Roo.EventManager.stoppedMouseDownEvent.addListener(h);
5952 var stopListening = function(el, ename, fn){
5953 var id = Roo.id(el), hds = fn._handlers, hd = fn;
5955 for(var i = 0, len = hds.length; i < len; i++){
5957 if(h[0] == id && h[1] == ename){
5964 E.un(el, ename, hd);
5965 el = Roo.getDom(el);
5966 if(ename == "mousewheel" && el.addEventListener){
5967 el.removeEventListener("DOMMouseScroll", hd, false);
5969 if(ename == "mousedown" && el == document){ // fix stopped mousedowns on the document
5970 Roo.EventManager.stoppedMouseDownEvent.removeListener(hd);
5974 var propRe = /^(?:scope|delay|buffer|single|stopEvent|preventDefault|stopPropagation|normalized|args|delegate)$/;
5981 * @scope Roo.EventManager
5986 * This is no longer needed and is deprecated. Places a simple wrapper around an event handler to override the browser event
5987 * object with a Roo.EventObject
5988 * @param {Function} fn The method the event invokes
5989 * @param {Object} scope An object that becomes the scope of the handler
5990 * @param {boolean} override If true, the obj passed in becomes
5991 * the execution scope of the listener
5992 * @return {Function} The wrapped function
5995 wrap : function(fn, scope, override){
5997 Roo.EventObject.setEvent(e);
5998 fn.call(override ? scope || window : window, Roo.EventObject, scope);
6003 * Appends an event handler to an element (shorthand for addListener)
6004 * @param {String/HTMLElement} element The html element or id to assign the
6005 * @param {String} eventName The type of event to listen for
6006 * @param {Function} handler The method the event invokes
6007 * @param {Object} scope (optional) The scope in which to execute the handler
6008 * function. The handler function's "this" context.
6009 * @param {Object} options (optional) An object containing handler configuration
6010 * properties. This may contain any of the following properties:<ul>
6011 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6012 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6013 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6014 * <li>preventDefault {Boolean} True to prevent the default action</li>
6015 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6016 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6017 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6018 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6019 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6020 * by the specified number of milliseconds. If the event fires again within that time, the original
6021 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6024 * <b>Combining Options</b><br>
6025 * Using the options argument, it is possible to combine different types of listeners:<br>
6027 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6029 el.on('click', this.onClick, this, {
6036 * <b>Attaching multiple handlers in 1 call</b><br>
6037 * The method also allows for a single argument to be passed which is a config object containing properties
6038 * which specify multiple handlers.
6048 fn: this.onMouseOver
6057 * Or a shorthand syntax:<br>
6060 'click' : this.onClick,
6061 'mouseover' : this.onMouseOver,
6062 'mouseout' : this.onMouseOut
6066 addListener : function(element, eventName, fn, scope, options){
6067 if(typeof eventName == "object"){
6073 if(typeof o[e] == "function"){
6075 listen(element, e, o, o[e], o.scope);
6077 // individual options
6078 listen(element, e, o[e]);
6083 return listen(element, eventName, options, fn, scope);
6087 * Removes an event handler
6089 * @param {String/HTMLElement} element The id or html element to remove the
6091 * @param {String} eventName The type of event
6092 * @param {Function} fn
6093 * @return {Boolean} True if a listener was actually removed
6095 removeListener : function(element, eventName, fn){
6096 return stopListening(element, eventName, fn);
6100 * Fires when the document is ready (before onload and before images are loaded). Can be
6101 * accessed shorthanded Roo.onReady().
6102 * @param {Function} fn The method the event invokes
6103 * @param {Object} scope An object that becomes the scope of the handler
6104 * @param {boolean} options
6106 onDocumentReady : function(fn, scope, options){
6107 if(docReadyState){ // if it already fired
6108 docReadyEvent.addListener(fn, scope, options);
6109 docReadyEvent.fire();
6110 docReadyEvent.clearListeners();
6116 docReadyEvent.addListener(fn, scope, options);
6120 * Fires when the window is resized and provides resize event buffering (50 milliseconds), passes new viewport width and height to handlers.
6121 * @param {Function} fn The method the event invokes
6122 * @param {Object} scope An object that becomes the scope of the handler
6123 * @param {boolean} options
6125 onWindowResize : function(fn, scope, options){
6127 resizeEvent = new Roo.util.Event();
6128 resizeTask = new Roo.util.DelayedTask(function(){
6129 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6131 E.on(window, "resize", function(){
6133 resizeTask.delay(50);
6135 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6139 resizeEvent.addListener(fn, scope, options);
6143 * Fires when the user changes the active text size. Handler gets called with 2 params, the old size and the new size.
6144 * @param {Function} fn The method the event invokes
6145 * @param {Object} scope An object that becomes the scope of the handler
6146 * @param {boolean} options
6148 onTextResize : function(fn, scope, options){
6150 textEvent = new Roo.util.Event();
6151 var textEl = new Roo.Element(document.createElement('div'));
6152 textEl.dom.className = 'x-text-resize';
6153 textEl.dom.innerHTML = 'X';
6154 textEl.appendTo(document.body);
6155 textSize = textEl.dom.offsetHeight;
6156 setInterval(function(){
6157 if(textEl.dom.offsetHeight != textSize){
6158 textEvent.fire(textSize, textSize = textEl.dom.offsetHeight);
6160 }, this.textResizeInterval);
6162 textEvent.addListener(fn, scope, options);
6166 * Removes the passed window resize listener.
6167 * @param {Function} fn The method the event invokes
6168 * @param {Object} scope The scope of handler
6170 removeResizeListener : function(fn, scope){
6172 resizeEvent.removeListener(fn, scope);
6177 fireResize : function(){
6179 resizeEvent.fire(D.getViewWidth(), D.getViewHeight());
6183 * Url used for onDocumentReady with using SSL (defaults to Roo.SSL_SECURE_URL)
6187 * The frequency, in milliseconds, to check for text resize events (defaults to 50)
6189 textResizeInterval : 50
6194 * @scopeAlias pub=Roo.EventManager
6198 * Appends an event handler to an element (shorthand for addListener)
6199 * @param {String/HTMLElement} element The html element or id to assign the
6200 * @param {String} eventName The type of event to listen for
6201 * @param {Function} handler The method the event invokes
6202 * @param {Object} scope (optional) The scope in which to execute the handler
6203 * function. The handler function's "this" context.
6204 * @param {Object} options (optional) An object containing handler configuration
6205 * properties. This may contain any of the following properties:<ul>
6206 * <li>scope {Object} The scope in which to execute the handler function. The handler function's "this" context.</li>
6207 * <li>delegate {String} A simple selector to filter the target or look for a descendant of the target</li>
6208 * <li>stopEvent {Boolean} True to stop the event. That is stop propagation, and prevent the default action.</li>
6209 * <li>preventDefault {Boolean} True to prevent the default action</li>
6210 * <li>stopPropagation {Boolean} True to prevent event propagation</li>
6211 * <li>normalized {Boolean} False to pass a browser event to the handler function instead of an Roo.EventObject</li>
6212 * <li>delay {Number} The number of milliseconds to delay the invocation of the handler after te event fires.</li>
6213 * <li>single {Boolean} True to add a handler to handle just the next firing of the event, and then remove itself.</li>
6214 * <li>buffer {Number} Causes the handler to be scheduled to run in an {@link Roo.util.DelayedTask} delayed
6215 * by the specified number of milliseconds. If the event fires again within that time, the original
6216 * handler is <em>not</em> invoked, but the new handler is scheduled in its place.</li>
6219 * <b>Combining Options</b><br>
6220 * Using the options argument, it is possible to combine different types of listeners:<br>
6222 * A normalized, delayed, one-time listener that auto stops the event and passes a custom argument (forumId)<div style="margin: 5px 20px 20px;">
6224 el.on('click', this.onClick, this, {
6231 * <b>Attaching multiple handlers in 1 call</b><br>
6232 * The method also allows for a single argument to be passed which is a config object containing properties
6233 * which specify multiple handlers.
6243 fn: this.onMouseOver
6252 * Or a shorthand syntax:<br>
6255 'click' : this.onClick,
6256 'mouseover' : this.onMouseOver,
6257 'mouseout' : this.onMouseOut
6261 pub.on = pub.addListener;
6262 pub.un = pub.removeListener;
6264 pub.stoppedMouseDownEvent = new Roo.util.Event();
6268 * Fires when the document is ready (before onload and before images are loaded). Shorthand of {@link Roo.EventManager#onDocumentReady}.
6269 * @param {Function} fn The method the event invokes
6270 * @param {Object} scope An object that becomes the scope of the handler
6271 * @param {boolean} override If true, the obj passed in becomes
6272 * the execution scope of the listener
6276 Roo.onReady = Roo.EventManager.onDocumentReady;
6278 Roo.onReady(function(){
6279 var bd = Roo.get(document.body);
6284 : Roo.isGecko ? "roo-gecko"
6285 : Roo.isOpera ? "roo-opera"
6286 : Roo.isSafari ? "roo-safari" : ""];
6289 cls.push("roo-mac");
6292 cls.push("roo-linux");
6294 if(Roo.isBorderBox){
6295 cls.push('roo-border-box');
6297 if(Roo.isStrict){ // add to the parent to allow for selectors like ".ext-strict .ext-ie"
6298 var p = bd.dom.parentNode;
6300 p.className += ' roo-strict';
6303 bd.addClass(cls.join(' '));
6307 * @class Roo.EventObject
6308 * EventObject exposes the Yahoo! UI Event functionality directly on the object
6309 * passed to your event handler. It exists mostly for convenience. It also fixes the annoying null checks automatically to cleanup your code
6312 function handleClick(e){ // e is not a standard event object, it is a Roo.EventObject
6314 var target = e.getTarget();
6317 var myDiv = Roo.get("myDiv");
6318 myDiv.on("click", handleClick);
6320 Roo.EventManager.on("myDiv", 'click', handleClick);
6321 Roo.EventManager.addListener("myDiv", 'click', handleClick);
6325 Roo.EventObject = function(){
6327 var E = Roo.lib.Event;
6329 // safari keypress events for special keys return bad keycodes
6332 63235 : 39, // right
6335 63276 : 33, // page up
6336 63277 : 34, // page down
6337 63272 : 46, // delete
6342 // normalize button clicks
6343 var btnMap = Roo.isIE ? {1:0,4:1,2:2} :
6344 (Roo.isSafari ? {1:0,2:1,3:2} : {0:0,1:1,2:2});
6346 Roo.EventObjectImpl = function(e){
6348 this.setEvent(e.browserEvent || e);
6351 Roo.EventObjectImpl.prototype = {
6353 * Used to fix doc tools.
6354 * @scope Roo.EventObject.prototype
6360 /** The normal browser event */
6361 browserEvent : null,
6362 /** The button pressed in a mouse event */
6364 /** True if the shift key was down during the event */
6366 /** True if the control key was down during the event */
6368 /** True if the alt key was down during the event */
6427 setEvent : function(e){
6428 if(e == this || (e && e.browserEvent)){ // already wrapped
6431 this.browserEvent = e;
6433 // normalize buttons
6434 this.button = e.button ? btnMap[e.button] : (e.which ? e.which-1 : -1);
6435 if(e.type == 'click' && this.button == -1){
6439 this.shiftKey = e.shiftKey;
6440 // mac metaKey behaves like ctrlKey
6441 this.ctrlKey = e.ctrlKey || e.metaKey;
6442 this.altKey = e.altKey;
6443 // in getKey these will be normalized for the mac
6444 this.keyCode = e.keyCode;
6445 // keyup warnings on firefox.
6446 this.charCode = (e.type == 'keyup' || e.type == 'keydown') ? 0 : e.charCode;
6447 // cache the target for the delayed and or buffered events
6448 this.target = E.getTarget(e);
6450 this.xy = E.getXY(e);
6453 this.shiftKey = false;
6454 this.ctrlKey = false;
6455 this.altKey = false;
6465 * Stop the event (preventDefault and stopPropagation)
6467 stopEvent : function(){
6468 if(this.browserEvent){
6469 if(this.browserEvent.type == 'mousedown'){
6470 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6472 E.stopEvent(this.browserEvent);
6477 * Prevents the browsers default handling of the event.
6479 preventDefault : function(){
6480 if(this.browserEvent){
6481 E.preventDefault(this.browserEvent);
6486 isNavKeyPress : function(){
6487 var k = this.keyCode;
6488 k = Roo.isSafari ? (safariKeys[k] || k) : k;
6489 return (k >= 33 && k <= 40) || k == this.RETURN || k == this.TAB || k == this.ESC;
6492 isSpecialKey : function(){
6493 var k = this.keyCode;
6494 return (this.type == 'keypress' && this.ctrlKey) || k == 9 || k == 13 || k == 40 || k == 27 ||
6495 (k == 16) || (k == 17) ||
6496 (k >= 18 && k <= 20) ||
6497 (k >= 33 && k <= 35) ||
6498 (k >= 36 && k <= 39) ||
6499 (k >= 44 && k <= 45);
6502 * Cancels bubbling of the event.
6504 stopPropagation : function(){
6505 if(this.browserEvent){
6506 if(this.type == 'mousedown'){
6507 Roo.EventManager.stoppedMouseDownEvent.fire(this);
6509 E.stopPropagation(this.browserEvent);
6514 * Gets the key code for the event.
6517 getCharCode : function(){
6518 return this.charCode || this.keyCode;
6522 * Returns a normalized keyCode for the event.
6523 * @return {Number} The key code
6525 getKey : function(){
6526 var k = this.keyCode || this.charCode;
6527 return Roo.isSafari ? (safariKeys[k] || k) : k;
6531 * Gets the x coordinate of the event.
6534 getPageX : function(){
6539 * Gets the y coordinate of the event.
6542 getPageY : function(){
6547 * Gets the time of the event.
6550 getTime : function(){
6551 if(this.browserEvent){
6552 return E.getTime(this.browserEvent);
6558 * Gets the page coordinates of the event.
6559 * @return {Array} The xy values like [x, y]
6566 * Gets the target for the event.
6567 * @param {String} selector (optional) A simple selector to filter the target or look for an ancestor of the target
6568 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6569 search as a number or element (defaults to 10 || document.body)
6570 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6571 * @return {HTMLelement}
6573 getTarget : function(selector, maxDepth, returnEl){
6574 return selector ? Roo.fly(this.target).findParent(selector, maxDepth, returnEl) : this.target;
6577 * Gets the related target.
6578 * @return {HTMLElement}
6580 getRelatedTarget : function(){
6581 if(this.browserEvent){
6582 return E.getRelatedTarget(this.browserEvent);
6588 * Normalizes mouse wheel delta across browsers
6589 * @return {Number} The delta
6591 getWheelDelta : function(){
6592 var e = this.browserEvent;
6594 if(e.wheelDelta){ /* IE/Opera. */
6595 delta = e.wheelDelta/120;
6596 }else if(e.detail){ /* Mozilla case. */
6597 delta = -e.detail/3;
6603 * Returns true if the control, meta, shift or alt key was pressed during this event.
6606 hasModifier : function(){
6607 return !!((this.ctrlKey || this.altKey) || this.shiftKey);
6611 * Returns true if the target of this event equals el or is a child of el
6612 * @param {String/HTMLElement/Element} el
6613 * @param {Boolean} related (optional) true to test if the related target is within el instead of the target
6616 within : function(el, related){
6617 var t = this[related ? "getRelatedTarget" : "getTarget"]();
6618 return t && Roo.fly(el).contains(t);
6621 getPoint : function(){
6622 return new Roo.lib.Point(this.xy[0], this.xy[1]);
6626 return new Roo.EventObjectImpl();
6631 * Ext JS Library 1.1.1
6632 * Copyright(c) 2006-2007, Ext JS, LLC.
6634 * Originally Released Under LGPL - original licence link has changed is not relivant.
6637 * <script type="text/javascript">
6641 // was in Composite Element!??!?!
6644 var D = Roo.lib.Dom;
6645 var E = Roo.lib.Event;
6646 var A = Roo.lib.Anim;
6648 // local style camelizing for speed
6650 var camelRe = /(-[a-z])/gi;
6651 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
6652 var view = document.defaultView;
6655 * @class Roo.Element
6656 * Represents an Element in the DOM.<br><br>
6659 var el = Roo.get("my-div");
6662 var el = getEl("my-div");
6664 // or with a DOM element
6665 var el = Roo.get(myDivElement);
6667 * Using Roo.get() or getEl() instead of calling the constructor directly ensures you get the same object
6668 * each call instead of constructing a new one.<br><br>
6669 * <b>Animations</b><br />
6670 * Many of the functions for manipulating an element have an optional "animate" parameter. The animate parameter
6671 * should either be a boolean (true) or an object literal with animation options. The animation options are:
6673 Option Default Description
6674 --------- -------- ---------------------------------------------
6675 duration .35 The duration of the animation in seconds
6676 easing easeOut The YUI easing method
6677 callback none A function to execute when the anim completes
6678 scope this The scope (this) of the callback function
6680 * Also, the Anim object being used for the animation will be set on your options object as "anim", which allows you to stop or
6681 * manipulate the animation. Here's an example:
6683 var el = Roo.get("my-div");
6688 // default animation
6689 el.setWidth(100, true);
6691 // animation with some options set
6698 // using the "anim" property to get the Anim object
6704 el.setWidth(100, opt);
6706 if(opt.anim.isAnimated()){
6710 * <b> Composite (Collections of) Elements</b><br />
6711 * For working with collections of Elements, see <a href="Roo.CompositeElement.html">Roo.CompositeElement</a>
6712 * @constructor Create a new Element directly.
6713 * @param {String/HTMLElement} element
6714 * @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).
6716 Roo.Element = function(element, forceNew){
6717 var dom = typeof element == "string" ?
6718 document.getElementById(element) : element;
6719 if(!dom){ // invalid id/element
6723 if(forceNew !== true && id && Roo.Element.cache[id]){ // element object already exists
6724 return Roo.Element.cache[id];
6734 * The DOM element ID
6737 this.id = id || Roo.id(dom);
6740 var El = Roo.Element;
6744 * The element's default display mode (defaults to "")
6747 originalDisplay : "",
6751 * The default unit to append to CSS values where a unit isn't provided (defaults to px).
6756 * Sets the element's visibility mode. When setVisible() is called it
6757 * will use this to determine whether to set the visibility or the display property.
6758 * @param visMode Element.VISIBILITY or Element.DISPLAY
6759 * @return {Roo.Element} this
6761 setVisibilityMode : function(visMode){
6762 this.visibilityMode = visMode;
6766 * Convenience method for setVisibilityMode(Element.DISPLAY)
6767 * @param {String} display (optional) What to set display to when visible
6768 * @return {Roo.Element} this
6770 enableDisplayMode : function(display){
6771 this.setVisibilityMode(El.DISPLAY);
6772 if(typeof display != "undefined") this.originalDisplay = display;
6777 * 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)
6778 * @param {String} selector The simple selector to test
6779 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6780 search as a number or element (defaults to 10 || document.body)
6781 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6782 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6784 findParent : function(simpleSelector, maxDepth, returnEl){
6785 var p = this.dom, b = document.body, depth = 0, dq = Roo.DomQuery, stopEl;
6786 maxDepth = maxDepth || 50;
6787 if(typeof maxDepth != "number"){
6788 stopEl = Roo.getDom(maxDepth);
6791 while(p && p.nodeType == 1 && depth < maxDepth && p != b && p != stopEl){
6792 if(dq.is(p, simpleSelector)){
6793 return returnEl ? Roo.get(p) : p;
6803 * Looks at parent nodes for a match of the passed simple selector (e.g. div.some-class or span:first-child)
6804 * @param {String} selector The simple selector to test
6805 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6806 search as a number or element (defaults to 10 || document.body)
6807 * @param {Boolean} returnEl (optional) True to return a Roo.Element object instead of DOM node
6808 * @return {HTMLElement} The matching DOM node (or null if no match was found)
6810 findParentNode : function(simpleSelector, maxDepth, returnEl){
6811 var p = Roo.fly(this.dom.parentNode, '_internal');
6812 return p ? p.findParent(simpleSelector, maxDepth, returnEl) : null;
6816 * Walks up the dom looking for a parent node that matches the passed simple selector (e.g. div.some-class or span:first-child).
6817 * This is a shortcut for findParentNode() that always returns an Roo.Element.
6818 * @param {String} selector The simple selector to test
6819 * @param {Number/String/HTMLElement/Element} maxDepth (optional) The max depth to
6820 search as a number or element (defaults to 10 || document.body)
6821 * @return {Roo.Element} The matching DOM node (or null if no match was found)
6823 up : function(simpleSelector, maxDepth){
6824 return this.findParentNode(simpleSelector, maxDepth, true);
6830 * Returns true if this element matches the passed simple selector (e.g. div.some-class or span:first-child)
6831 * @param {String} selector The simple selector to test
6832 * @return {Boolean} True if this element matches the selector, else false
6834 is : function(simpleSelector){
6835 return Roo.DomQuery.is(this.dom, simpleSelector);
6839 * Perform animation on this element.
6840 * @param {Object} args The YUI animation control args
6841 * @param {Float} duration (optional) How long the animation lasts in seconds (defaults to .35)
6842 * @param {Function} onComplete (optional) Function to call when animation completes
6843 * @param {String} easing (optional) Easing method to use (defaults to 'easeOut')
6844 * @param {String} animType (optional) 'run' is the default. Can also be 'color', 'motion', or 'scroll'
6845 * @return {Roo.Element} this
6847 animate : function(args, duration, onComplete, easing, animType){
6848 this.anim(args, {duration: duration, callback: onComplete, easing: easing}, animType);
6853 * @private Internal animation call
6855 anim : function(args, opt, animType, defaultDur, defaultEase, cb){
6856 animType = animType || 'run';
6858 var anim = Roo.lib.Anim[animType](
6860 (opt.duration || defaultDur) || .35,
6861 (opt.easing || defaultEase) || 'easeOut',
6863 Roo.callback(cb, this);
6864 Roo.callback(opt.callback, opt.scope || this, [this, opt]);
6872 // private legacy anim prep
6873 preanim : function(a, i){
6874 return !a[i] ? false : (typeof a[i] == "object" ? a[i]: {duration: a[i+1], callback: a[i+2], easing: a[i+3]});
6878 * Removes worthless text nodes
6879 * @param {Boolean} forceReclean (optional) By default the element
6880 * keeps track if it has been cleaned already so
6881 * you can call this over and over. However, if you update the element and
6882 * need to force a reclean, you can pass true.
6884 clean : function(forceReclean){
6885 if(this.isCleaned && forceReclean !== true){
6889 var d = this.dom, n = d.firstChild, ni = -1;
6891 var nx = n.nextSibling;
6892 if(n.nodeType == 3 && !ns.test(n.nodeValue)){
6899 this.isCleaned = true;
6904 calcOffsetsTo : function(el){
6907 var restorePos = false;
6908 if(el.getStyle('position') == 'static'){
6909 el.position('relative');
6914 while(op && op != d && op.tagName != 'HTML'){
6917 op = op.offsetParent;
6920 el.position('static');
6926 * Scrolls this element into view within the passed container.
6927 * @param {String/HTMLElement/Element} container (optional) The container element to scroll (defaults to document.body)
6928 * @param {Boolean} hscroll (optional) False to disable horizontal scroll (defaults to true)
6929 * @return {Roo.Element} this
6931 scrollIntoView : function(container, hscroll){
6932 var c = Roo.getDom(container) || document.body;
6935 var o = this.calcOffsetsTo(c),
6938 b = t+el.offsetHeight,
6939 r = l+el.offsetWidth;
6941 var ch = c.clientHeight;
6942 var ct = parseInt(c.scrollTop, 10);
6943 var cl = parseInt(c.scrollLeft, 10);
6945 var cr = cl + c.clientWidth;
6953 if(hscroll !== false){
6957 c.scrollLeft = r-c.clientWidth;
6964 scrollChildIntoView : function(child, hscroll){
6965 Roo.fly(child, '_scrollChildIntoView').scrollIntoView(this, hscroll);
6969 * Measures the element's content height and updates height to match. Note: this function uses setTimeout so
6970 * the new height may not be available immediately.
6971 * @param {Boolean} animate (optional) Animate the transition (defaults to false)
6972 * @param {Float} duration (optional) Length of the animation in seconds (defaults to .35)
6973 * @param {Function} onComplete (optional) Function to call when animation completes
6974 * @param {String} easing (optional) Easing method to use (defaults to easeOut)
6975 * @return {Roo.Element} this
6977 autoHeight : function(animate, duration, onComplete, easing){
6978 var oldHeight = this.getHeight();
6980 this.setHeight(1); // force clipping
6981 setTimeout(function(){
6982 var height = parseInt(this.dom.scrollHeight, 10); // parseInt for Safari
6984 this.setHeight(height);
6986 if(typeof onComplete == "function"){
6990 this.setHeight(oldHeight); // restore original height
6991 this.setHeight(height, animate, duration, function(){
6993 if(typeof onComplete == "function") onComplete();
6994 }.createDelegate(this), easing);
6996 }.createDelegate(this), 0);
7001 * Returns true if this element is an ancestor of the passed element
7002 * @param {HTMLElement/String} el The element to check
7003 * @return {Boolean} True if this element is an ancestor of el, else false
7005 contains : function(el){
7006 if(!el){return false;}
7007 return D.isAncestor(this.dom, el.dom ? el.dom : el);
7011 * Checks whether the element is currently visible using both visibility and display properties.
7012 * @param {Boolean} deep (optional) True to walk the dom and see if parent elements are hidden (defaults to false)
7013 * @return {Boolean} True if the element is currently visible, else false
7015 isVisible : function(deep) {
7016 var vis = !(this.getStyle("visibility") == "hidden" || this.getStyle("display") == "none");
7017 if(deep !== true || !vis){
7020 var p = this.dom.parentNode;
7021 while(p && p.tagName.toLowerCase() != "body"){
7022 if(!Roo.fly(p, '_isVisible').isVisible()){
7031 * Creates a {@link Roo.CompositeElement} for child nodes based on the passed CSS selector (the selector should not contain an id).
7032 * @param {String} selector The CSS selector
7033 * @param {Boolean} unique (optional) True to create a unique Roo.Element for each child (defaults to false, which creates a single shared flyweight object)
7034 * @return {CompositeElement/CompositeElementLite} The composite element
7036 select : function(selector, unique){
7037 return El.select(selector, unique, this.dom);
7041 * Selects child nodes based on the passed CSS selector (the selector should not contain an id).
7042 * @param {String} selector The CSS selector
7043 * @return {Array} An array of the matched nodes
7045 query : function(selector, unique){
7046 return Roo.DomQuery.select(selector, this.dom);
7050 * Selects a single child at any depth below this element based on the passed CSS selector (the selector should not contain an id).
7051 * @param {String} selector The CSS selector
7052 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7053 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7055 child : function(selector, returnDom){
7056 var n = Roo.DomQuery.selectNode(selector, this.dom);
7057 return returnDom ? n : Roo.get(n);
7061 * Selects a single *direct* child based on the passed CSS selector (the selector should not contain an id).
7062 * @param {String} selector The CSS selector
7063 * @param {Boolean} returnDom (optional) True to return the DOM node instead of Roo.Element (defaults to false)
7064 * @return {HTMLElement/Roo.Element} The child Roo.Element (or DOM node if returnDom = true)
7066 down : function(selector, returnDom){
7067 var n = Roo.DomQuery.selectNode(" > " + selector, this.dom);
7068 return returnDom ? n : Roo.get(n);
7072 * Initializes a {@link Roo.dd.DD} drag drop object for this element.
7073 * @param {String} group The group the DD object is member of
7074 * @param {Object} config The DD config object
7075 * @param {Object} overrides An object containing methods to override/implement on the DD object
7076 * @return {Roo.dd.DD} The DD object
7078 initDD : function(group, config, overrides){
7079 var dd = new Roo.dd.DD(Roo.id(this.dom), group, config);
7080 return Roo.apply(dd, overrides);
7084 * Initializes a {@link Roo.dd.DDProxy} object for this element.
7085 * @param {String} group The group the DDProxy object is member of
7086 * @param {Object} config The DDProxy config object
7087 * @param {Object} overrides An object containing methods to override/implement on the DDProxy object
7088 * @return {Roo.dd.DDProxy} The DDProxy object
7090 initDDProxy : function(group, config, overrides){
7091 var dd = new Roo.dd.DDProxy(Roo.id(this.dom), group, config);
7092 return Roo.apply(dd, overrides);
7096 * Initializes a {@link Roo.dd.DDTarget} object for this element.
7097 * @param {String} group The group the DDTarget object is member of
7098 * @param {Object} config The DDTarget config object
7099 * @param {Object} overrides An object containing methods to override/implement on the DDTarget object
7100 * @return {Roo.dd.DDTarget} The DDTarget object
7102 initDDTarget : function(group, config, overrides){
7103 var dd = new Roo.dd.DDTarget(Roo.id(this.dom), group, config);
7104 return Roo.apply(dd, overrides);
7108 * Sets the visibility of the element (see details). If the visibilityMode is set to Element.DISPLAY, it will use
7109 * the display property to hide the element, otherwise it uses visibility. The default is to hide and show using the visibility property.
7110 * @param {Boolean} visible Whether the element is visible
7111 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7112 * @return {Roo.Element} this
7114 setVisible : function(visible, animate){
7116 if(this.visibilityMode == El.DISPLAY){
7117 this.setDisplayed(visible);
7120 this.dom.style.visibility = visible ? "visible" : "hidden";
7123 // closure for composites
7125 var visMode = this.visibilityMode;
7127 this.setOpacity(.01);
7128 this.setVisible(true);
7130 this.anim({opacity: { to: (visible?1:0) }},
7131 this.preanim(arguments, 1),
7132 null, .35, 'easeIn', function(){
7134 if(visMode == El.DISPLAY){
7135 dom.style.display = "none";
7137 dom.style.visibility = "hidden";
7139 Roo.get(dom).setOpacity(1);
7147 * Returns true if display is not "none"
7150 isDisplayed : function() {
7151 return this.getStyle("display") != "none";
7155 * Toggles the element's visibility or display, depending on visibility mode.
7156 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7157 * @return {Roo.Element} this
7159 toggle : function(animate){
7160 this.setVisible(!this.isVisible(), this.preanim(arguments, 0));
7165 * Sets the CSS display property. Uses originalDisplay if the specified value is a boolean true.
7166 * @param {Boolean} value Boolean value to display the element using its default display, or a string to set the display directly
7167 * @return {Roo.Element} this
7169 setDisplayed : function(value) {
7170 if(typeof value == "boolean"){
7171 value = value ? this.originalDisplay : "none";
7173 this.setStyle("display", value);
7178 * Tries to focus the element. Any exceptions are caught and ignored.
7179 * @return {Roo.Element} this
7181 focus : function() {
7189 * Tries to blur the element. Any exceptions are caught and ignored.
7190 * @return {Roo.Element} this
7200 * Adds one or more CSS classes to the element. Duplicate classes are automatically filtered out.
7201 * @param {String/Array} className The CSS class to add, or an array of classes
7202 * @return {Roo.Element} this
7204 addClass : function(className){
7205 if(className instanceof Array){
7206 for(var i = 0, len = className.length; i < len; i++) {
7207 this.addClass(className[i]);
7210 if(className && !this.hasClass(className)){
7211 this.dom.className = this.dom.className + " " + className;
7218 * Adds one or more CSS classes to this element and removes the same class(es) from all siblings.
7219 * @param {String/Array} className The CSS class to add, or an array of classes
7220 * @return {Roo.Element} this
7222 radioClass : function(className){
7223 var siblings = this.dom.parentNode.childNodes;
7224 for(var i = 0; i < siblings.length; i++) {
7225 var s = siblings[i];
7226 if(s.nodeType == 1){
7227 Roo.get(s).removeClass(className);
7230 this.addClass(className);
7235 * Removes one or more CSS classes from the element.
7236 * @param {String/Array} className The CSS class to remove, or an array of classes
7237 * @return {Roo.Element} this
7239 removeClass : function(className){
7240 if(!className || !this.dom.className){
7243 if(className instanceof Array){
7244 for(var i = 0, len = className.length; i < len; i++) {
7245 this.removeClass(className[i]);
7248 if(this.hasClass(className)){
7249 var re = this.classReCache[className];
7251 re = new RegExp('(?:^|\\s+)' + className + '(?:\\s+|$)', "g");
7252 this.classReCache[className] = re;
7254 this.dom.className =
7255 this.dom.className.replace(re, " ");
7265 * Toggles the specified CSS class on this element (removes it if it already exists, otherwise adds it).
7266 * @param {String} className The CSS class to toggle
7267 * @return {Roo.Element} this
7269 toggleClass : function(className){
7270 if(this.hasClass(className)){
7271 this.removeClass(className);
7273 this.addClass(className);
7279 * Checks if the specified CSS class exists on this element's DOM node.
7280 * @param {String} className The CSS class to check for
7281 * @return {Boolean} True if the class exists, else false
7283 hasClass : function(className){
7284 return className && (' '+this.dom.className+' ').indexOf(' '+className+' ') != -1;
7288 * Replaces a CSS class on the element with another. If the old name does not exist, the new name will simply be added.
7289 * @param {String} oldClassName The CSS class to replace
7290 * @param {String} newClassName The replacement CSS class
7291 * @return {Roo.Element} this
7293 replaceClass : function(oldClassName, newClassName){
7294 this.removeClass(oldClassName);
7295 this.addClass(newClassName);
7300 * Returns an object with properties matching the styles requested.
7301 * For example, el.getStyles('color', 'font-size', 'width') might return
7302 * {'color': '#FFFFFF', 'font-size': '13px', 'width': '100px'}.
7303 * @param {String} style1 A style name
7304 * @param {String} style2 A style name
7305 * @param {String} etc.
7306 * @return {Object} The style object
7308 getStyles : function(){
7309 var a = arguments, len = a.length, r = {};
7310 for(var i = 0; i < len; i++){
7311 r[a[i]] = this.getStyle(a[i]);
7317 * Normalizes currentStyle and computedStyle. This is not YUI getStyle, it is an optimised version.
7318 * @param {String} property The style property whose value is returned.
7319 * @return {String} The current value of the style property for this element.
7321 getStyle : function(){
7322 return view && view.getComputedStyle ?
7324 var el = this.dom, v, cs, camel;
7325 if(prop == 'float'){
7328 if(el.style && (v = el.style[prop])){
7331 if(cs = view.getComputedStyle(el, "")){
7332 if(!(camel = propCache[prop])){
7333 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7340 var el = this.dom, v, cs, camel;
7341 if(prop == 'opacity'){
7342 if(typeof el.style.filter == 'string'){
7343 var m = el.style.filter.match(/alpha\(opacity=(.*)\)/i);
7345 var fv = parseFloat(m[1]);
7347 return fv ? fv / 100 : 0;
7352 }else if(prop == 'float'){
7353 prop = "styleFloat";
7355 if(!(camel = propCache[prop])){
7356 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7358 if(v = el.style[camel]){
7361 if(cs = el.currentStyle){
7369 * Wrapper for setting style properties, also takes single object parameter of multiple styles.
7370 * @param {String/Object} property The style property to be set, or an object of multiple styles.
7371 * @param {String} value (optional) The value to apply to the given property, or null if an object was passed.
7372 * @return {Roo.Element} this
7374 setStyle : function(prop, value){
7375 if(typeof prop == "string"){
7377 if(!(camel = propCache[prop])){
7378 camel = propCache[prop] = prop.replace(camelRe, camelFn);
7380 if(camel == 'opacity') {
7381 this.setOpacity(value);
7383 this.dom.style[camel] = value;
7386 for(var style in prop){
7387 if(typeof prop[style] != "function"){
7388 this.setStyle(style, prop[style]);
7396 * More flexible version of {@link #setStyle} for setting style properties.
7397 * @param {String/Object/Function} styles A style specification string, e.g. "width:100px", or object in the form {width:"100px"}, or
7398 * a function which returns such a specification.
7399 * @return {Roo.Element} this
7401 applyStyles : function(style){
7402 Roo.DomHelper.applyStyles(this.dom, style);
7407 * 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).
7408 * @return {Number} The X position of the element
7411 return D.getX(this.dom);
7415 * 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).
7416 * @return {Number} The Y position of the element
7419 return D.getY(this.dom);
7423 * 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).
7424 * @return {Array} The XY position of the element
7427 return D.getXY(this.dom);
7431 * 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).
7432 * @param {Number} The X position of the element
7433 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7434 * @return {Roo.Element} this
7436 setX : function(x, animate){
7438 D.setX(this.dom, x);
7440 this.setXY([x, this.getY()], this.preanim(arguments, 1));
7446 * 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).
7447 * @param {Number} The Y position of the element
7448 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7449 * @return {Roo.Element} this
7451 setY : function(y, animate){
7453 D.setY(this.dom, y);
7455 this.setXY([this.getX(), y], this.preanim(arguments, 1));
7461 * Sets the element's left position directly using CSS style (instead of {@link #setX}).
7462 * @param {String} left The left CSS property value
7463 * @return {Roo.Element} this
7465 setLeft : function(left){
7466 this.setStyle("left", this.addUnits(left));
7471 * Sets the element's top position directly using CSS style (instead of {@link #setY}).
7472 * @param {String} top The top CSS property value
7473 * @return {Roo.Element} this
7475 setTop : function(top){
7476 this.setStyle("top", this.addUnits(top));
7481 * Sets the element's CSS right style.
7482 * @param {String} right The right CSS property value
7483 * @return {Roo.Element} this
7485 setRight : function(right){
7486 this.setStyle("right", this.addUnits(right));
7491 * Sets the element's CSS bottom style.
7492 * @param {String} bottom The bottom CSS property value
7493 * @return {Roo.Element} this
7495 setBottom : function(bottom){
7496 this.setStyle("bottom", this.addUnits(bottom));
7501 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7502 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7503 * @param {Array} pos Contains X & Y [x, y] values for new position (coordinates are page-based)
7504 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7505 * @return {Roo.Element} this
7507 setXY : function(pos, animate){
7509 D.setXY(this.dom, pos);
7511 this.anim({points: {to: pos}}, this.preanim(arguments, 1), 'motion');
7517 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7518 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7519 * @param {Number} x X value for new position (coordinates are page-based)
7520 * @param {Number} y Y value for new position (coordinates are page-based)
7521 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7522 * @return {Roo.Element} this
7524 setLocation : function(x, y, animate){
7525 this.setXY([x, y], this.preanim(arguments, 2));
7530 * Sets the position of the element in page coordinates, regardless of how the element is positioned.
7531 * The element must be part of the DOM tree to have page coordinates (display:none or elements not appended return false).
7532 * @param {Number} x X value for new position (coordinates are page-based)
7533 * @param {Number} y Y value for new position (coordinates are page-based)
7534 * @param {Boolean/Object} animate (optional) True for the default animation, or a standard Element animation config object
7535 * @return {Roo.Element} this
7537 moveTo : function(x, y, animate){
7538 this.setXY([x, y], this.preanim(arguments, 2));
7543 * Returns the region of the given element.
7544 * The element must be part of the DOM tree to have a region (display:none or elements not appended return false).
7545 * @return {Region} A Roo.lib.Region containing "top, left, bottom, right" member data.
7547 getRegion : function(){
7548 return D.getRegion(this.dom);
7552 * Returns the offset height of the element
7553 * @param {Boolean} contentHeight (optional) true to get the height minus borders and padding
7554 * @return {Number} The element's height
7556 getHeight : function(contentHeight){
7557 var h = this.dom.offsetHeight || 0;
7558 return contentHeight !== true ? h : h-this.getBorderWidth("tb")-this.getPadding("tb");
7562 * Returns the offset width of the element
7563 * @param {Boolean} contentWidth (optional) true to get the width minus borders and padding
7564 * @return {Number} The element's width
7566 getWidth : function(contentWidth){
7567 var w = this.dom.offsetWidth || 0;
7568 return contentWidth !== true ? w : w-this.getBorderWidth("lr")-this.getPadding("lr");
7572 * Returns either the offsetHeight or the height of this element based on CSS height adjusted by padding or borders
7573 * when needed to simulate offsetHeight when offsets aren't available. This may not work on display:none elements
7574 * if a height has not been set using CSS.
7577 getComputedHeight : function(){
7578 var h = Math.max(this.dom.offsetHeight, this.dom.clientHeight);
7580 h = parseInt(this.getStyle('height'), 10) || 0;
7581 if(!this.isBorderBox()){
7582 h += this.getFrameWidth('tb');
7589 * Returns either the offsetWidth or the width of this element based on CSS width adjusted by padding or borders
7590 * when needed to simulate offsetWidth when offsets aren't available. This may not work on display:none elements
7591 * if a width has not been set using CSS.
7594 getComputedWidth : function(){
7595 var w = Math.max(this.dom.offsetWidth, this.dom.clientWidth);
7597 w = parseInt(this.getStyle('width'), 10) || 0;
7598 if(!this.isBorderBox()){
7599 w += this.getFrameWidth('lr');
7606 * Returns the size of the element.
7607 * @param {Boolean} contentSize (optional) true to get the width/size minus borders and padding
7608 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
7610 getSize : function(contentSize){
7611 return {width: this.getWidth(contentSize), height: this.getHeight(contentSize)};
7615 * Returns the width and height of the viewport.
7616 * @return {Object} An object containing the viewport's size {width: (viewport width), height: (viewport height)}
7618 getViewSize : function(){
7619 var d = this.dom, doc = document, aw = 0, ah = 0;
7620 if(d == doc || d == doc.body){
7621 return {width : D.getViewWidth(), height: D.getViewHeight()};
7624 width : d.clientWidth,
7625 height: d.clientHeight
7631 * Returns the value of the "value" attribute
7632 * @param {Boolean} asNumber true to parse the value as a number
7633 * @return {String/Number}
7635 getValue : function(asNumber){
7636 return asNumber ? parseInt(this.dom.value, 10) : this.dom.value;
7640 adjustWidth : function(width){
7641 if(typeof width == "number"){
7642 if(this.autoBoxAdjust && !this.isBorderBox()){
7643 width -= (this.getBorderWidth("lr") + this.getPadding("lr"));
7653 adjustHeight : function(height){
7654 if(typeof height == "number"){
7655 if(this.autoBoxAdjust && !this.isBorderBox()){
7656 height -= (this.getBorderWidth("tb") + this.getPadding("tb"));
7666 * Set the width of the element
7667 * @param {Number} width The new width
7668 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7669 * @return {Roo.Element} this
7671 setWidth : function(width, animate){
7672 width = this.adjustWidth(width);
7674 this.dom.style.width = this.addUnits(width);
7676 this.anim({width: {to: width}}, this.preanim(arguments, 1));
7682 * Set the height of the element
7683 * @param {Number} height The new height
7684 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7685 * @return {Roo.Element} this
7687 setHeight : function(height, animate){
7688 height = this.adjustHeight(height);
7690 this.dom.style.height = this.addUnits(height);
7692 this.anim({height: {to: height}}, this.preanim(arguments, 1));
7698 * Set the size of the element. If animation is true, both width an height will be animated concurrently.
7699 * @param {Number} width The new width
7700 * @param {Number} height The new height
7701 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7702 * @return {Roo.Element} this
7704 setSize : function(width, height, animate){
7705 if(typeof width == "object"){ // in case of object from getSize()
7706 height = width.height; width = width.width;
7708 width = this.adjustWidth(width); height = this.adjustHeight(height);
7710 this.dom.style.width = this.addUnits(width);
7711 this.dom.style.height = this.addUnits(height);
7713 this.anim({width: {to: width}, height: {to: height}}, this.preanim(arguments, 2));
7719 * Sets the element's position and size in one shot. If animation is true then width, height, x and y will be animated concurrently.
7720 * @param {Number} x X value for new position (coordinates are page-based)
7721 * @param {Number} y Y value for new position (coordinates are page-based)
7722 * @param {Number} width The new width
7723 * @param {Number} height The new height
7724 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7725 * @return {Roo.Element} this
7727 setBounds : function(x, y, width, height, animate){
7729 this.setSize(width, height);
7730 this.setLocation(x, y);
7732 width = this.adjustWidth(width); height = this.adjustHeight(height);
7733 this.anim({points: {to: [x, y]}, width: {to: width}, height: {to: height}},
7734 this.preanim(arguments, 4), 'motion');
7740 * 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.
7741 * @param {Roo.lib.Region} region The region to fill
7742 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7743 * @return {Roo.Element} this
7745 setRegion : function(region, animate){
7746 this.setBounds(region.left, region.top, region.right-region.left, region.bottom-region.top, this.preanim(arguments, 1));
7751 * Appends an event handler
7753 * @param {String} eventName The type of event to append
7754 * @param {Function} fn The method the event invokes
7755 * @param {Object} scope (optional) The scope (this object) of the fn
7756 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
7758 addListener : function(eventName, fn, scope, options){
7759 Roo.EventManager.on(this.dom, eventName, fn, scope || this, options);
7763 * Removes an event handler from this element
7764 * @param {String} eventName the type of event to remove
7765 * @param {Function} fn the method the event invokes
7766 * @return {Roo.Element} this
7768 removeListener : function(eventName, fn){
7769 Roo.EventManager.removeListener(this.dom, eventName, fn);
7774 * Removes all previous added listeners from this element
7775 * @return {Roo.Element} this
7777 removeAllListeners : function(){
7778 E.purgeElement(this.dom);
7782 relayEvent : function(eventName, observable){
7783 this.on(eventName, function(e){
7784 observable.fireEvent(eventName, e);
7789 * Set the opacity of the element
7790 * @param {Float} opacity The new opacity. 0 = transparent, .5 = 50% visibile, 1 = fully visible, etc
7791 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7792 * @return {Roo.Element} this
7794 setOpacity : function(opacity, animate){
7796 var s = this.dom.style;
7799 s.filter = (s.filter || '').replace(/alpha\([^\)]*\)/gi,"") +
7800 (opacity == 1 ? "" : "alpha(opacity=" + opacity * 100 + ")");
7802 s.opacity = opacity;
7805 this.anim({opacity: {to: opacity}}, this.preanim(arguments, 1), null, .35, 'easeIn');
7811 * Gets the left X coordinate
7812 * @param {Boolean} local True to get the local css position instead of page coordinate
7815 getLeft : function(local){
7819 return parseInt(this.getStyle("left"), 10) || 0;
7824 * Gets the right X coordinate of the element (element X position + element width)
7825 * @param {Boolean} local True to get the local css position instead of page coordinate
7828 getRight : function(local){
7830 return this.getX() + this.getWidth();
7832 return (this.getLeft(true) + this.getWidth()) || 0;
7837 * Gets the top Y coordinate
7838 * @param {Boolean} local True to get the local css position instead of page coordinate
7841 getTop : function(local) {
7845 return parseInt(this.getStyle("top"), 10) || 0;
7850 * Gets the bottom Y coordinate of the element (element Y position + element height)
7851 * @param {Boolean} local True to get the local css position instead of page coordinate
7854 getBottom : function(local){
7856 return this.getY() + this.getHeight();
7858 return (this.getTop(true) + this.getHeight()) || 0;
7863 * Initializes positioning on this element. If a desired position is not passed, it will make the
7864 * the element positioned relative IF it is not already positioned.
7865 * @param {String} pos (optional) Positioning to use "relative", "absolute" or "fixed"
7866 * @param {Number} zIndex (optional) The zIndex to apply
7867 * @param {Number} x (optional) Set the page X position
7868 * @param {Number} y (optional) Set the page Y position
7870 position : function(pos, zIndex, x, y){
7872 if(this.getStyle('position') == 'static'){
7873 this.setStyle('position', 'relative');
7876 this.setStyle("position", pos);
7879 this.setStyle("z-index", zIndex);
7881 if(x !== undefined && y !== undefined){
7883 }else if(x !== undefined){
7885 }else if(y !== undefined){
7891 * Clear positioning back to the default when the document was loaded
7892 * @param {String} value (optional) The value to use for the left,right,top,bottom, defaults to '' (empty string). You could use 'auto'.
7893 * @return {Roo.Element} this
7895 clearPositioning : function(value){
7903 "position" : "static"
7909 * Gets an object with all CSS positioning properties. Useful along with setPostioning to get
7910 * snapshot before performing an update and then restoring the element.
7913 getPositioning : function(){
7914 var l = this.getStyle("left");
7915 var t = this.getStyle("top");
7917 "position" : this.getStyle("position"),
7919 "right" : l ? "" : this.getStyle("right"),
7921 "bottom" : t ? "" : this.getStyle("bottom"),
7922 "z-index" : this.getStyle("z-index")
7927 * Gets the width of the border(s) for the specified side(s)
7928 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7929 * passing lr would get the border (l)eft width + the border (r)ight width.
7930 * @return {Number} The width of the sides passed added together
7932 getBorderWidth : function(side){
7933 return this.addStyles(side, El.borders);
7937 * Gets the width of the padding(s) for the specified side(s)
7938 * @param {String} side Can be t, l, r, b or any combination of those to add multiple values. For example,
7939 * passing lr would get the padding (l)eft + the padding (r)ight.
7940 * @return {Number} The padding of the sides passed added together
7942 getPadding : function(side){
7943 return this.addStyles(side, El.paddings);
7947 * Set positioning with an object returned by getPositioning().
7948 * @param {Object} posCfg
7949 * @return {Roo.Element} this
7951 setPositioning : function(pc){
7952 this.applyStyles(pc);
7953 if(pc.right == "auto"){
7954 this.dom.style.right = "";
7956 if(pc.bottom == "auto"){
7957 this.dom.style.bottom = "";
7963 fixDisplay : function(){
7964 if(this.getStyle("display") == "none"){
7965 this.setStyle("visibility", "hidden");
7966 this.setStyle("display", this.originalDisplay); // first try reverting to default
7967 if(this.getStyle("display") == "none"){ // if that fails, default to block
7968 this.setStyle("display", "block");
7974 * Quick set left and top adding default units
7975 * @param {String} left The left CSS property value
7976 * @param {String} top The top CSS property value
7977 * @return {Roo.Element} this
7979 setLeftTop : function(left, top){
7980 this.dom.style.left = this.addUnits(left);
7981 this.dom.style.top = this.addUnits(top);
7986 * Move this element relative to its current position.
7987 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
7988 * @param {Number} distance How far to move the element in pixels
7989 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
7990 * @return {Roo.Element} this
7992 move : function(direction, distance, animate){
7993 var xy = this.getXY();
7994 direction = direction.toLowerCase();
7998 this.moveTo(xy[0]-distance, xy[1], this.preanim(arguments, 2));
8002 this.moveTo(xy[0]+distance, xy[1], this.preanim(arguments, 2));
8007 this.moveTo(xy[0], xy[1]-distance, this.preanim(arguments, 2));
8012 this.moveTo(xy[0], xy[1]+distance, this.preanim(arguments, 2));
8019 * Store the current overflow setting and clip overflow on the element - use {@link #unclip} to remove
8020 * @return {Roo.Element} this
8023 if(!this.isClipped){
8024 this.isClipped = true;
8025 this.originalClip = {
8026 "o": this.getStyle("overflow"),
8027 "x": this.getStyle("overflow-x"),
8028 "y": this.getStyle("overflow-y")
8030 this.setStyle("overflow", "hidden");
8031 this.setStyle("overflow-x", "hidden");
8032 this.setStyle("overflow-y", "hidden");
8038 * Return clipping (overflow) to original clipping before clip() was called
8039 * @return {Roo.Element} this
8041 unclip : function(){
8043 this.isClipped = false;
8044 var o = this.originalClip;
8045 if(o.o){this.setStyle("overflow", o.o);}
8046 if(o.x){this.setStyle("overflow-x", o.x);}
8047 if(o.y){this.setStyle("overflow-y", o.y);}
8054 * Gets the x,y coordinates specified by the anchor position on the element.
8055 * @param {String} anchor (optional) The specified anchor position (defaults to "c"). See {@link #alignTo} for details on supported anchor positions.
8056 * @param {Object} size (optional) An object containing the size to use for calculating anchor position
8057 * {width: (target width), height: (target height)} (defaults to the element's current size)
8058 * @param {Boolean} local (optional) True to get the local (element top/left-relative) anchor position instead of page coordinates
8059 * @return {Array} [x, y] An array containing the element's x and y coordinates
8061 getAnchorXY : function(anchor, local, s){
8062 //Passing a different size is useful for pre-calculating anchors,
8063 //especially for anchored animations that change the el size.
8065 var w, h, vp = false;
8068 if(d == document.body || d == document){
8070 w = D.getViewWidth(); h = D.getViewHeight();
8072 w = this.getWidth(); h = this.getHeight();
8075 w = s.width; h = s.height;
8077 var x = 0, y = 0, r = Math.round;
8078 switch((anchor || "tl").toLowerCase()){
8120 var sc = this.getScroll();
8121 return [x + sc.left, y + sc.top];
8123 //Add the element's offset xy
8124 var o = this.getXY();
8125 return [x+o[0], y+o[1]];
8129 * Gets the x,y coordinates to align this element with another element. See {@link #alignTo} for more info on the
8130 * supported position values.
8131 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8132 * @param {String} position The position to align to.
8133 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8134 * @return {Array} [x, y]
8136 getAlignToXY : function(el, p, o){
8140 throw "Element.alignTo with an element that doesn't exist";
8142 var c = false; //constrain to viewport
8143 var p1 = "", p2 = "";
8150 }else if(p.indexOf("-") == -1){
8153 p = p.toLowerCase();
8154 var m = p.match(/^([a-z]+)-([a-z]+)(\?)?$/);
8156 throw "Element.alignTo with an invalid alignment " + p;
8158 p1 = m[1]; p2 = m[2]; c = !!m[3];
8160 //Subtract the aligned el's internal xy from the target's offset xy
8161 //plus custom offset to get the aligned el's new offset xy
8162 var a1 = this.getAnchorXY(p1, true);
8163 var a2 = el.getAnchorXY(p2, false);
8164 var x = a2[0] - a1[0] + o[0];
8165 var y = a2[1] - a1[1] + o[1];
8167 //constrain the aligned el to viewport if necessary
8168 var w = this.getWidth(), h = this.getHeight(), r = el.getRegion();
8169 // 5px of margin for ie
8170 var dw = D.getViewWidth()-5, dh = D.getViewHeight()-5;
8172 //If we are at a viewport boundary and the aligned el is anchored on a target border that is
8173 //perpendicular to the vp border, allow the aligned el to slide on that border,
8174 //otherwise swap the aligned el to the opposite border of the target.
8175 var p1y = p1.charAt(0), p1x = p1.charAt(p1.length-1);
8176 var p2y = p2.charAt(0), p2x = p2.charAt(p2.length-1);
8177 var swapY = ((p1y=="t" && p2y=="b") || (p1y=="b" && p2y=="t"));
8178 var swapX = ((p1x=="r" && p2x=="l") || (p1x=="l" && p2x=="r"));
8181 var scrollX = (doc.documentElement.scrollLeft || doc.body.scrollLeft || 0)+5;
8182 var scrollY = (doc.documentElement.scrollTop || doc.body.scrollTop || 0)+5;
8184 if((x+w) > dw + scrollX){
8185 x = swapX ? r.left-w : dw+scrollX-w;
8188 x = swapX ? r.right : scrollX;
8190 if((y+h) > dh + scrollY){
8191 y = swapY ? r.top-h : dh+scrollY-h;
8194 y = swapY ? r.bottom : scrollY;
8201 getConstrainToXY : function(){
8202 var os = {top:0, left:0, bottom:0, right: 0};
8204 return function(el, local, offsets, proposedXY){
8206 offsets = offsets ? Roo.applyIf(offsets, os) : os;
8208 var vw, vh, vx = 0, vy = 0;
8209 if(el.dom == document.body || el.dom == document){
8210 vw = Roo.lib.Dom.getViewWidth();
8211 vh = Roo.lib.Dom.getViewHeight();
8213 vw = el.dom.clientWidth;
8214 vh = el.dom.clientHeight;
8216 var vxy = el.getXY();
8222 var s = el.getScroll();
8224 vx += offsets.left + s.left;
8225 vy += offsets.top + s.top;
8227 vw -= offsets.right;
8228 vh -= offsets.bottom;
8233 var xy = proposedXY || (!local ? this.getXY() : [this.getLeft(true), this.getTop(true)]);
8234 var x = xy[0], y = xy[1];
8235 var w = this.dom.offsetWidth, h = this.dom.offsetHeight;
8237 // only move it if it needs it
8240 // first validate right/bottom
8249 // then make sure top/left isn't negative
8258 return moved ? [x, y] : false;
8263 adjustForConstraints : function(xy, parent, offsets){
8264 return this.getConstrainToXY(parent || document, false, offsets, xy) || xy;
8268 * Aligns this element with another element relative to the specified anchor points. If the other element is the
8269 * document it aligns it to the viewport.
8270 * The position parameter is optional, and can be specified in any one of the following formats:
8272 * <li><b>Blank</b>: Defaults to aligning the element's top-left corner to the target's bottom-left corner ("tl-bl").</li>
8273 * <li><b>One anchor (deprecated)</b>: The passed anchor position is used as the target element's anchor point.
8274 * The element being aligned will position its top-left corner (tl) to that point. <i>This method has been
8275 * deprecated in favor of the newer two anchor syntax below</i>.</li>
8276 * <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
8277 * element's anchor point, and the second value is used as the target's anchor point.</li>
8279 * In addition to the anchor points, the position parameter also supports the "?" character. If "?" is passed at the end of
8280 * the position string, the element will attempt to align as specified, but the position will be adjusted to constrain to
8281 * the viewport if necessary. Note that the element being aligned might be swapped to align to a different position than
8282 * that specified in order to enforce the viewport constraints.
8283 * Following are all of the supported anchor positions:
8286 ----- -----------------------------
8287 tl The top left corner (default)
8288 t The center of the top edge
8289 tr The top right corner
8290 l The center of the left edge
8291 c In the center of the element
8292 r The center of the right edge
8293 bl The bottom left corner
8294 b The center of the bottom edge
8295 br The bottom right corner
8299 // align el to other-el using the default positioning ("tl-bl", non-constrained)
8300 el.alignTo("other-el");
8302 // align the top left corner of el with the top right corner of other-el (constrained to viewport)
8303 el.alignTo("other-el", "tr?");
8305 // align the bottom right corner of el with the center left edge of other-el
8306 el.alignTo("other-el", "br-l?");
8308 // align the center of el with the bottom left corner of other-el and
8309 // adjust the x position by -6 pixels (and the y position by 0)
8310 el.alignTo("other-el", "c-bl", [-6, 0]);
8312 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8313 * @param {String} position The position to align to.
8314 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8315 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8316 * @return {Roo.Element} this
8318 alignTo : function(element, position, offsets, animate){
8319 var xy = this.getAlignToXY(element, position, offsets);
8320 this.setXY(xy, this.preanim(arguments, 3));
8325 * Anchors an element to another element and realigns it when the window is resized.
8326 * @param {String/HTMLElement/Roo.Element} element The element to align to.
8327 * @param {String} position The position to align to.
8328 * @param {Array} offsets (optional) Offset the positioning by [x, y]
8329 * @param {Boolean/Object} animate (optional) True for the default animation or a standard Element animation config object
8330 * @param {Boolean/Number} monitorScroll (optional) True to monitor body scroll and reposition. If this parameter
8331 * is a number, it is used as the buffer delay (defaults to 50ms).
8332 * @param {Function} callback The function to call after the animation finishes
8333 * @return {Roo.Element} this
8335 anchorTo : function(el, alignment, offsets, animate, monitorScroll, callback){
8336 var action = function(){
8337 this.alignTo(el, alignment, offsets, animate);
8338 Roo.callback(callback, this);
8340 Roo.EventManager.onWindowResize(action, this);
8341 var tm = typeof monitorScroll;
8342 if(tm != 'undefined'){
8343 Roo.EventManager.on(window, 'scroll', action, this,
8344 {buffer: tm == 'number' ? monitorScroll : 50});
8346 action.call(this); // align immediately
8350 * Clears any opacity settings from this element. Required in some cases for IE.
8351 * @return {Roo.Element} this
8353 clearOpacity : function(){
8354 if (window.ActiveXObject) {
8355 if(typeof this.dom.style.filter == 'string' && (/alpha/i).test(this.dom.style.filter)){
8356 this.dom.style.filter = "";
8359 this.dom.style.opacity = "";
8360 this.dom.style["-moz-opacity"] = "";
8361 this.dom.style["-khtml-opacity"] = "";
8367 * Hide this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8368 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8369 * @return {Roo.Element} this
8371 hide : function(animate){
8372 this.setVisible(false, this.preanim(arguments, 0));
8377 * Show this element - Uses display mode to determine whether to use "display" or "visibility". See {@link #setVisible}.
8378 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8379 * @return {Roo.Element} this
8381 show : function(animate){
8382 this.setVisible(true, this.preanim(arguments, 0));
8387 * @private Test if size has a unit, otherwise appends the default
8389 addUnits : function(size){
8390 return Roo.Element.addUnits(size, this.defaultUnit);
8394 * Temporarily enables offsets (width,height,x,y) for an element with display:none, use endMeasure() when done.
8395 * @return {Roo.Element} this
8397 beginMeasure : function(){
8399 if(el.offsetWidth || el.offsetHeight){
8400 return this; // offsets work already
8403 var p = this.dom, b = document.body; // start with this element
8404 while((!el.offsetWidth && !el.offsetHeight) && p && p.tagName && p != b){
8405 var pe = Roo.get(p);
8406 if(pe.getStyle('display') == 'none'){
8407 changed.push({el: p, visibility: pe.getStyle("visibility")});
8408 p.style.visibility = "hidden";
8409 p.style.display = "block";
8413 this._measureChanged = changed;
8419 * Restores displays to before beginMeasure was called
8420 * @return {Roo.Element} this
8422 endMeasure : function(){
8423 var changed = this._measureChanged;
8425 for(var i = 0, len = changed.length; i < len; i++) {
8427 r.el.style.visibility = r.visibility;
8428 r.el.style.display = "none";
8430 this._measureChanged = null;
8436 * Update the innerHTML of this element, optionally searching for and processing scripts
8437 * @param {String} html The new HTML
8438 * @param {Boolean} loadScripts (optional) true to look for and process scripts
8439 * @param {Function} callback For async script loading you can be noticed when the update completes
8440 * @return {Roo.Element} this
8442 update : function(html, loadScripts, callback){
8443 if(typeof html == "undefined"){
8446 if(loadScripts !== true){
8447 this.dom.innerHTML = html;
8448 if(typeof callback == "function"){
8456 html += '<span id="' + id + '"></span>';
8458 E.onAvailable(id, function(){
8459 var hd = document.getElementsByTagName("head")[0];
8460 var re = /(?:<script([^>]*)?>)((\n|\r|.)*?)(?:<\/script>)/ig;
8461 var srcRe = /\ssrc=([\'\"])(.*?)\1/i;
8462 var typeRe = /\stype=([\'\"])(.*?)\1/i;
8465 while(match = re.exec(html)){
8466 var attrs = match[1];
8467 var srcMatch = attrs ? attrs.match(srcRe) : false;
8468 if(srcMatch && srcMatch[2]){
8469 var s = document.createElement("script");
8470 s.src = srcMatch[2];
8471 var typeMatch = attrs.match(typeRe);
8472 if(typeMatch && typeMatch[2]){
8473 s.type = typeMatch[2];
8476 }else if(match[2] && match[2].length > 0){
8477 if(window.execScript) {
8478 window.execScript(match[2]);
8486 window.eval(match[2]);
8490 var el = document.getElementById(id);
8491 if(el){el.parentNode.removeChild(el);}
8492 if(typeof callback == "function"){
8496 dom.innerHTML = html.replace(/(?:<script.*?>)((\n|\r|.)*?)(?:<\/script>)/ig, "");
8501 * Direct access to the UpdateManager update() method (takes the same parameters).
8502 * @param {String/Function} url The url for this request or a function to call to get the url
8503 * @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}
8504 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
8505 * @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.
8506 * @return {Roo.Element} this
8509 var um = this.getUpdateManager();
8510 um.update.apply(um, arguments);
8515 * Gets this element's UpdateManager
8516 * @return {Roo.UpdateManager} The UpdateManager
8518 getUpdateManager : function(){
8519 if(!this.updateManager){
8520 this.updateManager = new Roo.UpdateManager(this);
8522 return this.updateManager;
8526 * Disables text selection for this element (normalized across browsers)
8527 * @return {Roo.Element} this
8529 unselectable : function(){
8530 this.dom.unselectable = "on";
8531 this.swallowEvent("selectstart", true);
8532 this.applyStyles("-moz-user-select:none;-khtml-user-select:none;");
8533 this.addClass("x-unselectable");
8538 * Calculates the x, y to center this element on the screen
8539 * @return {Array} The x, y values [x, y]
8541 getCenterXY : function(){
8542 return this.getAlignToXY(document, 'c-c');
8546 * Centers the Element in either the viewport, or another Element.
8547 * @param {String/HTMLElement/Roo.Element} centerIn (optional) The element in which to center the element.
8549 center : function(centerIn){
8550 this.alignTo(centerIn || document, 'c-c');
8555 * Tests various css rules/browsers to determine if this element uses a border box
8558 isBorderBox : function(){
8559 return noBoxAdjust[this.dom.tagName.toLowerCase()] || Roo.isBorderBox;
8563 * Return a box {x, y, width, height} that can be used to set another elements
8564 * size/location to match this element.
8565 * @param {Boolean} contentBox (optional) If true a box for the content of the element is returned.
8566 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page x/y.
8567 * @return {Object} box An object in the format {x, y, width, height}
8569 getBox : function(contentBox, local){
8574 var left = parseInt(this.getStyle("left"), 10) || 0;
8575 var top = parseInt(this.getStyle("top"), 10) || 0;
8578 var el = this.dom, w = el.offsetWidth, h = el.offsetHeight, bx;
8580 bx = {x: xy[0], y: xy[1], 0: xy[0], 1: xy[1], width: w, height: h};
8582 var l = this.getBorderWidth("l")+this.getPadding("l");
8583 var r = this.getBorderWidth("r")+this.getPadding("r");
8584 var t = this.getBorderWidth("t")+this.getPadding("t");
8585 var b = this.getBorderWidth("b")+this.getPadding("b");
8586 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)};
8588 bx.right = bx.x + bx.width;
8589 bx.bottom = bx.y + bx.height;
8594 * Returns the sum width of the padding and borders for the passed "sides". See getBorderWidth()
8595 for more information about the sides.
8596 * @param {String} sides
8599 getFrameWidth : function(sides, onlyContentBox){
8600 return onlyContentBox && Roo.isBorderBox ? 0 : (this.getPadding(sides) + this.getBorderWidth(sides));
8604 * 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.
8605 * @param {Object} box The box to fill {x, y, width, height}
8606 * @param {Boolean} adjust (optional) Whether to adjust for box-model issues automatically
8607 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
8608 * @return {Roo.Element} this
8610 setBox : function(box, adjust, animate){
8611 var w = box.width, h = box.height;
8612 if((adjust && !this.autoBoxAdjust) && !this.isBorderBox()){
8613 w -= (this.getBorderWidth("lr") + this.getPadding("lr"));
8614 h -= (this.getBorderWidth("tb") + this.getPadding("tb"));
8616 this.setBounds(box.x, box.y, w, h, this.preanim(arguments, 2));
8621 * Forces the browser to repaint this element
8622 * @return {Roo.Element} this
8624 repaint : function(){
8626 this.addClass("x-repaint");
8627 setTimeout(function(){
8628 Roo.get(dom).removeClass("x-repaint");
8634 * Returns an object with properties top, left, right and bottom representing the margins of this element unless sides is passed,
8635 * then it returns the calculated width of the sides (see getPadding)
8636 * @param {String} sides (optional) Any combination of l, r, t, b to get the sum of those sides
8637 * @return {Object/Number}
8639 getMargins : function(side){
8642 top: parseInt(this.getStyle("margin-top"), 10) || 0,
8643 left: parseInt(this.getStyle("margin-left"), 10) || 0,
8644 bottom: parseInt(this.getStyle("margin-bottom"), 10) || 0,
8645 right: parseInt(this.getStyle("margin-right"), 10) || 0
8648 return this.addStyles(side, El.margins);
8653 addStyles : function(sides, styles){
8655 for(var i = 0, len = sides.length; i < len; i++){
8656 v = this.getStyle(styles[sides.charAt(i)]);
8658 w = parseInt(v, 10);
8666 * Creates a proxy element of this element
8667 * @param {String/Object} config The class name of the proxy element or a DomHelper config object
8668 * @param {String/HTMLElement} renderTo (optional) The element or element id to render the proxy to (defaults to document.body)
8669 * @param {Boolean} matchBox (optional) True to align and size the proxy to this element now (defaults to false)
8670 * @return {Roo.Element} The new proxy element
8672 createProxy : function(config, renderTo, matchBox){
8674 renderTo = Roo.getDom(renderTo);
8676 renderTo = document.body;
8678 config = typeof config == "object" ?
8679 config : {tag : "div", cls: config};
8680 var proxy = Roo.DomHelper.append(renderTo, config, true);
8682 proxy.setBox(this.getBox());
8688 * Puts a mask over this element to disable user interaction. Requires core.css.
8689 * This method can only be applied to elements which accept child nodes.
8690 * @param {String} msg (optional) A message to display in the mask
8691 * @param {String} msgCls (optional) A css class to apply to the msg element
8692 * @return {Element} The mask element
8694 mask : function(msg, msgCls){
8695 if(this.getStyle("position") == "static"){
8696 this.setStyle("position", "relative");
8699 this._mask = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask"}, true);
8701 this.addClass("x-masked");
8702 this._mask.setDisplayed(true);
8703 if(typeof msg == 'string'){
8705 this._maskMsg = Roo.DomHelper.append(this.dom, {cls:"roo-el-mask-msg", cn:{tag:'div'}}, true);
8707 var mm = this._maskMsg;
8708 mm.dom.className = msgCls ? "roo-el-mask-msg " + msgCls : "roo-el-mask-msg";
8709 mm.dom.firstChild.innerHTML = msg;
8710 mm.setDisplayed(true);
8713 if(Roo.isIE && !(Roo.isIE7 && Roo.isStrict) && this.getStyle('height') == 'auto'){ // ie will not expand full height automatically
8714 this._mask.setHeight(this.getHeight());
8720 * Removes a previously applied mask. If removeEl is true the mask overlay is destroyed, otherwise
8721 * it is cached for reuse.
8723 unmask : function(removeEl){
8725 if(removeEl === true){
8726 this._mask.remove();
8729 this._maskMsg.remove();
8730 delete this._maskMsg;
8733 this._mask.setDisplayed(false);
8735 this._maskMsg.setDisplayed(false);
8739 this.removeClass("x-masked");
8743 * Returns true if this element is masked
8746 isMasked : function(){
8747 return this._mask && this._mask.isVisible();
8751 * Creates an iframe shim for this element to keep selects and other windowed objects from
8753 * @return {Roo.Element} The new shim element
8755 createShim : function(){
8756 var el = document.createElement('iframe');
8757 el.frameBorder = 'no';
8758 el.className = 'roo-shim';
8759 if(Roo.isIE && Roo.isSecure){
8760 el.src = Roo.SSL_SECURE_URL;
8762 var shim = Roo.get(this.dom.parentNode.insertBefore(el, this.dom));
8763 shim.autoBoxAdjust = false;
8768 * Removes this element from the DOM and deletes it from the cache
8770 remove : function(){
8771 if(this.dom.parentNode){
8772 this.dom.parentNode.removeChild(this.dom);
8774 delete El.cache[this.dom.id];
8778 * Sets up event handlers to add and remove a css class when the mouse is over this element
8779 * @param {String} className
8780 * @param {Boolean} preventFlicker (optional) If set to true, it prevents flickering by filtering
8781 * mouseout events for children elements
8782 * @return {Roo.Element} this
8784 addClassOnOver : function(className, preventFlicker){
8785 this.on("mouseover", function(){
8786 Roo.fly(this, '_internal').addClass(className);
8788 var removeFn = function(e){
8789 if(preventFlicker !== true || !e.within(this, true)){
8790 Roo.fly(this, '_internal').removeClass(className);
8793 this.on("mouseout", removeFn, this.dom);
8798 * Sets up event handlers to add and remove a css class when this element has the focus
8799 * @param {String} className
8800 * @return {Roo.Element} this
8802 addClassOnFocus : function(className){
8803 this.on("focus", function(){
8804 Roo.fly(this, '_internal').addClass(className);
8806 this.on("blur", function(){
8807 Roo.fly(this, '_internal').removeClass(className);
8812 * 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)
8813 * @param {String} className
8814 * @return {Roo.Element} this
8816 addClassOnClick : function(className){
8818 this.on("mousedown", function(){
8819 Roo.fly(dom, '_internal').addClass(className);
8820 var d = Roo.get(document);
8821 var fn = function(){
8822 Roo.fly(dom, '_internal').removeClass(className);
8823 d.removeListener("mouseup", fn);
8825 d.on("mouseup", fn);
8831 * Stops the specified event from bubbling and optionally prevents the default action
8832 * @param {String} eventName
8833 * @param {Boolean} preventDefault (optional) true to prevent the default action too
8834 * @return {Roo.Element} this
8836 swallowEvent : function(eventName, preventDefault){
8837 var fn = function(e){
8838 e.stopPropagation();
8843 if(eventName instanceof Array){
8844 for(var i = 0, len = eventName.length; i < len; i++){
8845 this.on(eventName[i], fn);
8849 this.on(eventName, fn);
8856 fitToParentDelegate : Roo.emptyFn, // keep a reference to the fitToParent delegate
8859 * Sizes this element to its parent element's dimensions performing
8860 * neccessary box adjustments.
8861 * @param {Boolean} monitorResize (optional) If true maintains the fit when the browser window is resized.
8862 * @param {String/HTMLElment/Element} targetParent (optional) The target parent, default to the parentNode.
8863 * @return {Roo.Element} this
8865 fitToParent : function(monitorResize, targetParent) {
8866 Roo.EventManager.removeResizeListener(this.fitToParentDelegate); // always remove previous fitToParent delegate from onWindowResize
8867 this.fitToParentDelegate = Roo.emptyFn; // remove reference to previous delegate
8868 if (monitorResize === true && !this.dom.parentNode) { // check if this Element still exists
8871 var p = Roo.get(targetParent || this.dom.parentNode);
8872 this.setSize(p.getComputedWidth() - p.getFrameWidth('lr'), p.getComputedHeight() - p.getFrameWidth('tb'));
8873 if (monitorResize === true) {
8874 this.fitToParentDelegate = this.fitToParent.createDelegate(this, [true, targetParent]);
8875 Roo.EventManager.onWindowResize(this.fitToParentDelegate);
8881 * Gets the next sibling, skipping text nodes
8882 * @return {HTMLElement} The next sibling or null
8884 getNextSibling : function(){
8885 var n = this.dom.nextSibling;
8886 while(n && n.nodeType != 1){
8893 * Gets the previous sibling, skipping text nodes
8894 * @return {HTMLElement} The previous sibling or null
8896 getPrevSibling : function(){
8897 var n = this.dom.previousSibling;
8898 while(n && n.nodeType != 1){
8899 n = n.previousSibling;
8906 * Appends the passed element(s) to this element
8907 * @param {String/HTMLElement/Array/Element/CompositeElement} el
8908 * @return {Roo.Element} this
8910 appendChild: function(el){
8917 * Creates the passed DomHelper config and appends it to this element or optionally inserts it before the passed child element.
8918 * @param {Object} config DomHelper element config object. If no tag is specified (e.g., {tag:'input'}) then a div will be
8919 * automatically generated with the specified attributes.
8920 * @param {HTMLElement} insertBefore (optional) a child element of this element
8921 * @param {Boolean} returnDom (optional) true to return the dom node instead of creating an Element
8922 * @return {Roo.Element} The new child element
8924 createChild: function(config, insertBefore, returnDom){
8925 config = config || {tag:'div'};
8927 return Roo.DomHelper.insertBefore(insertBefore, config, returnDom !== true);
8929 return Roo.DomHelper[!this.dom.firstChild ? 'overwrite' : 'append'](this.dom, config, returnDom !== true);
8933 * Appends this element to the passed element
8934 * @param {String/HTMLElement/Element} el The new parent element
8935 * @return {Roo.Element} this
8937 appendTo: function(el){
8938 el = Roo.getDom(el);
8939 el.appendChild(this.dom);
8944 * Inserts this element before the passed element in the DOM
8945 * @param {String/HTMLElement/Element} el The element to insert before
8946 * @return {Roo.Element} this
8948 insertBefore: function(el){
8949 el = Roo.getDom(el);
8950 el.parentNode.insertBefore(this.dom, el);
8955 * Inserts this element after the passed element in the DOM
8956 * @param {String/HTMLElement/Element} el The element to insert after
8957 * @return {Roo.Element} this
8959 insertAfter: function(el){
8960 el = Roo.getDom(el);
8961 el.parentNode.insertBefore(this.dom, el.nextSibling);
8966 * Inserts (or creates) an element (or DomHelper config) as the first child of the this element
8967 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8968 * @return {Roo.Element} The new child
8970 insertFirst: function(el, returnDom){
8972 if(typeof el == 'object' && !el.nodeType){ // dh config
8973 return this.createChild(el, this.dom.firstChild, returnDom);
8975 el = Roo.getDom(el);
8976 this.dom.insertBefore(el, this.dom.firstChild);
8977 return !returnDom ? Roo.get(el) : el;
8982 * Inserts (or creates) the passed element (or DomHelper config) as a sibling of this element
8983 * @param {String/HTMLElement/Element/Object} el The id or element to insert or a DomHelper config to create and insert
8984 * @param {String} where (optional) 'before' or 'after' defaults to before
8985 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
8986 * @return {Roo.Element} the inserted Element
8988 insertSibling: function(el, where, returnDom){
8989 where = where ? where.toLowerCase() : 'before';
8991 var rt, refNode = where == 'before' ? this.dom : this.dom.nextSibling;
8993 if(typeof el == 'object' && !el.nodeType){ // dh config
8994 if(where == 'after' && !this.dom.nextSibling){
8995 rt = Roo.DomHelper.append(this.dom.parentNode, el, !returnDom);
8997 rt = Roo.DomHelper[where == 'after' ? 'insertAfter' : 'insertBefore'](this.dom, el, !returnDom);
9001 rt = this.dom.parentNode.insertBefore(Roo.getDom(el),
9002 where == 'before' ? this.dom : this.dom.nextSibling);
9011 * Creates and wraps this element with another element
9012 * @param {Object} config (optional) DomHelper element config object for the wrapper element or null for an empty div
9013 * @param {Boolean} returnDom (optional) True to return the raw DOM element instead of Roo.Element
9014 * @return {HTMLElement/Element} The newly created wrapper element
9016 wrap: function(config, returnDom){
9018 config = {tag: "div"};
9020 var newEl = Roo.DomHelper.insertBefore(this.dom, config, !returnDom);
9021 newEl.dom ? newEl.dom.appendChild(this.dom) : newEl.appendChild(this.dom);
9026 * Replaces the passed element with this element
9027 * @param {String/HTMLElement/Element} el The element to replace
9028 * @return {Roo.Element} this
9030 replace: function(el){
9032 this.insertBefore(el);
9038 * Inserts an html fragment into this element
9039 * @param {String} where Where to insert the html in relation to the this element - beforeBegin, afterBegin, beforeEnd, afterEnd.
9040 * @param {String} html The HTML fragment
9041 * @param {Boolean} returnEl True to return an Roo.Element
9042 * @return {HTMLElement/Roo.Element} The inserted node (or nearest related if more than 1 inserted)
9044 insertHtml : function(where, html, returnEl){
9045 var el = Roo.DomHelper.insertHtml(where, this.dom, html);
9046 return returnEl ? Roo.get(el) : el;
9050 * Sets the passed attributes as attributes of this element (a style attribute can be a string, object or function)
9051 * @param {Object} o The object with the attributes
9052 * @param {Boolean} useSet (optional) false to override the default setAttribute to use expandos.
9053 * @return {Roo.Element} this
9055 set : function(o, useSet){
9057 useSet = typeof useSet == 'undefined' ? (el.setAttribute ? true : false) : useSet;
9059 if(attr == "style" || typeof o[attr] == "function") continue;
9061 el.className = o["cls"];
9063 if(useSet) el.setAttribute(attr, o[attr]);
9064 else el[attr] = o[attr];
9068 Roo.DomHelper.applyStyles(el, o.style);
9074 * Convenience method for constructing a KeyMap
9075 * @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:
9076 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
9077 * @param {Function} fn The function to call
9078 * @param {Object} scope (optional) The scope of the function
9079 * @return {Roo.KeyMap} The KeyMap created
9081 addKeyListener : function(key, fn, scope){
9083 if(typeof key != "object" || key instanceof Array){
9099 return new Roo.KeyMap(this, config);
9103 * Creates a KeyMap for this element
9104 * @param {Object} config The KeyMap config. See {@link Roo.KeyMap} for more details
9105 * @return {Roo.KeyMap} The KeyMap created
9107 addKeyMap : function(config){
9108 return new Roo.KeyMap(this, config);
9112 * Returns true if this element is scrollable.
9115 isScrollable : function(){
9117 return dom.scrollHeight > dom.clientHeight || dom.scrollWidth > dom.clientWidth;
9121 * 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().
9122 * @param {String} side Either "left" for scrollLeft values or "top" for scrollTop values.
9123 * @param {Number} value The new scroll value
9124 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9125 * @return {Element} this
9128 scrollTo : function(side, value, animate){
9129 var prop = side.toLowerCase() == "left" ? "scrollLeft" : "scrollTop";
9131 this.dom[prop] = value;
9133 var to = prop == "scrollLeft" ? [value, this.dom.scrollTop] : [this.dom.scrollLeft, value];
9134 this.anim({scroll: {"to": to}}, this.preanim(arguments, 2), 'scroll');
9140 * Scrolls this element the specified direction. Does bounds checking to make sure the scroll is
9141 * within this element's scrollable range.
9142 * @param {String} direction Possible values are: "l","left" - "r","right" - "t","top","up" - "b","bottom","down".
9143 * @param {Number} distance How far to scroll the element in pixels
9144 * @param {Boolean/Object} animate (optional) true for the default animation or a standard Element animation config object
9145 * @return {Boolean} Returns true if a scroll was triggered or false if the element
9146 * was scrolled as far as it could go.
9148 scroll : function(direction, distance, animate){
9149 if(!this.isScrollable()){
9153 var l = el.scrollLeft, t = el.scrollTop;
9154 var w = el.scrollWidth, h = el.scrollHeight;
9155 var cw = el.clientWidth, ch = el.clientHeight;
9156 direction = direction.toLowerCase();
9157 var scrolled = false;
9158 var a = this.preanim(arguments, 2);
9163 var v = Math.min(l + distance, w-cw);
9164 this.scrollTo("left", v, a);
9171 var v = Math.max(l - distance, 0);
9172 this.scrollTo("left", v, a);
9180 var v = Math.max(t - distance, 0);
9181 this.scrollTo("top", v, a);
9189 var v = Math.min(t + distance, h-ch);
9190 this.scrollTo("top", v, a);
9199 * Translates the passed page coordinates into left/top css values for this element
9200 * @param {Number/Array} x The page x or an array containing [x, y]
9201 * @param {Number} y The page y
9202 * @return {Object} An object with left and top properties. e.g. {left: (value), top: (value)}
9204 translatePoints : function(x, y){
9205 if(typeof x == 'object' || x instanceof Array){
9208 var p = this.getStyle('position');
9209 var o = this.getXY();
9211 var l = parseInt(this.getStyle('left'), 10);
9212 var t = parseInt(this.getStyle('top'), 10);
9215 l = (p == "relative") ? 0 : this.dom.offsetLeft;
9218 t = (p == "relative") ? 0 : this.dom.offsetTop;
9221 return {left: (x - o[0] + l), top: (y - o[1] + t)};
9225 * Returns the current scroll position of the element.
9226 * @return {Object} An object containing the scroll position in the format {left: (scrollLeft), top: (scrollTop)}
9228 getScroll : function(){
9229 var d = this.dom, doc = document;
9230 if(d == doc || d == doc.body){
9231 var l = window.pageXOffset || doc.documentElement.scrollLeft || doc.body.scrollLeft || 0;
9232 var t = window.pageYOffset || doc.documentElement.scrollTop || doc.body.scrollTop || 0;
9233 return {left: l, top: t};
9235 return {left: d.scrollLeft, top: d.scrollTop};
9240 * Return the CSS color for the specified CSS attribute. rgb, 3 digit (like #fff) and valid values
9241 * are convert to standard 6 digit hex color.
9242 * @param {String} attr The css attribute
9243 * @param {String} defaultValue The default value to use when a valid color isn't found
9244 * @param {String} prefix (optional) defaults to #. Use an empty string when working with
9247 getColor : function(attr, defaultValue, prefix){
9248 var v = this.getStyle(attr);
9249 if(!v || v == "transparent" || v == "inherit") {
9250 return defaultValue;
9252 var color = typeof prefix == "undefined" ? "#" : prefix;
9253 if(v.substr(0, 4) == "rgb("){
9254 var rvs = v.slice(4, v.length -1).split(",");
9255 for(var i = 0; i < 3; i++){
9256 var h = parseInt(rvs[i]).toString(16);
9263 if(v.substr(0, 1) == "#"){
9265 for(var i = 1; i < 4; i++){
9266 var c = v.charAt(i);
9269 }else if(v.length == 7){
9270 color += v.substr(1);
9274 return(color.length > 5 ? color.toLowerCase() : defaultValue);
9278 * Wraps the specified element with a special markup/CSS block that renders by default as a gray container with a
9279 * gradient background, rounded corners and a 4-way shadow.
9280 * @param {String} class (optional) A base CSS class to apply to the containing wrapper element (defaults to 'x-box').
9281 * Note that there are a number of CSS rules that are dependent on this name to make the overall effect work,
9282 * so if you supply an alternate base class, make sure you also supply all of the necessary rules.
9283 * @return {Roo.Element} this
9285 boxWrap : function(cls){
9286 cls = cls || 'x-box';
9287 var el = Roo.get(this.insertHtml('beforeBegin', String.format('<div class="{0}">'+El.boxMarkup+'</div>', cls)));
9288 el.child('.'+cls+'-mc').dom.appendChild(this.dom);
9293 * Returns the value of a namespaced attribute from the element's underlying DOM node.
9294 * @param {String} namespace The namespace in which to look for the attribute
9295 * @param {String} name The attribute name
9296 * @return {String} The attribute value
9298 getAttributeNS : Roo.isIE ? function(ns, name){
9300 var type = typeof d[ns+":"+name];
9301 if(type != 'undefined' && type != 'unknown'){
9302 return d[ns+":"+name];
9305 } : function(ns, name){
9307 return d.getAttributeNS(ns, name) || d.getAttribute(ns+":"+name) || d.getAttribute(name) || d[name];
9311 var ep = El.prototype;
9314 * Appends an event handler (Shorthand for addListener)
9315 * @param {String} eventName The type of event to append
9316 * @param {Function} fn The method the event invokes
9317 * @param {Object} scope (optional) The scope (this object) of the fn
9318 * @param {Object} options (optional)An object with standard {@link Roo.EventManager#addListener} options
9321 ep.on = ep.addListener;
9323 ep.mon = ep.addListener;
9326 * Removes an event handler from this element (shorthand for removeListener)
9327 * @param {String} eventName the type of event to remove
9328 * @param {Function} fn the method the event invokes
9329 * @return {Roo.Element} this
9332 ep.un = ep.removeListener;
9335 * true to automatically adjust width and height settings for box-model issues (default to true)
9337 ep.autoBoxAdjust = true;
9340 El.unitPattern = /\d+(px|em|%|en|ex|pt|in|cm|mm|pc)$/i;
9343 El.addUnits = function(v, defaultUnit){
9344 if(v === "" || v == "auto"){
9347 if(v === undefined){
9350 if(typeof v == "number" || !El.unitPattern.test(v)){
9351 return v + (defaultUnit || 'px');
9356 // special markup used throughout Roo when box wrapping elements
9357 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>';
9359 * Visibility mode constant - Use visibility to hide element
9365 * Visibility mode constant - Use display to hide element
9371 El.borders = {l: "border-left-width", r: "border-right-width", t: "border-top-width", b: "border-bottom-width"};
9372 El.paddings = {l: "padding-left", r: "padding-right", t: "padding-top", b: "padding-bottom"};
9373 El.margins = {l: "margin-left", r: "margin-right", t: "margin-top", b: "margin-bottom"};
9385 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9386 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9387 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9388 * @return {Element} The Element object
9391 El.get = function(el){
9393 if(!el){ return null; }
9394 if(typeof el == "string"){ // element id
9395 if(!(elm = document.getElementById(el))){
9398 if(ex = El.cache[el]){
9401 ex = El.cache[el] = new El(elm);
9404 }else if(el.tagName){ // dom element
9408 if(ex = El.cache[id]){
9411 ex = El.cache[id] = new El(el);
9414 }else if(el instanceof El){
9416 el.dom = document.getElementById(el.id) || el.dom; // refresh dom element in case no longer valid,
9417 // catch case where it hasn't been appended
9418 El.cache[el.id] = el; // in case it was created directly with Element(), let's cache it
9421 }else if(el.isComposite){
9423 }else if(el instanceof Array){
9424 return El.select(el);
9425 }else if(el == document){
9426 // create a bogus element object representing the document object
9428 var f = function(){};
9429 f.prototype = El.prototype;
9431 docEl.dom = document;
9439 El.uncache = function(el){
9440 for(var i = 0, a = arguments, len = a.length; i < len; i++) {
9442 delete El.cache[a[i].id || a[i]];
9448 // Garbage collection - uncache elements/purge listeners on orphaned elements
9449 // so we don't hold a reference and cause the browser to retain them
9450 El.garbageCollect = function(){
9451 if(!Roo.enableGarbageCollector){
9452 clearInterval(El.collectorThread);
9455 for(var eid in El.cache){
9456 var el = El.cache[eid], d = el.dom;
9457 // -------------------------------------------------------
9458 // Determining what is garbage:
9459 // -------------------------------------------------------
9461 // dom node is null, definitely garbage
9462 // -------------------------------------------------------
9464 // no parentNode == direct orphan, definitely garbage
9465 // -------------------------------------------------------
9466 // !d.offsetParent && !document.getElementById(eid)
9467 // display none elements have no offsetParent so we will
9468 // also try to look it up by it's id. However, check
9469 // offsetParent first so we don't do unneeded lookups.
9470 // This enables collection of elements that are not orphans
9471 // directly, but somewhere up the line they have an orphan
9473 // -------------------------------------------------------
9474 if(!d || !d.parentNode || (!d.offsetParent && !document.getElementById(eid))){
9475 delete El.cache[eid];
9476 if(d && Roo.enableListenerCollection){
9482 El.collectorThreadId = setInterval(El.garbageCollect, 30000);
9486 El.Flyweight = function(dom){
9489 El.Flyweight.prototype = El.prototype;
9491 El._flyweights = {};
9493 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9494 * the dom node can be overwritten by other code.
9495 * @param {String/HTMLElement} el The dom node or id
9496 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9497 * prevent conflicts (e.g. internally Roo uses "_internal")
9499 * @return {Element} The shared Element object
9501 El.fly = function(el, named){
9502 named = named || '_global';
9503 el = Roo.getDom(el);
9507 if(!El._flyweights[named]){
9508 El._flyweights[named] = new El.Flyweight();
9510 El._flyweights[named].dom = el;
9511 return El._flyweights[named];
9515 * Static method to retrieve Element objects. Uses simple caching to consistently return the same object.
9516 * Automatically fixes if an object was recreated with the same id via AJAX or DOM.
9517 * Shorthand of {@link Roo.Element#get}
9518 * @param {String/HTMLElement/Element} el The id of the node, a DOM Node or an existing Element.
9519 * @return {Element} The Element object
9525 * Gets the globally shared flyweight Element, with the passed node as the active element. Do not store a reference to this element -
9526 * the dom node can be overwritten by other code.
9527 * Shorthand of {@link Roo.Element#fly}
9528 * @param {String/HTMLElement} el The dom node or id
9529 * @param {String} named (optional) Allows for creation of named reusable flyweights to
9530 * prevent conflicts (e.g. internally Roo uses "_internal")
9532 * @return {Element} The shared Element object
9538 // speedy lookup for elements never to box adjust
9539 var noBoxAdjust = Roo.isStrict ? {
9542 input:1, select:1, textarea:1
9544 if(Roo.isIE || Roo.isGecko){
9545 noBoxAdjust['button'] = 1;
9549 Roo.EventManager.on(window, 'unload', function(){
9551 delete El._flyweights;
9559 Roo.Element.selectorFunction = Roo.DomQuery.select;
9562 Roo.Element.select = function(selector, unique, root){
9564 if(typeof selector == "string"){
9565 els = Roo.Element.selectorFunction(selector, root);
9566 }else if(selector.length !== undefined){
9569 throw "Invalid selector";
9571 if(unique === true){
9572 return new Roo.CompositeElement(els);
9574 return new Roo.CompositeElementLite(els);
9578 * Selects elements based on the passed CSS selector to enable working on them as 1.
9579 * @param {String/Array} selector The CSS selector or an array of elements
9580 * @param {Boolean} unique (optional) true to create a unique Roo.Element for each element (defaults to a shared flyweight object)
9581 * @param {HTMLElement/String} root (optional) The root element of the query or id of the root
9582 * @return {CompositeElementLite/CompositeElement}
9586 Roo.select = Roo.Element.select;
9603 * Ext JS Library 1.1.1
9604 * Copyright(c) 2006-2007, Ext JS, LLC.
9606 * Originally Released Under LGPL - original licence link has changed is not relivant.
9609 * <script type="text/javascript">
9614 //Notifies Element that fx methods are available
9615 Roo.enableFx = true;
9619 * <p>A class to provide basic animation and visual effects support. <b>Note:</b> This class is automatically applied
9620 * to the {@link Roo.Element} interface when included, so all effects calls should be performed via Element.
9621 * Conversely, since the effects are not actually defined in Element, Roo.Fx <b>must</b> be included in order for the
9622 * Element effects to work.</p><br/>
9624 * <p>It is important to note that although the Fx methods and many non-Fx Element methods support "method chaining" in that
9625 * they return the Element object itself as the method return value, it is not always possible to mix the two in a single
9626 * method chain. The Fx methods use an internal effects queue so that each effect can be properly timed and sequenced.
9627 * Non-Fx methods, on the other hand, have no such internal queueing and will always execute immediately. For this reason,
9628 * while it may be possible to mix certain Fx and non-Fx method calls in a single chain, it may not always provide the
9629 * expected results and should be done with care.</p><br/>
9631 * <p>Motion effects support 8-way anchoring, meaning that you can choose one of 8 different anchor points on the Element
9632 * that will serve as either the start or end point of the animation. Following are all of the supported anchor positions:</p>
9635 ----- -----------------------------
9636 tl The top left corner
9637 t The center of the top edge
9638 tr The top right corner
9639 l The center of the left edge
9640 r The center of the right edge
9641 bl The bottom left corner
9642 b The center of the bottom edge
9643 br The bottom right corner
9645 * <b>Although some Fx methods accept specific custom config parameters, the ones shown in the Config Options section
9646 * below are common options that can be passed to any Fx method.</b>
9647 * @cfg {Function} callback A function called when the effect is finished
9648 * @cfg {Object} scope The scope of the effect function
9649 * @cfg {String} easing A valid Easing value for the effect
9650 * @cfg {String} afterCls A css class to apply after the effect
9651 * @cfg {Number} duration The length of time (in seconds) that the effect should last
9652 * @cfg {Boolean} remove Whether the Element should be removed from the DOM and destroyed after the effect finishes
9653 * @cfg {Boolean} useDisplay Whether to use the <i>display</i> CSS property instead of <i>visibility</i> when hiding Elements (only applies to
9654 * effects that end with the element being visually hidden, ignored otherwise)
9655 * @cfg {String/Object/Function} afterStyle A style specification string, e.g. "width:100px", or an object in the form {width:"100px"}, or
9656 * a function which returns such a specification that will be applied to the Element after the effect finishes
9657 * @cfg {Boolean} block Whether the effect should block other effects from queueing while it runs
9658 * @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
9659 * @cfg {Boolean} stopFx Whether subsequent effects should be stopped and removed after the current effect finishes
9663 * Slides the element into view. An anchor point can be optionally passed to set the point of
9664 * origin for the slide effect. This function automatically handles wrapping the element with
9665 * a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9668 // default: slide the element in from the top
9671 // custom: slide the element in from the right with a 2-second duration
9672 el.slideIn('r', { duration: 2 });
9674 // common config options shown with default values
9680 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9681 * @param {Object} options (optional) Object literal with any of the Fx config options
9682 * @return {Roo.Element} The Element
9684 slideIn : function(anchor, o){
9685 var el = this.getFxEl();
9688 el.queueFx(o, function(){
9690 anchor = anchor || "t";
9692 // fix display to visibility
9695 // restore values after effect
9696 var r = this.getFxRestore();
9697 var b = this.getBox();
9698 // fixed size for slide
9702 var wrap = this.fxWrap(r.pos, o, "hidden");
9704 var st = this.dom.style;
9705 st.visibility = "visible";
9706 st.position = "absolute";
9708 // clear out temp styles after slide and unwrap
9709 var after = function(){
9710 el.fxUnwrap(wrap, r.pos, o);
9712 st.height = r.height;
9715 // time to calc the positions
9716 var a, pt = {to: [b.x, b.y]}, bw = {to: b.width}, bh = {to: b.height};
9718 switch(anchor.toLowerCase()){
9720 wrap.setSize(b.width, 0);
9721 st.left = st.bottom = "0";
9725 wrap.setSize(0, b.height);
9726 st.right = st.top = "0";
9730 wrap.setSize(0, b.height);
9732 st.left = st.top = "0";
9733 a = {width: bw, points: pt};
9736 wrap.setSize(b.width, 0);
9737 wrap.setY(b.bottom);
9738 st.left = st.top = "0";
9739 a = {height: bh, points: pt};
9743 st.right = st.bottom = "0";
9744 a = {width: bw, height: bh};
9748 wrap.setY(b.y+b.height);
9749 st.right = st.top = "0";
9750 a = {width: bw, height: bh, points: pt};
9754 wrap.setXY([b.right, b.bottom]);
9755 st.left = st.top = "0";
9756 a = {width: bw, height: bh, points: pt};
9760 wrap.setX(b.x+b.width);
9761 st.left = st.bottom = "0";
9762 a = {width: bw, height: bh, points: pt};
9765 this.dom.style.visibility = "visible";
9768 arguments.callee.anim = wrap.fxanim(a,
9778 * Slides the element out of view. An anchor point can be optionally passed to set the end point
9779 * for the slide effect. When the effect is completed, the element will be hidden (visibility =
9780 * 'hidden') but block elements will still take up space in the document. The element must be removed
9781 * from the DOM using the 'remove' config option if desired. This function automatically handles
9782 * wrapping the element with a fixed-size container if needed. See the Fx class overview for valid anchor point options.
9785 // default: slide the element out to the top
9788 // custom: slide the element out to the right with a 2-second duration
9789 el.slideOut('r', { duration: 2 });
9791 // common config options shown with default values
9799 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to top: 't')
9800 * @param {Object} options (optional) Object literal with any of the Fx config options
9801 * @return {Roo.Element} The Element
9803 slideOut : function(anchor, o){
9804 var el = this.getFxEl();
9807 el.queueFx(o, function(){
9809 anchor = anchor || "t";
9811 // restore values after effect
9812 var r = this.getFxRestore();
9814 var b = this.getBox();
9815 // fixed size for slide
9819 var wrap = this.fxWrap(r.pos, o, "visible");
9821 var st = this.dom.style;
9822 st.visibility = "visible";
9823 st.position = "absolute";
9827 var after = function(){
9829 el.setDisplayed(false);
9834 el.fxUnwrap(wrap, r.pos, o);
9837 st.height = r.height;
9842 var a, zero = {to: 0};
9843 switch(anchor.toLowerCase()){
9845 st.left = st.bottom = "0";
9849 st.right = st.top = "0";
9853 st.left = st.top = "0";
9854 a = {width: zero, points: {to:[b.right, b.y]}};
9857 st.left = st.top = "0";
9858 a = {height: zero, points: {to:[b.x, b.bottom]}};
9861 st.right = st.bottom = "0";
9862 a = {width: zero, height: zero};
9865 st.right = st.top = "0";
9866 a = {width: zero, height: zero, points: {to:[b.x, b.bottom]}};
9869 st.left = st.top = "0";
9870 a = {width: zero, height: zero, points: {to:[b.x+b.width, b.bottom]}};
9873 st.left = st.bottom = "0";
9874 a = {width: zero, height: zero, points: {to:[b.right, b.y]}};
9878 arguments.callee.anim = wrap.fxanim(a,
9888 * Fades the element out while slowly expanding it in all directions. When the effect is completed, the
9889 * element will be hidden (visibility = 'hidden') but block elements will still take up space in the document.
9890 * The element must be removed from the DOM using the 'remove' config option if desired.
9896 // common config options shown with default values
9904 * @param {Object} options (optional) Object literal with any of the Fx config options
9905 * @return {Roo.Element} The Element
9908 var el = this.getFxEl();
9911 el.queueFx(o, function(){
9912 this.clearOpacity();
9915 // restore values after effect
9916 var r = this.getFxRestore();
9917 var st = this.dom.style;
9919 var after = function(){
9921 el.setDisplayed(false);
9928 el.setPositioning(r.pos);
9930 st.height = r.height;
9935 var width = this.getWidth();
9936 var height = this.getHeight();
9938 arguments.callee.anim = this.fxanim({
9939 width : {to: this.adjustWidth(width * 2)},
9940 height : {to: this.adjustHeight(height * 2)},
9941 points : {by: [-(width * .5), -(height * .5)]},
9943 fontSize: {to:200, unit: "%"}
9954 * Blinks the element as if it was clicked and then collapses on its center (similar to switching off a television).
9955 * When the effect is completed, the element will be hidden (visibility = 'hidden') but block elements will still
9956 * take up space in the document. The element must be removed from the DOM using the 'remove' config option if desired.
9962 // all config options shown with default values
9970 * @param {Object} options (optional) Object literal with any of the Fx config options
9971 * @return {Roo.Element} The Element
9973 switchOff : function(o){
9974 var el = this.getFxEl();
9977 el.queueFx(o, function(){
9978 this.clearOpacity();
9981 // restore values after effect
9982 var r = this.getFxRestore();
9983 var st = this.dom.style;
9985 var after = function(){
9987 el.setDisplayed(false);
9993 el.setPositioning(r.pos);
9995 st.height = r.height;
10000 this.fxanim({opacity:{to:0.3}}, null, null, .1, null, function(){
10001 this.clearOpacity();
10005 points:{by:[0, this.getHeight() * .5]}
10006 }, o, 'motion', 0.3, 'easeIn', after);
10007 }).defer(100, this);
10014 * Highlights the Element by setting a color (applies to the background-color by default, but can be
10015 * changed using the "attr" config option) and then fading back to the original color. If no original
10016 * color is available, you should provide the "endColor" config option which will be cleared after the animation.
10019 // default: highlight background to yellow
10022 // custom: highlight foreground text to blue for 2 seconds
10023 el.highlight("0000ff", { attr: 'color', duration: 2 });
10025 // common config options shown with default values
10026 el.highlight("ffff9c", {
10027 attr: "background-color", //can be any valid CSS property (attribute) that supports a color value
10028 endColor: (current color) or "ffffff",
10033 * @param {String} color (optional) The highlight color. Should be a 6 char hex color without the leading # (defaults to yellow: 'ffff9c')
10034 * @param {Object} options (optional) Object literal with any of the Fx config options
10035 * @return {Roo.Element} The Element
10037 highlight : function(color, o){
10038 var el = this.getFxEl();
10041 el.queueFx(o, function(){
10042 color = color || "ffff9c";
10043 attr = o.attr || "backgroundColor";
10045 this.clearOpacity();
10048 var origColor = this.getColor(attr);
10049 var restoreColor = this.dom.style[attr];
10050 endColor = (o.endColor || origColor) || "ffffff";
10052 var after = function(){
10053 el.dom.style[attr] = restoreColor;
10058 a[attr] = {from: color, to: endColor};
10059 arguments.callee.anim = this.fxanim(a,
10069 * Shows a ripple of exploding, attenuating borders to draw attention to an Element.
10072 // default: a single light blue ripple
10075 // custom: 3 red ripples lasting 3 seconds total
10076 el.frame("ff0000", 3, { duration: 3 });
10078 // common config options shown with default values
10079 el.frame("C3DAF9", 1, {
10080 duration: 1 //duration of entire animation (not each individual ripple)
10081 // Note: Easing is not configurable and will be ignored if included
10084 * @param {String} color (optional) The color of the border. Should be a 6 char hex color without the leading # (defaults to light blue: 'C3DAF9').
10085 * @param {Number} count (optional) The number of ripples to display (defaults to 1)
10086 * @param {Object} options (optional) Object literal with any of the Fx config options
10087 * @return {Roo.Element} The Element
10089 frame : function(color, count, o){
10090 var el = this.getFxEl();
10093 el.queueFx(o, function(){
10094 color = color || "#C3DAF9";
10095 if(color.length == 6){
10096 color = "#" + color;
10098 count = count || 1;
10099 duration = o.duration || 1;
10102 var b = this.getBox();
10103 var animFn = function(){
10104 var proxy = this.createProxy({
10107 visbility:"hidden",
10108 position:"absolute",
10109 "z-index":"35000", // yee haw
10110 border:"0px solid " + color
10113 var scale = Roo.isBorderBox ? 2 : 1;
10115 top:{from:b.y, to:b.y - 20},
10116 left:{from:b.x, to:b.x - 20},
10117 borderWidth:{from:0, to:10},
10118 opacity:{from:1, to:0},
10119 height:{from:b.height, to:(b.height + (20*scale))},
10120 width:{from:b.width, to:(b.width + (20*scale))}
10121 }, duration, function(){
10125 animFn.defer((duration/2)*1000, this);
10136 * Creates a pause before any subsequent queued effects begin. If there are
10137 * no effects queued after the pause it will have no effect.
10142 * @param {Number} seconds The length of time to pause (in seconds)
10143 * @return {Roo.Element} The Element
10145 pause : function(seconds){
10146 var el = this.getFxEl();
10149 el.queueFx(o, function(){
10150 setTimeout(function(){
10152 }, seconds * 1000);
10158 * Fade an element in (from transparent to opaque). The ending opacity can be specified
10159 * using the "endOpacity" config option.
10162 // default: fade in from opacity 0 to 100%
10165 // custom: fade in from opacity 0 to 75% over 2 seconds
10166 el.fadeIn({ endOpacity: .75, duration: 2});
10168 // common config options shown with default values
10170 endOpacity: 1, //can be any value between 0 and 1 (e.g. .5)
10175 * @param {Object} options (optional) Object literal with any of the Fx config options
10176 * @return {Roo.Element} The Element
10178 fadeIn : function(o){
10179 var el = this.getFxEl();
10181 el.queueFx(o, function(){
10182 this.setOpacity(0);
10184 this.dom.style.visibility = 'visible';
10185 var to = o.endOpacity || 1;
10186 arguments.callee.anim = this.fxanim({opacity:{to:to}},
10187 o, null, .5, "easeOut", function(){
10189 this.clearOpacity();
10198 * Fade an element out (from opaque to transparent). The ending opacity can be specified
10199 * using the "endOpacity" config option.
10202 // default: fade out from the element's current opacity to 0
10205 // custom: fade out from the element's current opacity to 25% over 2 seconds
10206 el.fadeOut({ endOpacity: .25, duration: 2});
10208 // common config options shown with default values
10210 endOpacity: 0, //can be any value between 0 and 1 (e.g. .5)
10217 * @param {Object} options (optional) Object literal with any of the Fx config options
10218 * @return {Roo.Element} The Element
10220 fadeOut : function(o){
10221 var el = this.getFxEl();
10223 el.queueFx(o, function(){
10224 arguments.callee.anim = this.fxanim({opacity:{to:o.endOpacity || 0}},
10225 o, null, .5, "easeOut", function(){
10226 if(this.visibilityMode == Roo.Element.DISPLAY || o.useDisplay){
10227 this.dom.style.display = "none";
10229 this.dom.style.visibility = "hidden";
10231 this.clearOpacity();
10239 * Animates the transition of an element's dimensions from a starting height/width
10240 * to an ending height/width.
10243 // change height and width to 100x100 pixels
10244 el.scale(100, 100);
10246 // common config options shown with default values. The height and width will default to
10247 // the element's existing values if passed as null.
10250 [element's height], {
10255 * @param {Number} width The new width (pass undefined to keep the original width)
10256 * @param {Number} height The new height (pass undefined to keep the original height)
10257 * @param {Object} options (optional) Object literal with any of the Fx config options
10258 * @return {Roo.Element} The Element
10260 scale : function(w, h, o){
10261 this.shift(Roo.apply({}, o, {
10269 * Animates the transition of any combination of an element's dimensions, xy position and/or opacity.
10270 * Any of these properties not specified in the config object will not be changed. This effect
10271 * requires that at least one new dimension, position or opacity setting must be passed in on
10272 * the config object in order for the function to have any effect.
10275 // slide the element horizontally to x position 200 while changing the height and opacity
10276 el.shift({ x: 200, height: 50, opacity: .8 });
10278 // common config options shown with default values.
10280 width: [element's width],
10281 height: [element's height],
10282 x: [element's x position],
10283 y: [element's y position],
10284 opacity: [element's opacity],
10289 * @param {Object} options Object literal with any of the Fx config options
10290 * @return {Roo.Element} The Element
10292 shift : function(o){
10293 var el = this.getFxEl();
10295 el.queueFx(o, function(){
10296 var a = {}, w = o.width, h = o.height, x = o.x, y = o.y, op = o.opacity;
10297 if(w !== undefined){
10298 a.width = {to: this.adjustWidth(w)};
10300 if(h !== undefined){
10301 a.height = {to: this.adjustHeight(h)};
10303 if(x !== undefined || y !== undefined){
10305 x !== undefined ? x : this.getX(),
10306 y !== undefined ? y : this.getY()
10309 if(op !== undefined){
10310 a.opacity = {to: op};
10312 if(o.xy !== undefined){
10313 a.points = {to: o.xy};
10315 arguments.callee.anim = this.fxanim(a,
10316 o, 'motion', .35, "easeOut", function(){
10324 * Slides the element while fading it out of view. An anchor point can be optionally passed to set the
10325 * ending point of the effect.
10328 // default: slide the element downward while fading out
10331 // custom: slide the element out to the right with a 2-second duration
10332 el.ghost('r', { duration: 2 });
10334 // common config options shown with default values
10342 * @param {String} anchor (optional) One of the valid Fx anchor positions (defaults to bottom: 'b')
10343 * @param {Object} options (optional) Object literal with any of the Fx config options
10344 * @return {Roo.Element} The Element
10346 ghost : function(anchor, o){
10347 var el = this.getFxEl();
10350 el.queueFx(o, function(){
10351 anchor = anchor || "b";
10353 // restore values after effect
10354 var r = this.getFxRestore();
10355 var w = this.getWidth(),
10356 h = this.getHeight();
10358 var st = this.dom.style;
10360 var after = function(){
10362 el.setDisplayed(false);
10368 el.setPositioning(r.pos);
10369 st.width = r.width;
10370 st.height = r.height;
10375 var a = {opacity: {to: 0}, points: {}}, pt = a.points;
10376 switch(anchor.toLowerCase()){
10403 arguments.callee.anim = this.fxanim(a,
10413 * Ensures that all effects queued after syncFx is called on the element are
10414 * run concurrently. This is the opposite of {@link #sequenceFx}.
10415 * @return {Roo.Element} The Element
10417 syncFx : function(){
10418 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10427 * Ensures that all effects queued after sequenceFx is called on the element are
10428 * run in sequence. This is the opposite of {@link #syncFx}.
10429 * @return {Roo.Element} The Element
10431 sequenceFx : function(){
10432 this.fxDefaults = Roo.apply(this.fxDefaults || {}, {
10434 concurrent : false,
10441 nextFx : function(){
10442 var ef = this.fxQueue[0];
10449 * Returns true if the element has any effects actively running or queued, else returns false.
10450 * @return {Boolean} True if element has active effects, else false
10452 hasActiveFx : function(){
10453 return this.fxQueue && this.fxQueue[0];
10457 * Stops any running effects and clears the element's internal effects queue if it contains
10458 * any additional effects that haven't started yet.
10459 * @return {Roo.Element} The Element
10461 stopFx : function(){
10462 if(this.hasActiveFx()){
10463 var cur = this.fxQueue[0];
10464 if(cur && cur.anim && cur.anim.isAnimated()){
10465 this.fxQueue = [cur]; // clear out others
10466 cur.anim.stop(true);
10473 beforeFx : function(o){
10474 if(this.hasActiveFx() && !o.concurrent){
10485 * Returns true if the element is currently blocking so that no other effect can be queued
10486 * until this effect is finished, else returns false if blocking is not set. This is commonly
10487 * used to ensure that an effect initiated by a user action runs to completion prior to the
10488 * same effect being restarted (e.g., firing only one effect even if the user clicks several times).
10489 * @return {Boolean} True if blocking, else false
10491 hasFxBlock : function(){
10492 var q = this.fxQueue;
10493 return q && q[0] && q[0].block;
10497 queueFx : function(o, fn){
10501 if(!this.hasFxBlock()){
10502 Roo.applyIf(o, this.fxDefaults);
10504 var run = this.beforeFx(o);
10505 fn.block = o.block;
10506 this.fxQueue.push(fn);
10518 fxWrap : function(pos, o, vis){
10520 if(!o.wrap || !(wrap = Roo.get(o.wrap))){
10523 wrapXY = this.getXY();
10525 var div = document.createElement("div");
10526 div.style.visibility = vis;
10527 wrap = Roo.get(this.dom.parentNode.insertBefore(div, this.dom));
10528 wrap.setPositioning(pos);
10529 if(wrap.getStyle("position") == "static"){
10530 wrap.position("relative");
10532 this.clearPositioning('auto');
10534 wrap.dom.appendChild(this.dom);
10536 wrap.setXY(wrapXY);
10543 fxUnwrap : function(wrap, pos, o){
10544 this.clearPositioning();
10545 this.setPositioning(pos);
10547 wrap.dom.parentNode.insertBefore(this.dom, wrap.dom);
10553 getFxRestore : function(){
10554 var st = this.dom.style;
10555 return {pos: this.getPositioning(), width: st.width, height : st.height};
10559 afterFx : function(o){
10561 this.applyStyles(o.afterStyle);
10564 this.addClass(o.afterCls);
10566 if(o.remove === true){
10569 Roo.callback(o.callback, o.scope, [this]);
10571 this.fxQueue.shift();
10577 getFxEl : function(){ // support for composite element fx
10578 return Roo.get(this.dom);
10582 fxanim : function(args, opt, animType, defaultDur, defaultEase, cb){
10583 animType = animType || 'run';
10585 var anim = Roo.lib.Anim[animType](
10587 (opt.duration || defaultDur) || .35,
10588 (opt.easing || defaultEase) || 'easeOut',
10590 Roo.callback(cb, this);
10599 // backwords compat
10600 Roo.Fx.resize = Roo.Fx.scale;
10602 //When included, Roo.Fx is automatically applied to Element so that all basic
10603 //effects are available directly via the Element API
10604 Roo.apply(Roo.Element.prototype, Roo.Fx);/*
10606 * Ext JS Library 1.1.1
10607 * Copyright(c) 2006-2007, Ext JS, LLC.
10609 * Originally Released Under LGPL - original licence link has changed is not relivant.
10612 * <script type="text/javascript">
10617 * @class Roo.CompositeElement
10618 * Standard composite class. Creates a Roo.Element for every element in the collection.
10620 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10621 * actions will be performed on all the elements in this collection.</b>
10623 * All methods return <i>this</i> and can be chained.
10625 var els = Roo.select("#some-el div.some-class", true);
10626 // or select directly from an existing element
10627 var el = Roo.get('some-el');
10628 el.select('div.some-class', true);
10630 els.setWidth(100); // all elements become 100 width
10631 els.hide(true); // all elements fade out and hide
10633 els.setWidth(100).hide(true);
10636 Roo.CompositeElement = function(els){
10637 this.elements = [];
10638 this.addElements(els);
10640 Roo.CompositeElement.prototype = {
10642 addElements : function(els){
10643 if(!els) return this;
10644 if(typeof els == "string"){
10645 els = Roo.Element.selectorFunction(els);
10647 var yels = this.elements;
10648 var index = yels.length-1;
10649 for(var i = 0, len = els.length; i < len; i++) {
10650 yels[++index] = Roo.get(els[i]);
10656 * Clears this composite and adds the elements returned by the passed selector.
10657 * @param {String/Array} els A string CSS selector, an array of elements or an element
10658 * @return {CompositeElement} this
10660 fill : function(els){
10661 this.elements = [];
10667 * Filters this composite to only elements that match the passed selector.
10668 * @param {String} selector A string CSS selector
10669 * @return {CompositeElement} this
10671 filter : function(selector){
10673 this.each(function(el){
10674 if(el.is(selector)){
10675 els[els.length] = el.dom;
10682 invoke : function(fn, args){
10683 var els = this.elements;
10684 for(var i = 0, len = els.length; i < len; i++) {
10685 Roo.Element.prototype[fn].apply(els[i], args);
10690 * Adds elements to this composite.
10691 * @param {String/Array} els A string CSS selector, an array of elements or an element
10692 * @return {CompositeElement} this
10694 add : function(els){
10695 if(typeof els == "string"){
10696 this.addElements(Roo.Element.selectorFunction(els));
10697 }else if(els.length !== undefined){
10698 this.addElements(els);
10700 this.addElements([els]);
10705 * Calls the passed function passing (el, this, index) for each element in this composite.
10706 * @param {Function} fn The function to call
10707 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10708 * @return {CompositeElement} this
10710 each : function(fn, scope){
10711 var els = this.elements;
10712 for(var i = 0, len = els.length; i < len; i++){
10713 if(fn.call(scope || els[i], els[i], this, i) === false) {
10721 * Returns the Element object at the specified index
10722 * @param {Number} index
10723 * @return {Roo.Element}
10725 item : function(index){
10726 return this.elements[index] || null;
10730 * Returns the first Element
10731 * @return {Roo.Element}
10733 first : function(){
10734 return this.item(0);
10738 * Returns the last Element
10739 * @return {Roo.Element}
10742 return this.item(this.elements.length-1);
10746 * Returns the number of elements in this composite
10749 getCount : function(){
10750 return this.elements.length;
10754 * Returns true if this composite contains the passed element
10757 contains : function(el){
10758 return this.indexOf(el) !== -1;
10762 * Returns true if this composite contains the passed element
10765 indexOf : function(el){
10766 return this.elements.indexOf(Roo.get(el));
10771 * Removes the specified element(s).
10772 * @param {Mixed} el The id of an element, the Element itself, the index of the element in this composite
10773 * or an array of any of those.
10774 * @param {Boolean} removeDom (optional) True to also remove the element from the document
10775 * @return {CompositeElement} this
10777 removeElement : function(el, removeDom){
10778 if(el instanceof Array){
10779 for(var i = 0, len = el.length; i < len; i++){
10780 this.removeElement(el[i]);
10784 var index = typeof el == 'number' ? el : this.indexOf(el);
10787 var d = this.elements[index];
10791 d.parentNode.removeChild(d);
10794 this.elements.splice(index, 1);
10800 * Replaces the specified element with the passed element.
10801 * @param {String/HTMLElement/Element/Number} el The id of an element, the Element itself, the index of the element in this composite
10803 * @param {String/HTMLElement/Element} replacement The id of an element or the Element itself.
10804 * @param {Boolean} domReplace (Optional) True to remove and replace the element in the document too.
10805 * @return {CompositeElement} this
10807 replaceElement : function(el, replacement, domReplace){
10808 var index = typeof el == 'number' ? el : this.indexOf(el);
10811 this.elements[index].replaceWith(replacement);
10813 this.elements.splice(index, 1, Roo.get(replacement))
10820 * Removes all elements.
10822 clear : function(){
10823 this.elements = [];
10827 Roo.CompositeElement.createCall = function(proto, fnName){
10828 if(!proto[fnName]){
10829 proto[fnName] = function(){
10830 return this.invoke(fnName, arguments);
10834 for(var fnName in Roo.Element.prototype){
10835 if(typeof Roo.Element.prototype[fnName] == "function"){
10836 Roo.CompositeElement.createCall(Roo.CompositeElement.prototype, fnName);
10842 * Ext JS Library 1.1.1
10843 * Copyright(c) 2006-2007, Ext JS, LLC.
10845 * Originally Released Under LGPL - original licence link has changed is not relivant.
10848 * <script type="text/javascript">
10852 * @class Roo.CompositeElementLite
10853 * @extends Roo.CompositeElement
10854 * Flyweight composite class. Reuses the same Roo.Element for element operations.
10856 var els = Roo.select("#some-el div.some-class");
10857 // or select directly from an existing element
10858 var el = Roo.get('some-el');
10859 el.select('div.some-class');
10861 els.setWidth(100); // all elements become 100 width
10862 els.hide(true); // all elements fade out and hide
10864 els.setWidth(100).hide(true);
10865 </code></pre><br><br>
10866 * <b>NOTE: Although they are not listed, this class supports all of the set/update methods of Roo.Element. All Roo.Element
10867 * actions will be performed on all the elements in this collection.</b>
10869 Roo.CompositeElementLite = function(els){
10870 Roo.CompositeElementLite.superclass.constructor.call(this, els);
10871 this.el = new Roo.Element.Flyweight();
10873 Roo.extend(Roo.CompositeElementLite, Roo.CompositeElement, {
10874 addElements : function(els){
10876 if(els instanceof Array){
10877 this.elements = this.elements.concat(els);
10879 var yels = this.elements;
10880 var index = yels.length-1;
10881 for(var i = 0, len = els.length; i < len; i++) {
10882 yels[++index] = els[i];
10888 invoke : function(fn, args){
10889 var els = this.elements;
10891 for(var i = 0, len = els.length; i < len; i++) {
10893 Roo.Element.prototype[fn].apply(el, args);
10898 * Returns a flyweight Element of the dom element object at the specified index
10899 * @param {Number} index
10900 * @return {Roo.Element}
10902 item : function(index){
10903 if(!this.elements[index]){
10906 this.el.dom = this.elements[index];
10910 // fixes scope with flyweight
10911 addListener : function(eventName, handler, scope, opt){
10912 var els = this.elements;
10913 for(var i = 0, len = els.length; i < len; i++) {
10914 Roo.EventManager.on(els[i], eventName, handler, scope || els[i], opt);
10920 * Calls the passed function passing (el, this, index) for each element in this composite. <b>The element
10921 * passed is the flyweight (shared) Roo.Element instance, so if you require a
10922 * a reference to the dom node, use el.dom.</b>
10923 * @param {Function} fn The function to call
10924 * @param {Object} scope (optional) The <i>this</i> object (defaults to the element)
10925 * @return {CompositeElement} this
10927 each : function(fn, scope){
10928 var els = this.elements;
10930 for(var i = 0, len = els.length; i < len; i++){
10932 if(fn.call(scope || el, el, this, i) === false){
10939 indexOf : function(el){
10940 return this.elements.indexOf(Roo.getDom(el));
10943 replaceElement : function(el, replacement, domReplace){
10944 var index = typeof el == 'number' ? el : this.indexOf(el);
10946 replacement = Roo.getDom(replacement);
10948 var d = this.elements[index];
10949 d.parentNode.insertBefore(replacement, d);
10950 d.parentNode.removeChild(d);
10952 this.elements.splice(index, 1, replacement);
10957 Roo.CompositeElementLite.prototype.on = Roo.CompositeElementLite.prototype.addListener;
10961 * Ext JS Library 1.1.1
10962 * Copyright(c) 2006-2007, Ext JS, LLC.
10964 * Originally Released Under LGPL - original licence link has changed is not relivant.
10967 * <script type="text/javascript">
10973 * @class Roo.data.Connection
10974 * @extends Roo.util.Observable
10975 * The class encapsulates a connection to the page's originating domain, allowing requests to be made
10976 * either to a configured URL, or to a URL specified at request time.<br><br>
10978 * Requests made by this class are asynchronous, and will return immediately. No data from
10979 * the server will be available to the statement immediately following the {@link #request} call.
10980 * To process returned data, use a callback in the request options object, or an event listener.</p><br>
10982 * Note: If you are doing a file upload, you will not get a normal response object sent back to
10983 * your callback or event handler. Since the upload is handled via in IFRAME, there is no XMLHttpRequest.
10984 * The response object is created using the innerHTML of the IFRAME's document as the responseText
10985 * property and, if present, the IFRAME's XML document as the responseXML property.</p><br>
10986 * This means that a valid XML or HTML document must be returned. If JSON data is required, it is suggested
10987 * that it be placed either inside a <textarea> in an HTML document and retrieved from the responseText
10988 * using a regex, or inside a CDATA section in an XML document and retrieved from the responseXML using
10989 * standard DOM methods.
10991 * @param {Object} config a configuration object.
10993 Roo.data.Connection = function(config){
10994 Roo.apply(this, config);
10997 * @event beforerequest
10998 * Fires before a network request is made to retrieve a data object.
10999 * @param {Connection} conn This Connection object.
11000 * @param {Object} options The options config object passed to the {@link #request} method.
11002 "beforerequest" : true,
11004 * @event requestcomplete
11005 * Fires if the request was successfully completed.
11006 * @param {Connection} conn This Connection object.
11007 * @param {Object} response The XHR object containing the response data.
11008 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11009 * @param {Object} options The options config object passed to the {@link #request} method.
11011 "requestcomplete" : true,
11013 * @event requestexception
11014 * Fires if an error HTTP status was returned from the server.
11015 * See {@link http://www.w3.org/Protocols/rfc2616/rfc2616-sec10.html} for details of HTTP status codes.
11016 * @param {Connection} conn This Connection object.
11017 * @param {Object} response The XHR object containing the response data.
11018 * See {@link http://www.w3.org/TR/XMLHttpRequest/} for details.
11019 * @param {Object} options The options config object passed to the {@link #request} method.
11021 "requestexception" : true
11023 Roo.data.Connection.superclass.constructor.call(this);
11026 Roo.extend(Roo.data.Connection, Roo.util.Observable, {
11028 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
11031 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
11032 * extra parameters to each request made by this object. (defaults to undefined)
11035 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
11036 * to each request made by this object. (defaults to undefined)
11039 * @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)
11042 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
11046 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
11052 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
11055 disableCaching: true,
11058 * Sends an HTTP request to a remote server.
11059 * @param {Object} options An object which may contain the following properties:<ul>
11060 * <li><b>url</b> {String} (Optional) The URL to which to send the request. Defaults to configured URL</li>
11061 * <li><b>params</b> {Object/String/Function} (Optional) An object containing properties which are used as parameters to the
11062 * request, a url encoded string or a function to call to get either.</li>
11063 * <li><b>method</b> {String} (Optional) The HTTP method to use for the request. Defaults to the configured method, or
11064 * if no method was configured, "GET" if no parameters are being sent, and "POST" if parameters are being sent.</li>
11065 * <li><b>callback</b> {Function} (Optional) The function to be called upon receipt of the HTTP response.
11066 * The callback is called regardless of success or failure and is passed the following parameters:<ul>
11067 * <li>options {Object} The parameter to the request call.</li>
11068 * <li>success {Boolean} True if the request succeeded.</li>
11069 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11071 * <li><b>success</b> {Function} (Optional) The function to be called upon success of the request.
11072 * The callback is passed the following parameters:<ul>
11073 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11074 * <li>options {Object} The parameter to the request call.</li>
11076 * <li><b>failure</b> {Function} (Optional) The function to be called upon failure of the request.
11077 * The callback is passed the following parameters:<ul>
11078 * <li>response {Object} The XMLHttpRequest object containing the response data.</li>
11079 * <li>options {Object} The parameter to the request call.</li>
11081 * <li><b>scope</b> {Object} (Optional) The scope in which to execute the callbacks: The "this" object
11082 * for the callback function. Defaults to the browser window.</li>
11083 * <li><b>form</b> {Object/String} (Optional) A form object or id to pull parameters from.</li>
11084 * <li><b>isUpload</b> {Boolean} (Optional) True if the form object is a file upload (will usually be automatically detected).</li>
11085 * <li><b>headers</b> {Object} (Optional) Request headers to set for the request.</li>
11086 * <li><b>xmlData</b> {Object} (Optional) XML document to use for the post. Note: This will be used instead of
11087 * params for the post data. Any params will be appended to the URL.</li>
11088 * <li><b>disableCaching</b> {Boolean} (Optional) True to add a unique cache-buster param to GET requests.</li>
11090 * @return {Number} transactionId
11092 request : function(o){
11093 if(this.fireEvent("beforerequest", this, o) !== false){
11096 if(typeof p == "function"){
11097 p = p.call(o.scope||window, o);
11099 if(typeof p == "object"){
11100 p = Roo.urlEncode(o.params);
11102 if(this.extraParams){
11103 var extras = Roo.urlEncode(this.extraParams);
11104 p = p ? (p + '&' + extras) : extras;
11107 var url = o.url || this.url;
11108 if(typeof url == 'function'){
11109 url = url.call(o.scope||window, o);
11113 var form = Roo.getDom(o.form);
11114 url = url || form.action;
11116 var enctype = form.getAttribute("enctype");
11117 if(o.isUpload || (enctype && enctype.toLowerCase() == 'multipart/form-data')){
11118 return this.doFormUpload(o, p, url);
11120 var f = Roo.lib.Ajax.serializeForm(form);
11121 p = p ? (p + '&' + f) : f;
11124 var hs = o.headers;
11125 if(this.defaultHeaders){
11126 hs = Roo.apply(hs || {}, this.defaultHeaders);
11133 success: this.handleResponse,
11134 failure: this.handleFailure,
11136 argument: {options: o},
11137 timeout : this.timeout
11140 var method = o.method||this.method||(p ? "POST" : "GET");
11142 if(method == 'GET' && (this.disableCaching && o.disableCaching !== false) || o.disableCaching === true){
11143 url += (url.indexOf('?') != -1 ? '&' : '?') + '_dc=' + (new Date().getTime());
11146 if(typeof o.autoAbort == 'boolean'){ // options gets top priority
11150 }else if(this.autoAbort !== false){
11154 if((method == 'GET' && p) || o.xmlData){
11155 url += (url.indexOf('?') != -1 ? '&' : '?') + p;
11158 this.transId = Roo.lib.Ajax.request(method, url, cb, p, o);
11159 return this.transId;
11161 Roo.callback(o.callback, o.scope, [o, null, null]);
11167 * Determine whether this object has a request outstanding.
11168 * @param {Number} transactionId (Optional) defaults to the last transaction
11169 * @return {Boolean} True if there is an outstanding request.
11171 isLoading : function(transId){
11173 return Roo.lib.Ajax.isCallInProgress(transId);
11175 return this.transId ? true : false;
11180 * Aborts any outstanding request.
11181 * @param {Number} transactionId (Optional) defaults to the last transaction
11183 abort : function(transId){
11184 if(transId || this.isLoading()){
11185 Roo.lib.Ajax.abort(transId || this.transId);
11190 handleResponse : function(response){
11191 this.transId = false;
11192 var options = response.argument.options;
11193 response.argument = options ? options.argument : null;
11194 this.fireEvent("requestcomplete", this, response, options);
11195 Roo.callback(options.success, options.scope, [response, options]);
11196 Roo.callback(options.callback, options.scope, [options, true, response]);
11200 handleFailure : function(response, e){
11201 this.transId = false;
11202 var options = response.argument.options;
11203 response.argument = options ? options.argument : null;
11204 this.fireEvent("requestexception", this, response, options, e);
11205 Roo.callback(options.failure, options.scope, [response, options]);
11206 Roo.callback(options.callback, options.scope, [options, false, response]);
11210 doFormUpload : function(o, ps, url){
11212 var frame = document.createElement('iframe');
11215 frame.className = 'x-hidden';
11217 frame.src = Roo.SSL_SECURE_URL;
11219 document.body.appendChild(frame);
11222 document.frames[id].name = id;
11225 var form = Roo.getDom(o.form);
11227 form.method = 'POST';
11228 form.enctype = form.encoding = 'multipart/form-data';
11234 if(ps){ // add dynamic params
11236 ps = Roo.urlDecode(ps, false);
11238 if(ps.hasOwnProperty(k)){
11239 hd = document.createElement('input');
11240 hd.type = 'hidden';
11243 form.appendChild(hd);
11250 var r = { // bogus response object
11255 r.argument = o ? o.argument : null;
11260 doc = frame.contentWindow.document;
11262 doc = (frame.contentDocument || window.frames[id].document);
11264 if(doc && doc.body){
11265 r.responseText = doc.body.innerHTML;
11267 if(doc && doc.XMLDocument){
11268 r.responseXML = doc.XMLDocument;
11270 r.responseXML = doc;
11277 Roo.EventManager.removeListener(frame, 'load', cb, this);
11279 this.fireEvent("requestcomplete", this, r, o);
11280 Roo.callback(o.success, o.scope, [r, o]);
11281 Roo.callback(o.callback, o.scope, [o, true, r]);
11283 setTimeout(function(){document.body.removeChild(frame);}, 100);
11286 Roo.EventManager.on(frame, 'load', cb, this);
11289 if(hiddens){ // remove dynamic params
11290 for(var i = 0, len = hiddens.length; i < len; i++){
11291 form.removeChild(hiddens[i]);
11299 * @extends Roo.data.Connection
11300 * Global Ajax request class.
11304 Roo.Ajax = new Roo.data.Connection({
11307 * @cfg {String} url @hide
11310 * @cfg {Object} extraParams @hide
11313 * @cfg {Object} defaultHeaders @hide
11316 * @cfg {String} method (Optional) @hide
11319 * @cfg {Number} timeout (Optional) @hide
11322 * @cfg {Boolean} autoAbort (Optional) @hide
11326 * @cfg {Boolean} disableCaching (Optional) @hide
11330 * @property disableCaching
11331 * True to add a unique cache-buster param to GET requests. (defaults to true)
11336 * The default URL to be used for requests to the server. (defaults to undefined)
11340 * @property extraParams
11341 * An object containing properties which are used as
11342 * extra parameters to each request made by this object. (defaults to undefined)
11346 * @property defaultHeaders
11347 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11352 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11356 * @property timeout
11357 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11362 * @property autoAbort
11363 * Whether a new request should abort any pending requests. (defaults to false)
11369 * Serialize the passed form into a url encoded string
11370 * @param {String/HTMLElement} form
11373 serializeForm : function(form){
11374 return Roo.lib.Ajax.serializeForm(form);
11378 * Ext JS Library 1.1.1
11379 * Copyright(c) 2006-2007, Ext JS, LLC.
11381 * Originally Released Under LGPL - original licence link has changed is not relivant.
11384 * <script type="text/javascript">
11389 * @extends Roo.data.Connection
11390 * Global Ajax request class.
11392 * @instanceOf Roo.data.Connection
11394 Roo.Ajax = new Roo.data.Connection({
11403 * @cfg {String} url @hide
11406 * @cfg {Object} extraParams @hide
11409 * @cfg {Object} defaultHeaders @hide
11412 * @cfg {String} method (Optional) @hide
11415 * @cfg {Number} timeout (Optional) @hide
11418 * @cfg {Boolean} autoAbort (Optional) @hide
11422 * @cfg {Boolean} disableCaching (Optional) @hide
11426 * @property disableCaching
11427 * True to add a unique cache-buster param to GET requests. (defaults to true)
11432 * The default URL to be used for requests to the server. (defaults to undefined)
11436 * @property extraParams
11437 * An object containing properties which are used as
11438 * extra parameters to each request made by this object. (defaults to undefined)
11442 * @property defaultHeaders
11443 * An object containing request headers which are added to each request made by this object. (defaults to undefined)
11448 * The default HTTP method to be used for requests. (defaults to undefined; if not set but parms are present will use POST, otherwise GET)
11452 * @property timeout
11453 * The timeout in milliseconds to be used for requests. (defaults to 30000)
11458 * @property autoAbort
11459 * Whether a new request should abort any pending requests. (defaults to false)
11465 * Serialize the passed form into a url encoded string
11466 * @param {String/HTMLElement} form
11469 serializeForm : function(form){
11470 return Roo.lib.Ajax.serializeForm(form);
11474 * Ext JS Library 1.1.1
11475 * Copyright(c) 2006-2007, Ext JS, LLC.
11477 * Originally Released Under LGPL - original licence link has changed is not relivant.
11480 * <script type="text/javascript">
11485 * @class Roo.UpdateManager
11486 * @extends Roo.util.Observable
11487 * Provides AJAX-style update for Element object.<br><br>
11490 * // Get it from a Roo.Element object
11491 * var el = Roo.get("foo");
11492 * var mgr = el.getUpdateManager();
11493 * mgr.update("http://myserver.com/index.php", "param1=1&param2=2");
11495 * mgr.formUpdate("myFormId", "http://myserver.com/index.php");
11497 * // or directly (returns the same UpdateManager instance)
11498 * var mgr = new Roo.UpdateManager("myElementId");
11499 * mgr.startAutoRefresh(60, "http://myserver.com/index.php");
11500 * mgr.on("update", myFcnNeedsToKnow);
11502 // short handed call directly from the element object
11503 Roo.get("foo").load({
11507 text: "Loading Foo..."
11511 * Create new UpdateManager directly.
11512 * @param {String/HTMLElement/Roo.Element} el The element to update
11513 * @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).
11515 Roo.UpdateManager = function(el, forceNew){
11517 if(!forceNew && el.updateManager){
11518 return el.updateManager;
11521 * The Element object
11522 * @type Roo.Element
11526 * Cached url to use for refreshes. Overwritten every time update() is called unless "discardUrl" param is set to true.
11529 this.defaultUrl = null;
11533 * @event beforeupdate
11534 * Fired before an update is made, return false from your handler and the update is cancelled.
11535 * @param {Roo.Element} el
11536 * @param {String/Object/Function} url
11537 * @param {String/Object} params
11539 "beforeupdate": true,
11542 * Fired after successful update is made.
11543 * @param {Roo.Element} el
11544 * @param {Object} oResponseObject The response Object
11549 * Fired on update failure.
11550 * @param {Roo.Element} el
11551 * @param {Object} oResponseObject The response Object
11555 var d = Roo.UpdateManager.defaults;
11557 * Blank page URL to use with SSL file uploads (Defaults to Roo.UpdateManager.defaults.sslBlankUrl or "about:blank").
11560 this.sslBlankUrl = d.sslBlankUrl;
11562 * Whether to append unique parameter on get request to disable caching (Defaults to Roo.UpdateManager.defaults.disableCaching or false).
11565 this.disableCaching = d.disableCaching;
11567 * Text for loading indicator (Defaults to Roo.UpdateManager.defaults.indicatorText or '<div class="loading-indicator">Loading...</div>').
11570 this.indicatorText = d.indicatorText;
11572 * Whether to show indicatorText when loading (Defaults to Roo.UpdateManager.defaults.showLoadIndicator or true).
11575 this.showLoadIndicator = d.showLoadIndicator;
11577 * Timeout for requests or form posts in seconds (Defaults to Roo.UpdateManager.defaults.timeout or 30 seconds).
11580 this.timeout = d.timeout;
11583 * True to process scripts in the output (Defaults to Roo.UpdateManager.defaults.loadScripts (false)).
11586 this.loadScripts = d.loadScripts;
11589 * Transaction object of current executing transaction
11591 this.transaction = null;
11596 this.autoRefreshProcId = null;
11598 * Delegate for refresh() prebound to "this", use myUpdater.refreshDelegate.createCallback(arg1, arg2) to bind arguments
11601 this.refreshDelegate = this.refresh.createDelegate(this);
11603 * Delegate for update() prebound to "this", use myUpdater.updateDelegate.createCallback(arg1, arg2) to bind arguments
11606 this.updateDelegate = this.update.createDelegate(this);
11608 * Delegate for formUpdate() prebound to "this", use myUpdater.formUpdateDelegate.createCallback(arg1, arg2) to bind arguments
11611 this.formUpdateDelegate = this.formUpdate.createDelegate(this);
11615 this.successDelegate = this.processSuccess.createDelegate(this);
11619 this.failureDelegate = this.processFailure.createDelegate(this);
11621 if(!this.renderer){
11623 * The renderer for this UpdateManager. Defaults to {@link Roo.UpdateManager.BasicRenderer}.
11625 this.renderer = new Roo.UpdateManager.BasicRenderer();
11628 Roo.UpdateManager.superclass.constructor.call(this);
11631 Roo.extend(Roo.UpdateManager, Roo.util.Observable, {
11633 * Get the Element this UpdateManager is bound to
11634 * @return {Roo.Element} The element
11636 getEl : function(){
11640 * Performs an async request, updating this element with the response. If params are specified it uses POST, otherwise it uses GET.
11641 * @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:
11644 url: "your-url.php",<br/>
11645 params: {param1: "foo", param2: "bar"}, // or a URL encoded string<br/>
11646 callback: yourFunction,<br/>
11647 scope: yourObject, //(optional scope) <br/>
11648 discardUrl: false, <br/>
11649 nocache: false,<br/>
11650 text: "Loading...",<br/>
11652 scripts: false<br/>
11655 * The only required property is url. The optional properties nocache, text and scripts
11656 * are shorthand for disableCaching, indicatorText and loadScripts and are used to set their associated property on this UpdateManager instance.
11657 * @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}
11658 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11659 * @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.
11661 update : function(url, params, callback, discardUrl){
11662 if(this.fireEvent("beforeupdate", this.el, url, params) !== false){
11663 var method = this.method, cfg;
11664 if(typeof url == "object"){ // must be config object
11667 params = params || cfg.params;
11668 callback = callback || cfg.callback;
11669 discardUrl = discardUrl || cfg.discardUrl;
11670 if(callback && cfg.scope){
11671 callback = callback.createDelegate(cfg.scope);
11673 if(typeof cfg.method != "undefined"){method = cfg.method;};
11674 if(typeof cfg.nocache != "undefined"){this.disableCaching = cfg.nocache;};
11675 if(typeof cfg.text != "undefined"){this.indicatorText = '<div class="loading-indicator">'+cfg.text+"</div>";};
11676 if(typeof cfg.scripts != "undefined"){this.loadScripts = cfg.scripts;};
11677 if(typeof cfg.timeout != "undefined"){this.timeout = cfg.timeout;};
11679 this.showLoading();
11681 this.defaultUrl = url;
11683 if(typeof url == "function"){
11684 url = url.call(this);
11687 method = method || (params ? "POST" : "GET");
11688 if(method == "GET"){
11689 url = this.prepareUrl(url);
11692 var o = Roo.apply(cfg ||{}, {
11695 success: this.successDelegate,
11696 failure: this.failureDelegate,
11697 callback: undefined,
11698 timeout: (this.timeout*1000),
11699 argument: {"url": url, "form": null, "callback": callback, "params": params}
11702 this.transaction = Roo.Ajax.request(o);
11707 * 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.
11708 * Uses this.sslBlankUrl for SSL file uploads to prevent IE security warning.
11709 * @param {String/HTMLElement} form The form Id or form element
11710 * @param {String} url (optional) The url to pass the form to. If omitted the action attribute on the form will be used.
11711 * @param {Boolean} reset (optional) Whether to try to reset the form after the update
11712 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess, oResponse)
11714 formUpdate : function(form, url, reset, callback){
11715 if(this.fireEvent("beforeupdate", this.el, form, url) !== false){
11716 if(typeof url == "function"){
11717 url = url.call(this);
11719 form = Roo.getDom(form);
11720 this.transaction = Roo.Ajax.request({
11723 success: this.successDelegate,
11724 failure: this.failureDelegate,
11725 timeout: (this.timeout*1000),
11726 argument: {"url": url, "form": form, "callback": callback, "reset": reset}
11728 this.showLoading.defer(1, this);
11733 * Refresh the element with the last used url or defaultUrl. If there is no url, it returns immediately
11734 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11736 refresh : function(callback){
11737 if(this.defaultUrl == null){
11740 this.update(this.defaultUrl, null, callback, true);
11744 * Set this element to auto refresh.
11745 * @param {Number} interval How often to update (in seconds).
11746 * @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)
11747 * @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}
11748 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
11749 * @param {Boolean} refreshNow (optional) Whether to execute the refresh now, or wait the interval
11751 startAutoRefresh : function(interval, url, params, callback, refreshNow){
11753 this.update(url || this.defaultUrl, params, callback, true);
11755 if(this.autoRefreshProcId){
11756 clearInterval(this.autoRefreshProcId);
11758 this.autoRefreshProcId = setInterval(this.update.createDelegate(this, [url || this.defaultUrl, params, callback, true]), interval*1000);
11762 * Stop auto refresh on this element.
11764 stopAutoRefresh : function(){
11765 if(this.autoRefreshProcId){
11766 clearInterval(this.autoRefreshProcId);
11767 delete this.autoRefreshProcId;
11771 isAutoRefreshing : function(){
11772 return this.autoRefreshProcId ? true : false;
11775 * Called to update the element to "Loading" state. Override to perform custom action.
11777 showLoading : function(){
11778 if(this.showLoadIndicator){
11779 this.el.update(this.indicatorText);
11784 * Adds unique parameter to query string if disableCaching = true
11787 prepareUrl : function(url){
11788 if(this.disableCaching){
11789 var append = "_dc=" + (new Date().getTime());
11790 if(url.indexOf("?") !== -1){
11791 url += "&" + append;
11793 url += "?" + append;
11802 processSuccess : function(response){
11803 this.transaction = null;
11804 if(response.argument.form && response.argument.reset){
11805 try{ // put in try/catch since some older FF releases had problems with this
11806 response.argument.form.reset();
11809 if(this.loadScripts){
11810 this.renderer.render(this.el, response, this,
11811 this.updateComplete.createDelegate(this, [response]));
11813 this.renderer.render(this.el, response, this);
11814 this.updateComplete(response);
11818 updateComplete : function(response){
11819 this.fireEvent("update", this.el, response);
11820 if(typeof response.argument.callback == "function"){
11821 response.argument.callback(this.el, true, response);
11828 processFailure : function(response){
11829 this.transaction = null;
11830 this.fireEvent("failure", this.el, response);
11831 if(typeof response.argument.callback == "function"){
11832 response.argument.callback(this.el, false, response);
11837 * Set the content renderer for this UpdateManager. See {@link Roo.UpdateManager.BasicRenderer#render} for more details.
11838 * @param {Object} renderer The object implementing the render() method
11840 setRenderer : function(renderer){
11841 this.renderer = renderer;
11844 getRenderer : function(){
11845 return this.renderer;
11849 * Set the defaultUrl used for updates
11850 * @param {String/Function} defaultUrl The url or a function to call to get the url
11852 setDefaultUrl : function(defaultUrl){
11853 this.defaultUrl = defaultUrl;
11857 * Aborts the executing transaction
11859 abort : function(){
11860 if(this.transaction){
11861 Roo.Ajax.abort(this.transaction);
11866 * Returns true if an update is in progress
11867 * @return {Boolean}
11869 isUpdating : function(){
11870 if(this.transaction){
11871 return Roo.Ajax.isLoading(this.transaction);
11878 * @class Roo.UpdateManager.defaults
11879 * @static (not really - but it helps the doc tool)
11880 * The defaults collection enables customizing the default properties of UpdateManager
11882 Roo.UpdateManager.defaults = {
11884 * Timeout for requests or form posts in seconds (Defaults 30 seconds).
11890 * True to process scripts by default (Defaults to false).
11893 loadScripts : false,
11896 * Blank page URL to use with SSL file uploads (Defaults to "javascript:false").
11899 sslBlankUrl : (Roo.SSL_SECURE_URL || "javascript:false"),
11901 * Whether to append unique parameter on get request to disable caching (Defaults to false).
11904 disableCaching : false,
11906 * Whether to show indicatorText when loading (Defaults to true).
11909 showLoadIndicator : true,
11911 * Text for loading indicator (Defaults to '<div class="loading-indicator">Loading...</div>').
11914 indicatorText : '<div class="loading-indicator">Loading...</div>'
11918 * Static convenience method. This method is deprecated in favor of el.load({url:'foo.php', ...}).
11920 * <pre><code>Roo.UpdateManager.updateElement("my-div", "stuff.php");</code></pre>
11921 * @param {String/HTMLElement/Roo.Element} el The element to update
11922 * @param {String} url The url
11923 * @param {String/Object} params (optional) Url encoded param string or an object of name/value pairs
11924 * @param {Object} options (optional) A config object with any of the UpdateManager properties you want to set - for example: {disableCaching:true, indicatorText: "Loading data..."}
11927 * @member Roo.UpdateManager
11929 Roo.UpdateManager.updateElement = function(el, url, params, options){
11930 var um = Roo.get(el, true).getUpdateManager();
11931 Roo.apply(um, options);
11932 um.update(url, params, options ? options.callback : null);
11934 // alias for backwards compat
11935 Roo.UpdateManager.update = Roo.UpdateManager.updateElement;
11937 * @class Roo.UpdateManager.BasicRenderer
11938 * Default Content renderer. Updates the elements innerHTML with the responseText.
11940 Roo.UpdateManager.BasicRenderer = function(){};
11942 Roo.UpdateManager.BasicRenderer.prototype = {
11944 * This is called when the transaction is completed and it's time to update the element - The BasicRenderer
11945 * updates the elements innerHTML with the responseText - To perform a custom render (i.e. XML or JSON processing),
11946 * create an object with a "render(el, response)" method and pass it to setRenderer on the UpdateManager.
11947 * @param {Roo.Element} el The element being rendered
11948 * @param {Object} response The YUI Connect response object
11949 * @param {UpdateManager} updateManager The calling update manager
11950 * @param {Function} callback A callback that will need to be called if loadScripts is true on the UpdateManager
11952 render : function(el, response, updateManager, callback){
11953 el.update(response.responseText, updateManager.loadScripts, callback);
11958 * Ext JS Library 1.1.1
11959 * Copyright(c) 2006-2007, Ext JS, LLC.
11961 * Originally Released Under LGPL - original licence link has changed is not relivant.
11964 * <script type="text/javascript">
11968 * @class Roo.util.DelayedTask
11969 * Provides a convenient method of performing setTimeout where a new
11970 * timeout cancels the old timeout. An example would be performing validation on a keypress.
11971 * You can use this class to buffer
11972 * the keypress events for a certain number of milliseconds, and perform only if they stop
11973 * for that amount of time.
11974 * @constructor The parameters to this constructor serve as defaults and are not required.
11975 * @param {Function} fn (optional) The default function to timeout
11976 * @param {Object} scope (optional) The default scope of that timeout
11977 * @param {Array} args (optional) The default Array of arguments
11979 Roo.util.DelayedTask = function(fn, scope, args){
11980 var id = null, d, t;
11982 var call = function(){
11983 var now = new Date().getTime();
11987 fn.apply(scope, args || []);
11991 * Cancels any pending timeout and queues a new one
11992 * @param {Number} delay The milliseconds to delay
11993 * @param {Function} newFn (optional) Overrides function passed to constructor
11994 * @param {Object} newScope (optional) Overrides scope passed to constructor
11995 * @param {Array} newArgs (optional) Overrides args passed to constructor
11997 this.delay = function(delay, newFn, newScope, newArgs){
11998 if(id && delay != d){
12002 t = new Date().getTime();
12004 scope = newScope || scope;
12005 args = newArgs || args;
12007 id = setInterval(call, d);
12012 * Cancel the last queued timeout
12014 this.cancel = function(){
12022 * Ext JS Library 1.1.1
12023 * Copyright(c) 2006-2007, Ext JS, LLC.
12025 * Originally Released Under LGPL - original licence link has changed is not relivant.
12028 * <script type="text/javascript">
12032 Roo.util.TaskRunner = function(interval){
12033 interval = interval || 10;
12034 var tasks = [], removeQueue = [];
12036 var running = false;
12038 var stopThread = function(){
12044 var startThread = function(){
12047 id = setInterval(runTasks, interval);
12051 var removeTask = function(task){
12052 removeQueue.push(task);
12058 var runTasks = function(){
12059 if(removeQueue.length > 0){
12060 for(var i = 0, len = removeQueue.length; i < len; i++){
12061 tasks.remove(removeQueue[i]);
12064 if(tasks.length < 1){
12069 var now = new Date().getTime();
12070 for(var i = 0, len = tasks.length; i < len; ++i){
12072 var itime = now - t.taskRunTime;
12073 if(t.interval <= itime){
12074 var rt = t.run.apply(t.scope || t, t.args || [++t.taskRunCount]);
12075 t.taskRunTime = now;
12076 if(rt === false || t.taskRunCount === t.repeat){
12081 if(t.duration && t.duration <= (now - t.taskStartTime)){
12088 * Queues a new task.
12089 * @param {Object} task
12091 this.start = function(task){
12093 task.taskStartTime = new Date().getTime();
12094 task.taskRunTime = 0;
12095 task.taskRunCount = 0;
12100 this.stop = function(task){
12105 this.stopAll = function(){
12107 for(var i = 0, len = tasks.length; i < len; i++){
12108 if(tasks[i].onStop){
12117 Roo.TaskMgr = new Roo.util.TaskRunner();/*
12119 * Ext JS Library 1.1.1
12120 * Copyright(c) 2006-2007, Ext JS, LLC.
12122 * Originally Released Under LGPL - original licence link has changed is not relivant.
12125 * <script type="text/javascript">
12130 * @class Roo.util.MixedCollection
12131 * @extends Roo.util.Observable
12132 * A Collection class that maintains both numeric indexes and keys and exposes events.
12134 * @param {Boolean} allowFunctions True if the addAll function should add function references to the
12135 * collection (defaults to false)
12136 * @param {Function} keyFn A function that can accept an item of the type(s) stored in this MixedCollection
12137 * and return the key value for that item. This is used when available to look up the key on items that
12138 * were passed without an explicit key parameter to a MixedCollection method. Passing this parameter is
12139 * equivalent to providing an implementation for the {@link #getKey} method.
12141 Roo.util.MixedCollection = function(allowFunctions, keyFn){
12149 * Fires when the collection is cleared.
12154 * Fires when an item is added to the collection.
12155 * @param {Number} index The index at which the item was added.
12156 * @param {Object} o The item added.
12157 * @param {String} key The key associated with the added item.
12162 * Fires when an item is replaced in the collection.
12163 * @param {String} key he key associated with the new added.
12164 * @param {Object} old The item being replaced.
12165 * @param {Object} new The new item.
12170 * Fires when an item is removed from the collection.
12171 * @param {Object} o The item being removed.
12172 * @param {String} key (optional) The key associated with the removed item.
12177 this.allowFunctions = allowFunctions === true;
12179 this.getKey = keyFn;
12181 Roo.util.MixedCollection.superclass.constructor.call(this);
12184 Roo.extend(Roo.util.MixedCollection, Roo.util.Observable, {
12185 allowFunctions : false,
12188 * Adds an item to the collection.
12189 * @param {String} key The key to associate with the item
12190 * @param {Object} o The item to add.
12191 * @return {Object} The item added.
12193 add : function(key, o){
12194 if(arguments.length == 1){
12196 key = this.getKey(o);
12198 if(typeof key == "undefined" || key === null){
12200 this.items.push(o);
12201 this.keys.push(null);
12203 var old = this.map[key];
12205 return this.replace(key, o);
12208 this.items.push(o);
12210 this.keys.push(key);
12212 this.fireEvent("add", this.length-1, o, key);
12217 * MixedCollection has a generic way to fetch keys if you implement getKey.
12220 var mc = new Roo.util.MixedCollection();
12221 mc.add(someEl.dom.id, someEl);
12222 mc.add(otherEl.dom.id, otherEl);
12226 var mc = new Roo.util.MixedCollection();
12227 mc.getKey = function(el){
12233 // or via the constructor
12234 var mc = new Roo.util.MixedCollection(false, function(el){
12240 * @param o {Object} The item for which to find the key.
12241 * @return {Object} The key for the passed item.
12243 getKey : function(o){
12248 * Replaces an item in the collection.
12249 * @param {String} key The key associated with the item to replace, or the item to replace.
12250 * @param o {Object} o (optional) If the first parameter passed was a key, the item to associate with that key.
12251 * @return {Object} The new item.
12253 replace : function(key, o){
12254 if(arguments.length == 1){
12256 key = this.getKey(o);
12258 var old = this.item(key);
12259 if(typeof key == "undefined" || key === null || typeof old == "undefined"){
12260 return this.add(key, o);
12262 var index = this.indexOfKey(key);
12263 this.items[index] = o;
12265 this.fireEvent("replace", key, old, o);
12270 * Adds all elements of an Array or an Object to the collection.
12271 * @param {Object/Array} objs An Object containing properties which will be added to the collection, or
12272 * an Array of values, each of which are added to the collection.
12274 addAll : function(objs){
12275 if(arguments.length > 1 || objs instanceof Array){
12276 var args = arguments.length > 1 ? arguments : objs;
12277 for(var i = 0, len = args.length; i < len; i++){
12281 for(var key in objs){
12282 if(this.allowFunctions || typeof objs[key] != "function"){
12283 this.add(key, objs[key]);
12290 * Executes the specified function once for every item in the collection, passing each
12291 * item as the first and only parameter. returning false from the function will stop the iteration.
12292 * @param {Function} fn The function to execute for each item.
12293 * @param {Object} scope (optional) The scope in which to execute the function.
12295 each : function(fn, scope){
12296 var items = [].concat(this.items); // each safe for removal
12297 for(var i = 0, len = items.length; i < len; i++){
12298 if(fn.call(scope || items[i], items[i], i, len) === false){
12305 * Executes the specified function once for every key in the collection, passing each
12306 * key, and its associated item as the first two parameters.
12307 * @param {Function} fn The function to execute for each item.
12308 * @param {Object} scope (optional) The scope in which to execute the function.
12310 eachKey : function(fn, scope){
12311 for(var i = 0, len = this.keys.length; i < len; i++){
12312 fn.call(scope || window, this.keys[i], this.items[i], i, len);
12317 * Returns the first item in the collection which elicits a true return value from the
12318 * passed selection function.
12319 * @param {Function} fn The selection function to execute for each item.
12320 * @param {Object} scope (optional) The scope in which to execute the function.
12321 * @return {Object} The first item in the collection which returned true from the selection function.
12323 find : function(fn, scope){
12324 for(var i = 0, len = this.items.length; i < len; i++){
12325 if(fn.call(scope || window, this.items[i], this.keys[i])){
12326 return this.items[i];
12333 * Inserts an item at the specified index in the collection.
12334 * @param {Number} index The index to insert the item at.
12335 * @param {String} key The key to associate with the new item, or the item itself.
12336 * @param {Object} o (optional) If the second parameter was a key, the new item.
12337 * @return {Object} The item inserted.
12339 insert : function(index, key, o){
12340 if(arguments.length == 2){
12342 key = this.getKey(o);
12344 if(index >= this.length){
12345 return this.add(key, o);
12348 this.items.splice(index, 0, o);
12349 if(typeof key != "undefined" && key != null){
12352 this.keys.splice(index, 0, key);
12353 this.fireEvent("add", index, o, key);
12358 * Removed an item from the collection.
12359 * @param {Object} o The item to remove.
12360 * @return {Object} The item removed.
12362 remove : function(o){
12363 return this.removeAt(this.indexOf(o));
12367 * Remove an item from a specified index in the collection.
12368 * @param {Number} index The index within the collection of the item to remove.
12370 removeAt : function(index){
12371 if(index < this.length && index >= 0){
12373 var o = this.items[index];
12374 this.items.splice(index, 1);
12375 var key = this.keys[index];
12376 if(typeof key != "undefined"){
12377 delete this.map[key];
12379 this.keys.splice(index, 1);
12380 this.fireEvent("remove", o, key);
12385 * Removed an item associated with the passed key fom the collection.
12386 * @param {String} key The key of the item to remove.
12388 removeKey : function(key){
12389 return this.removeAt(this.indexOfKey(key));
12393 * Returns the number of items in the collection.
12394 * @return {Number} the number of items in the collection.
12396 getCount : function(){
12397 return this.length;
12401 * Returns index within the collection of the passed Object.
12402 * @param {Object} o The item to find the index of.
12403 * @return {Number} index of the item.
12405 indexOf : function(o){
12406 if(!this.items.indexOf){
12407 for(var i = 0, len = this.items.length; i < len; i++){
12408 if(this.items[i] == o) return i;
12412 return this.items.indexOf(o);
12417 * Returns index within the collection of the passed key.
12418 * @param {String} key The key to find the index of.
12419 * @return {Number} index of the key.
12421 indexOfKey : function(key){
12422 if(!this.keys.indexOf){
12423 for(var i = 0, len = this.keys.length; i < len; i++){
12424 if(this.keys[i] == key) return i;
12428 return this.keys.indexOf(key);
12433 * Returns the item associated with the passed key OR index. Key has priority over index.
12434 * @param {String/Number} key The key or index of the item.
12435 * @return {Object} The item associated with the passed key.
12437 item : function(key){
12438 var item = typeof this.map[key] != "undefined" ? this.map[key] : this.items[key];
12439 return typeof item != 'function' || this.allowFunctions ? item : null; // for prototype!
12443 * Returns the item at the specified index.
12444 * @param {Number} index The index of the item.
12447 itemAt : function(index){
12448 return this.items[index];
12452 * Returns the item associated with the passed key.
12453 * @param {String/Number} key The key of the item.
12454 * @return {Object} The item associated with the passed key.
12456 key : function(key){
12457 return this.map[key];
12461 * Returns true if the collection contains the passed Object as an item.
12462 * @param {Object} o The Object to look for in the collection.
12463 * @return {Boolean} True if the collection contains the Object as an item.
12465 contains : function(o){
12466 return this.indexOf(o) != -1;
12470 * Returns true if the collection contains the passed Object as a key.
12471 * @param {String} key The key to look for in the collection.
12472 * @return {Boolean} True if the collection contains the Object as a key.
12474 containsKey : function(key){
12475 return typeof this.map[key] != "undefined";
12479 * Removes all items from the collection.
12481 clear : function(){
12486 this.fireEvent("clear");
12490 * Returns the first item in the collection.
12491 * @return {Object} the first item in the collection..
12493 first : function(){
12494 return this.items[0];
12498 * Returns the last item in the collection.
12499 * @return {Object} the last item in the collection..
12502 return this.items[this.length-1];
12505 _sort : function(property, dir, fn){
12506 var dsc = String(dir).toUpperCase() == "DESC" ? -1 : 1;
12507 fn = fn || function(a, b){
12510 var c = [], k = this.keys, items = this.items;
12511 for(var i = 0, len = items.length; i < len; i++){
12512 c[c.length] = {key: k[i], value: items[i], index: i};
12514 c.sort(function(a, b){
12515 var v = fn(a[property], b[property]) * dsc;
12517 v = (a.index < b.index ? -1 : 1);
12521 for(var i = 0, len = c.length; i < len; i++){
12522 items[i] = c[i].value;
12525 this.fireEvent("sort", this);
12529 * Sorts this collection with the passed comparison function
12530 * @param {String} direction (optional) "ASC" or "DESC"
12531 * @param {Function} fn (optional) comparison function
12533 sort : function(dir, fn){
12534 this._sort("value", dir, fn);
12538 * Sorts this collection by keys
12539 * @param {String} direction (optional) "ASC" or "DESC"
12540 * @param {Function} fn (optional) a comparison function (defaults to case insensitive string)
12542 keySort : function(dir, fn){
12543 this._sort("key", dir, fn || function(a, b){
12544 return String(a).toUpperCase()-String(b).toUpperCase();
12549 * Returns a range of items in this collection
12550 * @param {Number} startIndex (optional) defaults to 0
12551 * @param {Number} endIndex (optional) default to the last item
12552 * @return {Array} An array of items
12554 getRange : function(start, end){
12555 var items = this.items;
12556 if(items.length < 1){
12559 start = start || 0;
12560 end = Math.min(typeof end == "undefined" ? this.length-1 : end, this.length-1);
12563 for(var i = start; i <= end; i++) {
12564 r[r.length] = items[i];
12567 for(var i = start; i >= end; i--) {
12568 r[r.length] = items[i];
12575 * Filter the <i>objects</i> in this collection by a specific property.
12576 * Returns a new collection that has been filtered.
12577 * @param {String} property A property on your objects
12578 * @param {String/RegExp} value Either string that the property values
12579 * should start with or a RegExp to test against the property
12580 * @return {MixedCollection} The new filtered collection
12582 filter : function(property, value){
12583 if(!value.exec){ // not a regex
12584 value = String(value);
12585 if(value.length == 0){
12586 return this.clone();
12588 value = new RegExp("^" + Roo.escapeRe(value), "i");
12590 return this.filterBy(function(o){
12591 return o && value.test(o[property]);
12596 * Filter by a function. * Returns a new collection that has been filtered.
12597 * The passed function will be called with each
12598 * object in the collection. If the function returns true, the value is included
12599 * otherwise it is filtered.
12600 * @param {Function} fn The function to be called, it will receive the args o (the object), k (the key)
12601 * @param {Object} scope (optional) The scope of the function (defaults to this)
12602 * @return {MixedCollection} The new filtered collection
12604 filterBy : function(fn, scope){
12605 var r = new Roo.util.MixedCollection();
12606 r.getKey = this.getKey;
12607 var k = this.keys, it = this.items;
12608 for(var i = 0, len = it.length; i < len; i++){
12609 if(fn.call(scope||this, it[i], k[i])){
12610 r.add(k[i], it[i]);
12617 * Creates a duplicate of this collection
12618 * @return {MixedCollection}
12620 clone : function(){
12621 var r = new Roo.util.MixedCollection();
12622 var k = this.keys, it = this.items;
12623 for(var i = 0, len = it.length; i < len; i++){
12624 r.add(k[i], it[i]);
12626 r.getKey = this.getKey;
12631 * Returns the item associated with the passed key or index.
12633 * @param {String/Number} key The key or index of the item.
12634 * @return {Object} The item associated with the passed key.
12636 Roo.util.MixedCollection.prototype.get = Roo.util.MixedCollection.prototype.item;/*
12638 * Ext JS Library 1.1.1
12639 * Copyright(c) 2006-2007, Ext JS, LLC.
12641 * Originally Released Under LGPL - original licence link has changed is not relivant.
12644 * <script type="text/javascript">
12647 * @class Roo.util.JSON
12648 * Modified version of Douglas Crockford"s json.js that doesn"t
12649 * mess with the Object prototype
12650 * http://www.json.org/js.html
12653 Roo.util.JSON = new (function(){
12654 var useHasOwn = {}.hasOwnProperty ? true : false;
12656 // crashes Safari in some instances
12657 //var validRE = /^("(\\.|[^"\\\n\r])*?"|[,:{}\[\]0-9.\-+Eaeflnr-u \n\r\t])+?$/;
12659 var pad = function(n) {
12660 return n < 10 ? "0" + n : n;
12673 var encodeString = function(s){
12674 if (/["\\\x00-\x1f]/.test(s)) {
12675 return '"' + s.replace(/([\x00-\x1f\\"])/g, function(a, b) {
12680 c = b.charCodeAt();
12682 Math.floor(c / 16).toString(16) +
12683 (c % 16).toString(16);
12686 return '"' + s + '"';
12689 var encodeArray = function(o){
12690 var a = ["["], b, i, l = o.length, v;
12691 for (i = 0; i < l; i += 1) {
12693 switch (typeof v) {
12702 a.push(v === null ? "null" : Roo.util.JSON.encode(v));
12710 var encodeDate = function(o){
12711 return '"' + o.getFullYear() + "-" +
12712 pad(o.getMonth() + 1) + "-" +
12713 pad(o.getDate()) + "T" +
12714 pad(o.getHours()) + ":" +
12715 pad(o.getMinutes()) + ":" +
12716 pad(o.getSeconds()) + '"';
12720 * Encodes an Object, Array or other value
12721 * @param {Mixed} o The variable to encode
12722 * @return {String} The JSON string
12724 this.encode = function(o){
12725 if(typeof o == "undefined" || o === null){
12727 }else if(o instanceof Array){
12728 return encodeArray(o);
12729 }else if(o instanceof Date){
12730 return encodeDate(o);
12731 }else if(typeof o == "string"){
12732 return encodeString(o);
12733 }else if(typeof o == "number"){
12734 return isFinite(o) ? String(o) : "null";
12735 }else if(typeof o == "boolean"){
12738 var a = ["{"], b, i, v;
12740 if(!useHasOwn || o.hasOwnProperty(i)) {
12742 switch (typeof v) {
12751 a.push(this.encode(i), ":",
12752 v === null ? "null" : this.encode(v));
12763 * Decodes (parses) a JSON string to an object. If the JSON is invalid, this function throws a SyntaxError.
12764 * @param {String} json The JSON string
12765 * @return {Object} The resulting object
12767 this.decode = function(json){
12771 return eval("(" + json + ')');
12775 * Shorthand for {@link Roo.util.JSON#encode}
12776 * @member Roo encode
12778 Roo.encode = Roo.util.JSON.encode;
12780 * Shorthand for {@link Roo.util.JSON#decode}
12781 * @member Roo decode
12783 Roo.decode = Roo.util.JSON.decode;
12786 * Ext JS Library 1.1.1
12787 * Copyright(c) 2006-2007, Ext JS, LLC.
12789 * Originally Released Under LGPL - original licence link has changed is not relivant.
12792 * <script type="text/javascript">
12796 * @class Roo.util.Format
12797 * Reusable data formatting functions
12800 Roo.util.Format = function(){
12801 var trimRe = /^\s+|\s+$/g;
12804 * Truncate a string and add an ellipsis ('...') to the end if it exceeds the specified length
12805 * @param {String} value The string to truncate
12806 * @param {Number} length The maximum length to allow before truncating
12807 * @return {String} The converted text
12809 ellipsis : function(value, len){
12810 if(value && value.length > len){
12811 return value.substr(0, len-3)+"...";
12817 * Checks a reference and converts it to empty string if it is undefined
12818 * @param {Mixed} value Reference to check
12819 * @return {Mixed} Empty string if converted, otherwise the original value
12821 undef : function(value){
12822 return typeof value != "undefined" ? value : "";
12826 * Convert certain characters (&, <, >, and ') to their HTML character equivalents for literal display in web pages.
12827 * @param {String} value The string to encode
12828 * @return {String} The encoded text
12830 htmlEncode : function(value){
12831 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, """);
12835 * Convert certain characters (&, <, >, and ') from their HTML character equivalents.
12836 * @param {String} value The string to decode
12837 * @return {String} The decoded text
12839 htmlDecode : function(value){
12840 return !value ? value : String(value).replace(/&/g, "&").replace(/>/g, ">").replace(/</g, "<").replace(/"/g, '"');
12844 * Trims any whitespace from either side of a string
12845 * @param {String} value The text to trim
12846 * @return {String} The trimmed text
12848 trim : function(value){
12849 return String(value).replace(trimRe, "");
12853 * Returns a substring from within an original string
12854 * @param {String} value The original text
12855 * @param {Number} start The start index of the substring
12856 * @param {Number} length The length of the substring
12857 * @return {String} The substring
12859 substr : function(value, start, length){
12860 return String(value).substr(start, length);
12864 * Converts a string to all lower case letters
12865 * @param {String} value The text to convert
12866 * @return {String} The converted text
12868 lowercase : function(value){
12869 return String(value).toLowerCase();
12873 * Converts a string to all upper case letters
12874 * @param {String} value The text to convert
12875 * @return {String} The converted text
12877 uppercase : function(value){
12878 return String(value).toUpperCase();
12882 * Converts the first character only of a string to upper case
12883 * @param {String} value The text to convert
12884 * @return {String} The converted text
12886 capitalize : function(value){
12887 return !value ? value : value.charAt(0).toUpperCase() + value.substr(1).toLowerCase();
12891 call : function(value, fn){
12892 if(arguments.length > 2){
12893 var args = Array.prototype.slice.call(arguments, 2);
12894 args.unshift(value);
12896 return /** eval:var:value */ eval(fn).apply(window, args);
12898 /** eval:var:value */
12899 return /** eval:var:value */ eval(fn).call(window, value);
12904 * Format a number as US currency
12905 * @param {Number/String} value The numeric value to format
12906 * @return {String} The formatted currency string
12908 usMoney : function(v){
12909 v = (Math.round((v-0)*100))/100;
12910 v = (v == Math.floor(v)) ? v + ".00" : ((v*10 == Math.floor(v*10)) ? v + "0" : v);
12912 var ps = v.split('.');
12914 var sub = ps[1] ? '.'+ ps[1] : '.00';
12915 var r = /(\d+)(\d{3})/;
12916 while (r.test(whole)) {
12917 whole = whole.replace(r, '$1' + ',' + '$2');
12919 return "$" + whole + sub ;
12923 * Parse a value into a formatted date using the specified format pattern.
12924 * @param {Mixed} value The value to format
12925 * @param {String} format (optional) Any valid date format string (defaults to 'm/d/Y')
12926 * @return {String} The formatted date string
12928 date : function(v, format){
12932 if(!(v instanceof Date)){
12933 v = new Date(Date.parse(v));
12935 return v.dateFormat(format || "m/d/Y");
12939 * Returns a date rendering function that can be reused to apply a date format multiple times efficiently
12940 * @param {String} format Any valid date format string
12941 * @return {Function} The date formatting function
12943 dateRenderer : function(format){
12944 return function(v){
12945 return Roo.util.Format.date(v, format);
12950 stripTagsRE : /<\/?[^>]+>/gi,
12953 * Strips all HTML tags
12954 * @param {Mixed} value The text from which to strip tags
12955 * @return {String} The stripped text
12957 stripTags : function(v){
12958 return !v ? v : String(v).replace(this.stripTagsRE, "");
12963 * Ext JS Library 1.1.1
12964 * Copyright(c) 2006-2007, Ext JS, LLC.
12966 * Originally Released Under LGPL - original licence link has changed is not relivant.
12969 * <script type="text/javascript">
12976 * @class Roo.MasterTemplate
12977 * @extends Roo.Template
12978 * Provides a template that can have child templates. The syntax is:
12980 var t = new Roo.MasterTemplate(
12981 '<select name="{name}">',
12982 '<tpl name="options"><option value="{value:trim}">{text:ellipsis(10)}</option></tpl>',
12985 t.add('options', {value: 'foo', text: 'bar'});
12986 // or you can add multiple child elements in one shot
12987 t.addAll('options', [
12988 {value: 'foo', text: 'bar'},
12989 {value: 'foo2', text: 'bar2'},
12990 {value: 'foo3', text: 'bar3'}
12992 // then append, applying the master template values
12993 t.append('my-form', {name: 'my-select'});
12995 * A name attribute for the child template is not required if you have only one child
12996 * template or you want to refer to them by index.
12998 Roo.MasterTemplate = function(){
12999 Roo.MasterTemplate.superclass.constructor.apply(this, arguments);
13000 this.originalHtml = this.html;
13002 var m, re = this.subTemplateRe;
13005 while(m = re.exec(this.html)){
13006 var name = m[1], content = m[2];
13011 tpl : new Roo.Template(content)
13014 st[name] = st[subIndex];
13016 st[subIndex].tpl.compile();
13017 st[subIndex].tpl.call = this.call.createDelegate(this);
13020 this.subCount = subIndex;
13023 Roo.extend(Roo.MasterTemplate, Roo.Template, {
13025 * The regular expression used to match sub templates
13029 subTemplateRe : /<tpl(?:\sname="([\w-]+)")?>((?:.|\n)*?)<\/tpl>/gi,
13032 * Applies the passed values to a child template.
13033 * @param {String/Number} name (optional) The name or index of the child template
13034 * @param {Array/Object} values The values to be applied to the template
13035 * @return {MasterTemplate} this
13037 add : function(name, values){
13038 if(arguments.length == 1){
13039 values = arguments[0];
13042 var s = this.subs[name];
13043 s.buffer[s.buffer.length] = s.tpl.apply(values);
13048 * Applies all the passed values to a child template.
13049 * @param {String/Number} name (optional) The name or index of the child template
13050 * @param {Array} values The values to be applied to the template, this should be an array of objects.
13051 * @param {Boolean} reset (optional) True to reset the template first
13052 * @return {MasterTemplate} this
13054 fill : function(name, values, reset){
13056 if(a.length == 1 || (a.length == 2 && typeof a[1] == "boolean")){
13064 for(var i = 0, len = values.length; i < len; i++){
13065 this.add(name, values[i]);
13071 * Resets the template for reuse
13072 * @return {MasterTemplate} this
13074 reset : function(){
13076 for(var i = 0; i < this.subCount; i++){
13082 applyTemplate : function(values){
13084 var replaceIndex = -1;
13085 this.html = this.originalHtml.replace(this.subTemplateRe, function(m, name){
13086 return s[++replaceIndex].buffer.join("");
13088 return Roo.MasterTemplate.superclass.applyTemplate.call(this, values);
13091 apply : function(){
13092 return this.applyTemplate.apply(this, arguments);
13095 compile : function(){return this;}
13099 * Alias for fill().
13102 Roo.MasterTemplate.prototype.addAll = Roo.MasterTemplate.prototype.fill;
13104 * Creates a template from the passed element's value (display:none textarea, preferred) or innerHTML. e.g.
13105 * var tpl = Roo.MasterTemplate.from('element-id');
13106 * @param {String/HTMLElement} el
13107 * @param {Object} config
13110 Roo.MasterTemplate.from = function(el, config){
13111 el = Roo.getDom(el);
13112 return new Roo.MasterTemplate(el.value || el.innerHTML, config || '');
13115 * Ext JS Library 1.1.1
13116 * Copyright(c) 2006-2007, Ext JS, LLC.
13118 * Originally Released Under LGPL - original licence link has changed is not relivant.
13121 * <script type="text/javascript">
13126 * @class Roo.util.CSS
13127 * Utility class for manipulating CSS rules
13130 Roo.util.CSS = function(){
13132 var doc = document;
13134 var camelRe = /(-[a-z])/gi;
13135 var camelFn = function(m, a){ return a.charAt(1).toUpperCase(); };
13139 * Very simple dynamic creation of stylesheets from a text blob of rules. The text will wrapped in a style
13140 * tag and appended to the HEAD of the document.
13141 * @param {String} cssText The text containing the css rules
13142 * @param {String} id An id to add to the stylesheet for later removal
13143 * @return {StyleSheet}
13145 createStyleSheet : function(cssText, id){
13147 var head = doc.getElementsByTagName("head")[0];
13148 var rules = doc.createElement("style");
13149 rules.setAttribute("type", "text/css");
13151 rules.setAttribute("id", id);
13154 head.appendChild(rules);
13155 ss = rules.styleSheet;
13156 ss.cssText = cssText;
13159 rules.appendChild(doc.createTextNode(cssText));
13161 rules.cssText = cssText;
13163 head.appendChild(rules);
13164 ss = rules.styleSheet ? rules.styleSheet : (rules.sheet || doc.styleSheets[doc.styleSheets.length-1]);
13166 this.cacheStyleSheet(ss);
13171 * Removes a style or link tag by id
13172 * @param {String} id The id of the tag
13174 removeStyleSheet : function(id){
13175 var existing = doc.getElementById(id);
13177 existing.parentNode.removeChild(existing);
13182 * Dynamically swaps an existing stylesheet reference for a new one
13183 * @param {String} id The id of an existing link tag to remove
13184 * @param {String} url The href of the new stylesheet to include
13186 swapStyleSheet : function(id, url){
13187 this.removeStyleSheet(id);
13188 var ss = doc.createElement("link");
13189 ss.setAttribute("rel", "stylesheet");
13190 ss.setAttribute("type", "text/css");
13191 ss.setAttribute("id", id);
13192 ss.setAttribute("href", url);
13193 doc.getElementsByTagName("head")[0].appendChild(ss);
13197 * Refresh the rule cache if you have dynamically added stylesheets
13198 * @return {Object} An object (hash) of rules indexed by selector
13200 refreshCache : function(){
13201 return this.getRules(true);
13205 cacheStyleSheet : function(ss){
13209 try{// try catch for cross domain access issue
13210 var ssRules = ss.cssRules || ss.rules;
13211 for(var j = ssRules.length-1; j >= 0; --j){
13212 rules[ssRules[j].selectorText] = ssRules[j];
13218 * Gets all css rules for the document
13219 * @param {Boolean} refreshCache true to refresh the internal cache
13220 * @return {Object} An object (hash) of rules indexed by selector
13222 getRules : function(refreshCache){
13223 if(rules == null || refreshCache){
13225 var ds = doc.styleSheets;
13226 for(var i =0, len = ds.length; i < len; i++){
13228 this.cacheStyleSheet(ds[i]);
13236 * Gets an an individual CSS rule by selector(s)
13237 * @param {String/Array} selector The CSS selector or an array of selectors to try. The first selector that is found is returned.
13238 * @param {Boolean} refreshCache true to refresh the internal cache if you have recently updated any rules or added styles dynamically
13239 * @return {CSSRule} The CSS rule or null if one is not found
13241 getRule : function(selector, refreshCache){
13242 var rs = this.getRules(refreshCache);
13243 if(!(selector instanceof Array)){
13244 return rs[selector];
13246 for(var i = 0; i < selector.length; i++){
13247 if(rs[selector[i]]){
13248 return rs[selector[i]];
13256 * Updates a rule property
13257 * @param {String/Array} selector If it's an array it tries each selector until it finds one. Stops immediately once one is found.
13258 * @param {String} property The css property
13259 * @param {String} value The new value for the property
13260 * @return {Boolean} true If a rule was found and updated
13262 updateRule : function(selector, property, value){
13263 if(!(selector instanceof Array)){
13264 var rule = this.getRule(selector);
13266 rule.style[property.replace(camelRe, camelFn)] = value;
13270 for(var i = 0; i < selector.length; i++){
13271 if(this.updateRule(selector[i], property, value)){
13281 * Ext JS Library 1.1.1
13282 * Copyright(c) 2006-2007, Ext JS, LLC.
13284 * Originally Released Under LGPL - original licence link has changed is not relivant.
13287 * <script type="text/javascript">
13293 * @class Roo.util.ClickRepeater
13294 * @extends Roo.util.Observable
13296 * A wrapper class which can be applied to any element. Fires a "click" event while the
13297 * mouse is pressed. The interval between firings may be specified in the config but
13298 * defaults to 10 milliseconds.
13300 * Optionally, a CSS class may be applied to the element during the time it is pressed.
13302 * @cfg {String/HTMLElement/Element} el The element to act as a button.
13303 * @cfg {Number} delay The initial delay before the repeating event begins firing.
13304 * Similar to an autorepeat key delay.
13305 * @cfg {Number} interval The interval between firings of the "click" event. Default 10 ms.
13306 * @cfg {String} pressClass A CSS class name to be applied to the element while pressed.
13307 * @cfg {Boolean} accelerate True if autorepeating should start slowly and accelerate.
13308 * "interval" and "delay" are ignored. "immediate" is honored.
13309 * @cfg {Boolean} preventDefault True to prevent the default click event
13310 * @cfg {Boolean} stopDefault True to stop the default click event
13313 * 2007-02-02 jvs Original code contributed by Nige "Animal" White
13314 * 2007-02-02 jvs Renamed to ClickRepeater
13315 * 2007-02-03 jvs Modifications for FF Mac and Safari
13318 * @param {String/HTMLElement/Element} el The element to listen on
13319 * @param {Object} config
13321 Roo.util.ClickRepeater = function(el, config)
13323 this.el = Roo.get(el);
13324 this.el.unselectable();
13326 Roo.apply(this, config);
13331 * Fires when the mouse button is depressed.
13332 * @param {Roo.util.ClickRepeater} this
13334 "mousedown" : true,
13337 * Fires on a specified interval during the time the element is pressed.
13338 * @param {Roo.util.ClickRepeater} this
13343 * Fires when the mouse key is released.
13344 * @param {Roo.util.ClickRepeater} this
13349 this.el.on("mousedown", this.handleMouseDown, this);
13350 if(this.preventDefault || this.stopDefault){
13351 this.el.on("click", function(e){
13352 if(this.preventDefault){
13353 e.preventDefault();
13355 if(this.stopDefault){
13361 // allow inline handler
13363 this.on("click", this.handler, this.scope || this);
13366 Roo.util.ClickRepeater.superclass.constructor.call(this);
13369 Roo.extend(Roo.util.ClickRepeater, Roo.util.Observable, {
13372 preventDefault : true,
13373 stopDefault : false,
13377 handleMouseDown : function(){
13378 clearTimeout(this.timer);
13380 if(this.pressClass){
13381 this.el.addClass(this.pressClass);
13383 this.mousedownTime = new Date();
13385 Roo.get(document).on("mouseup", this.handleMouseUp, this);
13386 this.el.on("mouseout", this.handleMouseOut, this);
13388 this.fireEvent("mousedown", this);
13389 this.fireEvent("click", this);
13391 this.timer = this.click.defer(this.delay || this.interval, this);
13395 click : function(){
13396 this.fireEvent("click", this);
13397 this.timer = this.click.defer(this.getInterval(), this);
13401 getInterval: function(){
13402 if(!this.accelerate){
13403 return this.interval;
13405 var pressTime = this.mousedownTime.getElapsed();
13406 if(pressTime < 500){
13408 }else if(pressTime < 1700){
13410 }else if(pressTime < 2600){
13412 }else if(pressTime < 3500){
13414 }else if(pressTime < 4400){
13416 }else if(pressTime < 5300){
13418 }else if(pressTime < 6200){
13426 handleMouseOut : function(){
13427 clearTimeout(this.timer);
13428 if(this.pressClass){
13429 this.el.removeClass(this.pressClass);
13431 this.el.on("mouseover", this.handleMouseReturn, this);
13435 handleMouseReturn : function(){
13436 this.el.un("mouseover", this.handleMouseReturn);
13437 if(this.pressClass){
13438 this.el.addClass(this.pressClass);
13444 handleMouseUp : function(){
13445 clearTimeout(this.timer);
13446 this.el.un("mouseover", this.handleMouseReturn);
13447 this.el.un("mouseout", this.handleMouseOut);
13448 Roo.get(document).un("mouseup", this.handleMouseUp);
13449 this.el.removeClass(this.pressClass);
13450 this.fireEvent("mouseup", this);
13454 * Ext JS Library 1.1.1
13455 * Copyright(c) 2006-2007, Ext JS, LLC.
13457 * Originally Released Under LGPL - original licence link has changed is not relivant.
13460 * <script type="text/javascript">
13465 * @class Roo.KeyNav
13466 * <p>Provides a convenient wrapper for normalized keyboard navigation. KeyNav allows you to bind
13467 * navigation keys to function calls that will get called when the keys are pressed, providing an easy
13468 * way to implement custom navigation schemes for any UI component.</p>
13469 * <p>The following are all of the possible keys that can be implemented: enter, left, right, up, down, tab, esc,
13470 * pageUp, pageDown, del, home, end. Usage:</p>
13472 var nav = new Roo.KeyNav("my-element", {
13473 "left" : function(e){
13474 this.moveLeft(e.ctrlKey);
13476 "right" : function(e){
13477 this.moveRight(e.ctrlKey);
13479 "enter" : function(e){
13486 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13487 * @param {Object} config The config
13489 Roo.KeyNav = function(el, config){
13490 this.el = Roo.get(el);
13491 Roo.apply(this, config);
13492 if(!this.disabled){
13493 this.disabled = true;
13498 Roo.KeyNav.prototype = {
13500 * @cfg {Boolean} disabled
13501 * True to disable this KeyNav instance (defaults to false)
13505 * @cfg {String} defaultEventAction
13506 * The method to call on the {@link Roo.EventObject} after this KeyNav intercepts a key. Valid values are
13507 * {@link Roo.EventObject#stopEvent}, {@link Roo.EventObject#preventDefault} and
13508 * {@link Roo.EventObject#stopPropagation} (defaults to 'stopEvent')
13510 defaultEventAction: "stopEvent",
13512 * @cfg {Boolean} forceKeyDown
13513 * Handle the keydown event instead of keypress (defaults to false). KeyNav automatically does this for IE since
13514 * IE does not propagate special keys on keypress, but setting this to true will force other browsers to also
13515 * handle keydown instead of keypress.
13517 forceKeyDown : false,
13520 prepareEvent : function(e){
13521 var k = e.getKey();
13522 var h = this.keyToHandler[k];
13523 //if(h && this[h]){
13524 // e.stopPropagation();
13526 if(Roo.isSafari && h && k >= 37 && k <= 40){
13532 relay : function(e){
13533 var k = e.getKey();
13534 var h = this.keyToHandler[k];
13536 if(this.doRelay(e, this[h], h) !== true){
13537 e[this.defaultEventAction]();
13543 doRelay : function(e, h, hname){
13544 return h.call(this.scope || this, e);
13547 // possible handlers
13561 // quick lookup hash
13578 * Enable this KeyNav
13580 enable: function(){
13582 // ie won't do special keys on keypress, no one else will repeat keys with keydown
13583 // the EventObject will normalize Safari automatically
13584 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13585 this.el.on("keydown", this.relay, this);
13587 this.el.on("keydown", this.prepareEvent, this);
13588 this.el.on("keypress", this.relay, this);
13590 this.disabled = false;
13595 * Disable this KeyNav
13597 disable: function(){
13598 if(!this.disabled){
13599 if(this.forceKeyDown || Roo.isIE || Roo.isAir){
13600 this.el.un("keydown", this.relay);
13602 this.el.un("keydown", this.prepareEvent);
13603 this.el.un("keypress", this.relay);
13605 this.disabled = true;
13610 * Ext JS Library 1.1.1
13611 * Copyright(c) 2006-2007, Ext JS, LLC.
13613 * Originally Released Under LGPL - original licence link has changed is not relivant.
13616 * <script type="text/javascript">
13621 * @class Roo.KeyMap
13622 * Handles mapping keys to actions for an element. One key map can be used for multiple actions.
13623 * The constructor accepts the same config object as defined by {@link #addBinding}.
13624 * If you bind a callback function to a KeyMap, anytime the KeyMap handles an expected key
13625 * combination it will call the function with this signature (if the match is a multi-key
13626 * combination the callback will still be called only once): (String key, Roo.EventObject e)
13627 * A KeyMap can also handle a string representation of keys.<br />
13630 // map one key by key code
13631 var map = new Roo.KeyMap("my-element", {
13632 key: 13, // or Roo.EventObject.ENTER
13637 // map multiple keys to one action by string
13638 var map = new Roo.KeyMap("my-element", {
13644 // map multiple keys to multiple actions by strings and array of codes
13645 var map = new Roo.KeyMap("my-element", [
13648 fn: function(){ alert("Return was pressed"); }
13651 fn: function(){ alert('a, b or c was pressed'); }
13656 fn: function(){ alert('Control + shift + tab was pressed.'); }
13660 * <b>Note: A KeyMap starts enabled</b>
13662 * @param {String/HTMLElement/Roo.Element} el The element to bind to
13663 * @param {Object} config The config (see {@link #addBinding})
13664 * @param {String} eventName (optional) The event to bind to (defaults to "keydown")
13666 Roo.KeyMap = function(el, config, eventName){
13667 this.el = Roo.get(el);
13668 this.eventName = eventName || "keydown";
13669 this.bindings = [];
13671 this.addBinding(config);
13676 Roo.KeyMap.prototype = {
13678 * True to stop the event from bubbling and prevent the default browser action if the
13679 * key was handled by the KeyMap (defaults to false)
13685 * Add a new binding to this KeyMap. The following config object properties are supported:
13687 Property Type Description
13688 ---------- --------------- ----------------------------------------------------------------------
13689 key String/Array A single keycode or an array of keycodes to handle
13690 shift Boolean True to handle key only when shift is pressed (defaults to false)
13691 ctrl Boolean True to handle key only when ctrl is pressed (defaults to false)
13692 alt Boolean True to handle key only when alt is pressed (defaults to false)
13693 fn Function The function to call when KeyMap finds the expected key combination
13694 scope Object The scope of the callback function
13700 var map = new Roo.KeyMap(document, {
13701 key: Roo.EventObject.ENTER,
13706 //Add a new binding to the existing KeyMap later
13714 * @param {Object/Array} config A single KeyMap config or an array of configs
13716 addBinding : function(config){
13717 if(config instanceof Array){
13718 for(var i = 0, len = config.length; i < len; i++){
13719 this.addBinding(config[i]);
13723 var keyCode = config.key,
13724 shift = config.shift,
13725 ctrl = config.ctrl,
13728 scope = config.scope;
13729 if(typeof keyCode == "string"){
13731 var keyString = keyCode.toUpperCase();
13732 for(var j = 0, len = keyString.length; j < len; j++){
13733 ks.push(keyString.charCodeAt(j));
13737 var keyArray = keyCode instanceof Array;
13738 var handler = function(e){
13739 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
13740 var k = e.getKey();
13742 for(var i = 0, len = keyCode.length; i < len; i++){
13743 if(keyCode[i] == k){
13744 if(this.stopEvent){
13747 fn.call(scope || window, k, e);
13753 if(this.stopEvent){
13756 fn.call(scope || window, k, e);
13761 this.bindings.push(handler);
13765 * Shorthand for adding a single key listener
13766 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the
13767 * following options:
13768 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
13769 * @param {Function} fn The function to call
13770 * @param {Object} scope (optional) The scope of the function
13772 on : function(key, fn, scope){
13773 var keyCode, shift, ctrl, alt;
13774 if(typeof key == "object" && !(key instanceof Array)){
13793 handleKeyDown : function(e){
13794 if(this.enabled){ //just in case
13795 var b = this.bindings;
13796 for(var i = 0, len = b.length; i < len; i++){
13797 b[i].call(this, e);
13803 * Returns true if this KeyMap is enabled
13804 * @return {Boolean}
13806 isEnabled : function(){
13807 return this.enabled;
13811 * Enables this KeyMap
13813 enable: function(){
13815 this.el.on(this.eventName, this.handleKeyDown, this);
13816 this.enabled = true;
13821 * Disable this KeyMap
13823 disable: function(){
13825 this.el.removeListener(this.eventName, this.handleKeyDown, this);
13826 this.enabled = false;
13831 * Ext JS Library 1.1.1
13832 * Copyright(c) 2006-2007, Ext JS, LLC.
13834 * Originally Released Under LGPL - original licence link has changed is not relivant.
13837 * <script type="text/javascript">
13842 * @class Roo.util.TextMetrics
13843 * Provides precise pixel measurements for blocks of text so that you can determine exactly how high and
13844 * wide, in pixels, a given block of text will be.
13847 Roo.util.TextMetrics = function(){
13851 * Measures the size of the specified text
13852 * @param {String/HTMLElement} el The element, dom node or id from which to copy existing CSS styles
13853 * that can affect the size of the rendered text
13854 * @param {String} text The text to measure
13855 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13856 * in order to accurately measure the text height
13857 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13859 measure : function(el, text, fixedWidth){
13861 shared = Roo.util.TextMetrics.Instance(el, fixedWidth);
13864 shared.setFixedWidth(fixedWidth || 'auto');
13865 return shared.getSize(text);
13869 * Return a unique TextMetrics instance that can be bound directly to an element and reused. This reduces
13870 * the overhead of multiple calls to initialize the style properties on each measurement.
13871 * @param {String/HTMLElement} el The element, dom node or id that the instance will be bound to
13872 * @param {Number} fixedWidth (optional) If the text will be multiline, you have to set a fixed width
13873 * in order to accurately measure the text height
13874 * @return {Roo.util.TextMetrics.Instance} instance The new instance
13876 createInstance : function(el, fixedWidth){
13877 return Roo.util.TextMetrics.Instance(el, fixedWidth);
13884 Roo.util.TextMetrics.Instance = function(bindTo, fixedWidth){
13885 var ml = new Roo.Element(document.createElement('div'));
13886 document.body.appendChild(ml.dom);
13887 ml.position('absolute');
13888 ml.setLeftTop(-1000, -1000);
13892 ml.setWidth(fixedWidth);
13897 * Returns the size of the specified text based on the internal element's style and width properties
13898 * @memberOf Roo.util.TextMetrics.Instance#
13899 * @param {String} text The text to measure
13900 * @return {Object} An object containing the text's size {width: (width), height: (height)}
13902 getSize : function(text){
13904 var s = ml.getSize();
13910 * Binds this TextMetrics instance to an element from which to copy existing CSS styles
13911 * that can affect the size of the rendered text
13912 * @memberOf Roo.util.TextMetrics.Instance#
13913 * @param {String/HTMLElement} el The element, dom node or id
13915 bind : function(el){
13917 Roo.fly(el).getStyles('font-size','font-style', 'font-weight', 'font-family','line-height')
13922 * Sets a fixed width on the internal measurement element. If the text will be multiline, you have
13923 * to set a fixed width in order to accurately measure the text height.
13924 * @memberOf Roo.util.TextMetrics.Instance#
13925 * @param {Number} width The width to set on the element
13927 setFixedWidth : function(width){
13928 ml.setWidth(width);
13932 * Returns the measured width of the specified text
13933 * @memberOf Roo.util.TextMetrics.Instance#
13934 * @param {String} text The text to measure
13935 * @return {Number} width The width in pixels
13937 getWidth : function(text){
13938 ml.dom.style.width = 'auto';
13939 return this.getSize(text).width;
13943 * Returns the measured height of the specified text. For multiline text, be sure to call
13944 * {@link #setFixedWidth} if necessary.
13945 * @memberOf Roo.util.TextMetrics.Instance#
13946 * @param {String} text The text to measure
13947 * @return {Number} height The height in pixels
13949 getHeight : function(text){
13950 return this.getSize(text).height;
13954 instance.bind(bindTo);
13959 // backwards compat
13960 Roo.Element.measureText = Roo.util.TextMetrics.measure;/*
13962 * Ext JS Library 1.1.1
13963 * Copyright(c) 2006-2007, Ext JS, LLC.
13965 * Originally Released Under LGPL - original licence link has changed is not relivant.
13968 * <script type="text/javascript">
13972 * @class Roo.state.Provider
13973 * Abstract base class for state provider implementations. This class provides methods
13974 * for encoding and decoding <b>typed</b> variables including dates and defines the
13975 * Provider interface.
13977 Roo.state.Provider = function(){
13979 * @event statechange
13980 * Fires when a state change occurs.
13981 * @param {Provider} this This state provider
13982 * @param {String} key The state key which was changed
13983 * @param {String} value The encoded value for the state
13986 "statechange": true
13989 Roo.state.Provider.superclass.constructor.call(this);
13991 Roo.extend(Roo.state.Provider, Roo.util.Observable, {
13993 * Returns the current value for a key
13994 * @param {String} name The key name
13995 * @param {Mixed} defaultValue A default value to return if the key's value is not found
13996 * @return {Mixed} The state data
13998 get : function(name, defaultValue){
13999 return typeof this.state[name] == "undefined" ?
14000 defaultValue : this.state[name];
14004 * Clears a value from the state
14005 * @param {String} name The key name
14007 clear : function(name){
14008 delete this.state[name];
14009 this.fireEvent("statechange", this, name, null);
14013 * Sets the value for a key
14014 * @param {String} name The key name
14015 * @param {Mixed} value The value to set
14017 set : function(name, value){
14018 this.state[name] = value;
14019 this.fireEvent("statechange", this, name, value);
14023 * Decodes a string previously encoded with {@link #encodeValue}.
14024 * @param {String} value The value to decode
14025 * @return {Mixed} The decoded value
14027 decodeValue : function(cookie){
14028 var re = /^(a|n|d|b|s|o)\:(.*)$/;
14029 var matches = re.exec(unescape(cookie));
14030 if(!matches || !matches[1]) return; // non state cookie
14031 var type = matches[1];
14032 var v = matches[2];
14035 return parseFloat(v);
14037 return new Date(Date.parse(v));
14042 var values = v.split("^");
14043 for(var i = 0, len = values.length; i < len; i++){
14044 all.push(this.decodeValue(values[i]));
14049 var values = v.split("^");
14050 for(var i = 0, len = values.length; i < len; i++){
14051 var kv = values[i].split("=");
14052 all[kv[0]] = this.decodeValue(kv[1]);
14061 * Encodes a value including type information. Decode with {@link #decodeValue}.
14062 * @param {Mixed} value The value to encode
14063 * @return {String} The encoded value
14065 encodeValue : function(v){
14067 if(typeof v == "number"){
14069 }else if(typeof v == "boolean"){
14070 enc = "b:" + (v ? "1" : "0");
14071 }else if(v instanceof Date){
14072 enc = "d:" + v.toGMTString();
14073 }else if(v instanceof Array){
14075 for(var i = 0, len = v.length; i < len; i++){
14076 flat += this.encodeValue(v[i]);
14077 if(i != len-1) flat += "^";
14080 }else if(typeof v == "object"){
14083 if(typeof v[key] != "function"){
14084 flat += key + "=" + this.encodeValue(v[key]) + "^";
14087 enc = "o:" + flat.substring(0, flat.length-1);
14091 return escape(enc);
14097 * Ext JS Library 1.1.1
14098 * Copyright(c) 2006-2007, Ext JS, LLC.
14100 * Originally Released Under LGPL - original licence link has changed is not relivant.
14103 * <script type="text/javascript">
14106 * @class Roo.state.Manager
14107 * This is the global state manager. By default all components that are "state aware" check this class
14108 * for state information if you don't pass them a custom state provider. In order for this class
14109 * to be useful, it must be initialized with a provider when your application initializes.
14111 // in your initialization function
14113 Roo.state.Manager.setProvider(new Roo.state.CookieProvider());
14115 // supposed you have a {@link Roo.BorderLayout}
14116 var layout = new Roo.BorderLayout(...);
14117 layout.restoreState();
14118 // or a {Roo.BasicDialog}
14119 var dialog = new Roo.BasicDialog(...);
14120 dialog.restoreState();
14124 Roo.state.Manager = function(){
14125 var provider = new Roo.state.Provider();
14129 * Configures the default state provider for your application
14130 * @param {Provider} stateProvider The state provider to set
14132 setProvider : function(stateProvider){
14133 provider = stateProvider;
14137 * Returns the current value for a key
14138 * @param {String} name The key name
14139 * @param {Mixed} defaultValue The default value to return if the key lookup does not match
14140 * @return {Mixed} The state data
14142 get : function(key, defaultValue){
14143 return provider.get(key, defaultValue);
14147 * Sets the value for a key
14148 * @param {String} name The key name
14149 * @param {Mixed} value The state data
14151 set : function(key, value){
14152 provider.set(key, value);
14156 * Clears a value from the state
14157 * @param {String} name The key name
14159 clear : function(key){
14160 provider.clear(key);
14164 * Gets the currently configured state provider
14165 * @return {Provider} The state provider
14167 getProvider : function(){
14174 * Ext JS Library 1.1.1
14175 * Copyright(c) 2006-2007, Ext JS, LLC.
14177 * Originally Released Under LGPL - original licence link has changed is not relivant.
14180 * <script type="text/javascript">
14183 * @class Roo.state.CookieProvider
14184 * @extends Roo.state.Provider
14185 * The default Provider implementation which saves state via cookies.
14188 var cp = new Roo.state.CookieProvider({
14190 expires: new Date(new Date().getTime()+(1000*60*60*24*30)); //30 days
14191 domain: "roojs.com"
14193 Roo.state.Manager.setProvider(cp);
14195 * @cfg {String} path The path for which the cookie is active (defaults to root '/' which makes it active for all pages in the site)
14196 * @cfg {Date} expires The cookie expiration date (defaults to 7 days from now)
14197 * @cfg {String} domain The domain to save the cookie for. Note that you cannot specify a different domain than
14198 * your page is on, but you can specify a sub-domain, or simply the domain itself like 'roojs.com' to include
14199 * all sub-domains if you need to access cookies across different sub-domains (defaults to null which uses the same
14200 * domain the page is running on including the 'www' like 'www.roojs.com')
14201 * @cfg {Boolean} secure True if the site is using SSL (defaults to false)
14203 * Create a new CookieProvider
14204 * @param {Object} config The configuration object
14206 Roo.state.CookieProvider = function(config){
14207 Roo.state.CookieProvider.superclass.constructor.call(this);
14209 this.expires = new Date(new Date().getTime()+(1000*60*60*24*7)); //7 days
14210 this.domain = null;
14211 this.secure = false;
14212 Roo.apply(this, config);
14213 this.state = this.readCookies();
14216 Roo.extend(Roo.state.CookieProvider, Roo.state.Provider, {
14218 set : function(name, value){
14219 if(typeof value == "undefined" || value === null){
14223 this.setCookie(name, value);
14224 Roo.state.CookieProvider.superclass.set.call(this, name, value);
14228 clear : function(name){
14229 this.clearCookie(name);
14230 Roo.state.CookieProvider.superclass.clear.call(this, name);
14234 readCookies : function(){
14236 var c = document.cookie + ";";
14237 var re = /\s?(.*?)=(.*?);/g;
14239 while((matches = re.exec(c)) != null){
14240 var name = matches[1];
14241 var value = matches[2];
14242 if(name && name.substring(0,3) == "ys-"){
14243 cookies[name.substr(3)] = this.decodeValue(value);
14250 setCookie : function(name, value){
14251 document.cookie = "ys-"+ name + "=" + this.encodeValue(value) +
14252 ((this.expires == null) ? "" : ("; expires=" + this.expires.toGMTString())) +
14253 ((this.path == null) ? "" : ("; path=" + this.path)) +
14254 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14255 ((this.secure == true) ? "; secure" : "");
14259 clearCookie : function(name){
14260 document.cookie = "ys-" + name + "=null; expires=Thu, 01-Jan-70 00:00:01 GMT" +
14261 ((this.path == null) ? "" : ("; path=" + this.path)) +
14262 ((this.domain == null) ? "" : ("; domain=" + this.domain)) +
14263 ((this.secure == true) ? "; secure" : "");
14267 * Ext JS Library 1.1.1
14268 * Copyright(c) 2006-2007, Ext JS, LLC.
14270 * Originally Released Under LGPL - original licence link has changed is not relivant.
14273 * <script type="text/javascript">
14279 * These classes are derivatives of the similarly named classes in the YUI Library.
14280 * The original license:
14281 * Copyright (c) 2006, Yahoo! Inc. All rights reserved.
14282 * Code licensed under the BSD License:
14283 * http://developer.yahoo.net/yui/license.txt
14288 var Event=Roo.EventManager;
14289 var Dom=Roo.lib.Dom;
14292 * @class Roo.dd.DragDrop
14293 * Defines the interface and base operation of items that that can be
14294 * dragged or can be drop targets. It was designed to be extended, overriding
14295 * the event handlers for startDrag, onDrag, onDragOver and onDragOut.
14296 * Up to three html elements can be associated with a DragDrop instance:
14298 * <li>linked element: the element that is passed into the constructor.
14299 * This is the element which defines the boundaries for interaction with
14300 * other DragDrop objects.</li>
14301 * <li>handle element(s): The drag operation only occurs if the element that
14302 * was clicked matches a handle element. By default this is the linked
14303 * element, but there are times that you will want only a portion of the
14304 * linked element to initiate the drag operation, and the setHandleElId()
14305 * method provides a way to define this.</li>
14306 * <li>drag element: this represents the element that would be moved along
14307 * with the cursor during a drag operation. By default, this is the linked
14308 * element itself as in {@link Roo.dd.DD}. setDragElId() lets you define
14309 * a separate element that would be moved, as in {@link Roo.dd.DDProxy}.
14312 * This class should not be instantiated until the onload event to ensure that
14313 * the associated elements are available.
14314 * The following would define a DragDrop obj that would interact with any
14315 * other DragDrop obj in the "group1" group:
14317 * dd = new Roo.dd.DragDrop("div1", "group1");
14319 * Since none of the event handlers have been implemented, nothing would
14320 * actually happen if you were to run the code above. Normally you would
14321 * override this class or one of the default implementations, but you can
14322 * also override the methods you want on an instance of the class...
14324 * dd.onDragDrop = function(e, id) {
14325 * alert("dd was dropped on " + id);
14329 * @param {String} id of the element that is linked to this instance
14330 * @param {String} sGroup the group of related DragDrop objects
14331 * @param {object} config an object containing configurable attributes
14332 * Valid properties for DragDrop:
14333 * padding, isTarget, maintainOffset, primaryButtonOnly
14335 Roo.dd.DragDrop = function(id, sGroup, config) {
14337 this.init(id, sGroup, config);
14341 Roo.dd.DragDrop.prototype = {
14344 * The id of the element associated with this object. This is what we
14345 * refer to as the "linked element" because the size and position of
14346 * this element is used to determine when the drag and drop objects have
14354 * Configuration attributes passed into the constructor
14361 * The id of the element that will be dragged. By default this is same
14362 * as the linked element , but could be changed to another element. Ex:
14364 * @property dragElId
14371 * the id of the element that initiates the drag operation. By default
14372 * this is the linked element, but could be changed to be a child of this
14373 * element. This lets us do things like only starting the drag when the
14374 * header element within the linked html element is clicked.
14375 * @property handleElId
14382 * An associative array of HTML tags that will be ignored if clicked.
14383 * @property invalidHandleTypes
14384 * @type {string: string}
14386 invalidHandleTypes: null,
14389 * An associative array of ids for elements that will be ignored if clicked
14390 * @property invalidHandleIds
14391 * @type {string: string}
14393 invalidHandleIds: null,
14396 * An indexted array of css class names for elements that will be ignored
14398 * @property invalidHandleClasses
14401 invalidHandleClasses: null,
14404 * The linked element's absolute X position at the time the drag was
14406 * @property startPageX
14413 * The linked element's absolute X position at the time the drag was
14415 * @property startPageY
14422 * The group defines a logical collection of DragDrop objects that are
14423 * related. Instances only get events when interacting with other
14424 * DragDrop object in the same group. This lets us define multiple
14425 * groups using a single DragDrop subclass if we want.
14427 * @type {string: string}
14432 * Individual drag/drop instances can be locked. This will prevent
14433 * onmousedown start drag.
14441 * Lock this instance
14444 lock: function() { this.locked = true; },
14447 * Unlock this instace
14450 unlock: function() { this.locked = false; },
14453 * By default, all insances can be a drop target. This can be disabled by
14454 * setting isTarget to false.
14461 * The padding configured for this drag and drop object for calculating
14462 * the drop zone intersection with this object.
14469 * Cached reference to the linked element
14470 * @property _domRef
14476 * Internal typeof flag
14477 * @property __ygDragDrop
14480 __ygDragDrop: true,
14483 * Set to true when horizontal contraints are applied
14484 * @property constrainX
14491 * Set to true when vertical contraints are applied
14492 * @property constrainY
14499 * The left constraint
14507 * The right constraint
14515 * The up constraint
14524 * The down constraint
14532 * Maintain offsets when we resetconstraints. Set to true when you want
14533 * the position of the element relative to its parent to stay the same
14534 * when the page changes
14536 * @property maintainOffset
14539 maintainOffset: false,
14542 * Array of pixel locations the element will snap to if we specified a
14543 * horizontal graduation/interval. This array is generated automatically
14544 * when you define a tick interval.
14551 * Array of pixel locations the element will snap to if we specified a
14552 * vertical graduation/interval. This array is generated automatically
14553 * when you define a tick interval.
14560 * By default the drag and drop instance will only respond to the primary
14561 * button click (left button for a right-handed mouse). Set to true to
14562 * allow drag and drop to start with any mouse click that is propogated
14564 * @property primaryButtonOnly
14567 primaryButtonOnly: true,
14570 * The availabe property is false until the linked dom element is accessible.
14571 * @property available
14577 * By default, drags can only be initiated if the mousedown occurs in the
14578 * region the linked element is. This is done in part to work around a
14579 * bug in some browsers that mis-report the mousedown if the previous
14580 * mouseup happened outside of the window. This property is set to true
14581 * if outer handles are defined.
14583 * @property hasOuterHandles
14587 hasOuterHandles: false,
14590 * Code that executes immediately before the startDrag event
14591 * @method b4StartDrag
14594 b4StartDrag: function(x, y) { },
14597 * Abstract method called after a drag/drop object is clicked
14598 * and the drag or mousedown time thresholds have beeen met.
14599 * @method startDrag
14600 * @param {int} X click location
14601 * @param {int} Y click location
14603 startDrag: function(x, y) { /* override this */ },
14606 * Code that executes immediately before the onDrag event
14610 b4Drag: function(e) { },
14613 * Abstract method called during the onMouseMove event while dragging an
14616 * @param {Event} e the mousemove event
14618 onDrag: function(e) { /* override this */ },
14621 * Abstract method called when this element fist begins hovering over
14622 * another DragDrop obj
14623 * @method onDragEnter
14624 * @param {Event} e the mousemove event
14625 * @param {String|DragDrop[]} id In POINT mode, the element
14626 * id this is hovering over. In INTERSECT mode, an array of one or more
14627 * dragdrop items being hovered over.
14629 onDragEnter: function(e, id) { /* override this */ },
14632 * Code that executes immediately before the onDragOver event
14633 * @method b4DragOver
14636 b4DragOver: function(e) { },
14639 * Abstract method called when this element is hovering over another
14641 * @method onDragOver
14642 * @param {Event} e the mousemove event
14643 * @param {String|DragDrop[]} id In POINT mode, the element
14644 * id this is hovering over. In INTERSECT mode, an array of dd items
14645 * being hovered over.
14647 onDragOver: function(e, id) { /* override this */ },
14650 * Code that executes immediately before the onDragOut event
14651 * @method b4DragOut
14654 b4DragOut: function(e) { },
14657 * Abstract method called when we are no longer hovering over an element
14658 * @method onDragOut
14659 * @param {Event} e the mousemove event
14660 * @param {String|DragDrop[]} id In POINT mode, the element
14661 * id this was hovering over. In INTERSECT mode, an array of dd items
14662 * that the mouse is no longer over.
14664 onDragOut: function(e, id) { /* override this */ },
14667 * Code that executes immediately before the onDragDrop event
14668 * @method b4DragDrop
14671 b4DragDrop: function(e) { },
14674 * Abstract method called when this item is dropped on another DragDrop
14676 * @method onDragDrop
14677 * @param {Event} e the mouseup event
14678 * @param {String|DragDrop[]} id In POINT mode, the element
14679 * id this was dropped on. In INTERSECT mode, an array of dd items this
14682 onDragDrop: function(e, id) { /* override this */ },
14685 * Abstract method called when this item is dropped on an area with no
14687 * @method onInvalidDrop
14688 * @param {Event} e the mouseup event
14690 onInvalidDrop: function(e) { /* override this */ },
14693 * Code that executes immediately before the endDrag event
14694 * @method b4EndDrag
14697 b4EndDrag: function(e) { },
14700 * Fired when we are done dragging the object
14702 * @param {Event} e the mouseup event
14704 endDrag: function(e) { /* override this */ },
14707 * Code executed immediately before the onMouseDown event
14708 * @method b4MouseDown
14709 * @param {Event} e the mousedown event
14712 b4MouseDown: function(e) { },
14715 * Event handler that fires when a drag/drop obj gets a mousedown
14716 * @method onMouseDown
14717 * @param {Event} e the mousedown event
14719 onMouseDown: function(e) { /* override this */ },
14722 * Event handler that fires when a drag/drop obj gets a mouseup
14723 * @method onMouseUp
14724 * @param {Event} e the mouseup event
14726 onMouseUp: function(e) { /* override this */ },
14729 * Override the onAvailable method to do what is needed after the initial
14730 * position was determined.
14731 * @method onAvailable
14733 onAvailable: function () {
14737 * Provides default constraint padding to "constrainTo" elements (defaults to {left: 0, right:0, top:0, bottom:0}).
14740 defaultPadding : {left:0, right:0, top:0, bottom:0},
14743 * Initializes the drag drop object's constraints to restrict movement to a certain element.
14747 var dd = new Roo.dd.DDProxy("dragDiv1", "proxytest",
14748 { dragElId: "existingProxyDiv" });
14749 dd.startDrag = function(){
14750 this.constrainTo("parent-id");
14753 * Or you can initalize it using the {@link Roo.Element} object:
14755 Roo.get("dragDiv1").initDDProxy("proxytest", {dragElId: "existingProxyDiv"}, {
14756 startDrag : function(){
14757 this.constrainTo("parent-id");
14761 * @param {String/HTMLElement/Element} constrainTo The element to constrain to.
14762 * @param {Object/Number} pad (optional) Pad provides a way to specify "padding" of the constraints,
14763 * and can be either a number for symmetrical padding (4 would be equal to {left:4, right:4, top:4, bottom:4}) or
14764 * an object containing the sides to pad. For example: {right:10, bottom:10}
14765 * @param {Boolean} inContent (optional) Constrain the draggable in the content box of the element (inside padding and borders)
14767 constrainTo : function(constrainTo, pad, inContent){
14768 if(typeof pad == "number"){
14769 pad = {left: pad, right:pad, top:pad, bottom:pad};
14771 pad = pad || this.defaultPadding;
14772 var b = Roo.get(this.getEl()).getBox();
14773 var ce = Roo.get(constrainTo);
14774 var s = ce.getScroll();
14775 var c, cd = ce.dom;
14776 if(cd == document.body){
14777 c = { x: s.left, y: s.top, width: Roo.lib.Dom.getViewWidth(), height: Roo.lib.Dom.getViewHeight()};
14780 c = {x : xy[0]+s.left, y: xy[1]+s.top, width: cd.clientWidth, height: cd.clientHeight};
14784 var topSpace = b.y - c.y;
14785 var leftSpace = b.x - c.x;
14787 this.resetConstraints();
14788 this.setXConstraint(leftSpace - (pad.left||0), // left
14789 c.width - leftSpace - b.width - (pad.right||0) //right
14791 this.setYConstraint(topSpace - (pad.top||0), //top
14792 c.height - topSpace - b.height - (pad.bottom||0) //bottom
14797 * Returns a reference to the linked element
14799 * @return {HTMLElement} the html element
14801 getEl: function() {
14802 if (!this._domRef) {
14803 this._domRef = Roo.getDom(this.id);
14806 return this._domRef;
14810 * Returns a reference to the actual element to drag. By default this is
14811 * the same as the html element, but it can be assigned to another
14812 * element. An example of this can be found in Roo.dd.DDProxy
14813 * @method getDragEl
14814 * @return {HTMLElement} the html element
14816 getDragEl: function() {
14817 return Roo.getDom(this.dragElId);
14821 * Sets up the DragDrop object. Must be called in the constructor of any
14822 * Roo.dd.DragDrop subclass
14824 * @param id the id of the linked element
14825 * @param {String} sGroup the group of related items
14826 * @param {object} config configuration attributes
14828 init: function(id, sGroup, config) {
14829 this.initTarget(id, sGroup, config);
14830 Event.on(this.id, "mousedown", this.handleMouseDown, this);
14831 // Event.on(this.id, "selectstart", Event.preventDefault);
14835 * Initializes Targeting functionality only... the object does not
14836 * get a mousedown handler.
14837 * @method initTarget
14838 * @param id the id of the linked element
14839 * @param {String} sGroup the group of related items
14840 * @param {object} config configuration attributes
14842 initTarget: function(id, sGroup, config) {
14844 // configuration attributes
14845 this.config = config || {};
14847 // create a local reference to the drag and drop manager
14848 this.DDM = Roo.dd.DDM;
14849 // initialize the groups array
14852 // assume that we have an element reference instead of an id if the
14853 // parameter is not a string
14854 if (typeof id !== "string") {
14861 // add to an interaction group
14862 this.addToGroup((sGroup) ? sGroup : "default");
14864 // We don't want to register this as the handle with the manager
14865 // so we just set the id rather than calling the setter.
14866 this.handleElId = id;
14868 // the linked element is the element that gets dragged by default
14869 this.setDragElId(id);
14871 // by default, clicked anchors will not start drag operations.
14872 this.invalidHandleTypes = { A: "A" };
14873 this.invalidHandleIds = {};
14874 this.invalidHandleClasses = [];
14876 this.applyConfig();
14878 this.handleOnAvailable();
14882 * Applies the configuration parameters that were passed into the constructor.
14883 * This is supposed to happen at each level through the inheritance chain. So
14884 * a DDProxy implentation will execute apply config on DDProxy, DD, and
14885 * DragDrop in order to get all of the parameters that are available in
14887 * @method applyConfig
14889 applyConfig: function() {
14891 // configurable properties:
14892 // padding, isTarget, maintainOffset, primaryButtonOnly
14893 this.padding = this.config.padding || [0, 0, 0, 0];
14894 this.isTarget = (this.config.isTarget !== false);
14895 this.maintainOffset = (this.config.maintainOffset);
14896 this.primaryButtonOnly = (this.config.primaryButtonOnly !== false);
14901 * Executed when the linked element is available
14902 * @method handleOnAvailable
14905 handleOnAvailable: function() {
14906 this.available = true;
14907 this.resetConstraints();
14908 this.onAvailable();
14912 * Configures the padding for the target zone in px. Effectively expands
14913 * (or reduces) the virtual object size for targeting calculations.
14914 * Supports css-style shorthand; if only one parameter is passed, all sides
14915 * will have that padding, and if only two are passed, the top and bottom
14916 * will have the first param, the left and right the second.
14917 * @method setPadding
14918 * @param {int} iTop Top pad
14919 * @param {int} iRight Right pad
14920 * @param {int} iBot Bot pad
14921 * @param {int} iLeft Left pad
14923 setPadding: function(iTop, iRight, iBot, iLeft) {
14924 // this.padding = [iLeft, iRight, iTop, iBot];
14925 if (!iRight && 0 !== iRight) {
14926 this.padding = [iTop, iTop, iTop, iTop];
14927 } else if (!iBot && 0 !== iBot) {
14928 this.padding = [iTop, iRight, iTop, iRight];
14930 this.padding = [iTop, iRight, iBot, iLeft];
14935 * Stores the initial placement of the linked element.
14936 * @method setInitialPosition
14937 * @param {int} diffX the X offset, default 0
14938 * @param {int} diffY the Y offset, default 0
14940 setInitPosition: function(diffX, diffY) {
14941 var el = this.getEl();
14943 if (!this.DDM.verifyEl(el)) {
14947 var dx = diffX || 0;
14948 var dy = diffY || 0;
14950 var p = Dom.getXY( el );
14952 this.initPageX = p[0] - dx;
14953 this.initPageY = p[1] - dy;
14955 this.lastPageX = p[0];
14956 this.lastPageY = p[1];
14959 this.setStartPosition(p);
14963 * Sets the start position of the element. This is set when the obj
14964 * is initialized, the reset when a drag is started.
14965 * @method setStartPosition
14966 * @param pos current position (from previous lookup)
14969 setStartPosition: function(pos) {
14970 var p = pos || Dom.getXY( this.getEl() );
14971 this.deltaSetXY = null;
14973 this.startPageX = p[0];
14974 this.startPageY = p[1];
14978 * Add this instance to a group of related drag/drop objects. All
14979 * instances belong to at least one group, and can belong to as many
14980 * groups as needed.
14981 * @method addToGroup
14982 * @param sGroup {string} the name of the group
14984 addToGroup: function(sGroup) {
14985 this.groups[sGroup] = true;
14986 this.DDM.regDragDrop(this, sGroup);
14990 * Remove's this instance from the supplied interaction group
14991 * @method removeFromGroup
14992 * @param {string} sGroup The group to drop
14994 removeFromGroup: function(sGroup) {
14995 if (this.groups[sGroup]) {
14996 delete this.groups[sGroup];
14999 this.DDM.removeDDFromGroup(this, sGroup);
15003 * Allows you to specify that an element other than the linked element
15004 * will be moved with the cursor during a drag
15005 * @method setDragElId
15006 * @param id {string} the id of the element that will be used to initiate the drag
15008 setDragElId: function(id) {
15009 this.dragElId = id;
15013 * Allows you to specify a child of the linked element that should be
15014 * used to initiate the drag operation. An example of this would be if
15015 * you have a content div with text and links. Clicking anywhere in the
15016 * content area would normally start the drag operation. Use this method
15017 * to specify that an element inside of the content div is the element
15018 * that starts the drag operation.
15019 * @method setHandleElId
15020 * @param id {string} the id of the element that will be used to
15021 * initiate the drag.
15023 setHandleElId: function(id) {
15024 if (typeof id !== "string") {
15027 this.handleElId = id;
15028 this.DDM.regHandle(this.id, id);
15032 * Allows you to set an element outside of the linked element as a drag
15034 * @method setOuterHandleElId
15035 * @param id the id of the element that will be used to initiate the drag
15037 setOuterHandleElId: function(id) {
15038 if (typeof id !== "string") {
15041 Event.on(id, "mousedown",
15042 this.handleMouseDown, this);
15043 this.setHandleElId(id);
15045 this.hasOuterHandles = true;
15049 * Remove all drag and drop hooks for this element
15052 unreg: function() {
15053 Event.un(this.id, "mousedown",
15054 this.handleMouseDown);
15055 this._domRef = null;
15056 this.DDM._remove(this);
15059 destroy : function(){
15064 * Returns true if this instance is locked, or the drag drop mgr is locked
15065 * (meaning that all drag/drop is disabled on the page.)
15067 * @return {boolean} true if this obj or all drag/drop is locked, else
15070 isLocked: function() {
15071 return (this.DDM.isLocked() || this.locked);
15075 * Fired when this object is clicked
15076 * @method handleMouseDown
15078 * @param {Roo.dd.DragDrop} oDD the clicked dd object (this dd obj)
15081 handleMouseDown: function(e, oDD){
15082 if (this.primaryButtonOnly && e.button != 0) {
15086 if (this.isLocked()) {
15090 this.DDM.refreshCache(this.groups);
15092 var pt = new Roo.lib.Point(Roo.lib.Event.getPageX(e), Roo.lib.Event.getPageY(e));
15093 if (!this.hasOuterHandles && !this.DDM.isOverTarget(pt, this) ) {
15095 if (this.clickValidator(e)) {
15097 // set the initial element position
15098 this.setStartPosition();
15101 this.b4MouseDown(e);
15102 this.onMouseDown(e);
15104 this.DDM.handleMouseDown(e, this);
15106 this.DDM.stopEvent(e);
15114 clickValidator: function(e) {
15115 var target = e.getTarget();
15116 return ( this.isValidHandleChild(target) &&
15117 (this.id == this.handleElId ||
15118 this.DDM.handleWasClicked(target, this.id)) );
15122 * Allows you to specify a tag name that should not start a drag operation
15123 * when clicked. This is designed to facilitate embedding links within a
15124 * drag handle that do something other than start the drag.
15125 * @method addInvalidHandleType
15126 * @param {string} tagName the type of element to exclude
15128 addInvalidHandleType: function(tagName) {
15129 var type = tagName.toUpperCase();
15130 this.invalidHandleTypes[type] = type;
15134 * Lets you to specify an element id for a child of a drag handle
15135 * that should not initiate a drag
15136 * @method addInvalidHandleId
15137 * @param {string} id the element id of the element you wish to ignore
15139 addInvalidHandleId: function(id) {
15140 if (typeof id !== "string") {
15143 this.invalidHandleIds[id] = id;
15147 * Lets you specify a css class of elements that will not initiate a drag
15148 * @method addInvalidHandleClass
15149 * @param {string} cssClass the class of the elements you wish to ignore
15151 addInvalidHandleClass: function(cssClass) {
15152 this.invalidHandleClasses.push(cssClass);
15156 * Unsets an excluded tag name set by addInvalidHandleType
15157 * @method removeInvalidHandleType
15158 * @param {string} tagName the type of element to unexclude
15160 removeInvalidHandleType: function(tagName) {
15161 var type = tagName.toUpperCase();
15162 // this.invalidHandleTypes[type] = null;
15163 delete this.invalidHandleTypes[type];
15167 * Unsets an invalid handle id
15168 * @method removeInvalidHandleId
15169 * @param {string} id the id of the element to re-enable
15171 removeInvalidHandleId: function(id) {
15172 if (typeof id !== "string") {
15175 delete this.invalidHandleIds[id];
15179 * Unsets an invalid css class
15180 * @method removeInvalidHandleClass
15181 * @param {string} cssClass the class of the element(s) you wish to
15184 removeInvalidHandleClass: function(cssClass) {
15185 for (var i=0, len=this.invalidHandleClasses.length; i<len; ++i) {
15186 if (this.invalidHandleClasses[i] == cssClass) {
15187 delete this.invalidHandleClasses[i];
15193 * Checks the tag exclusion list to see if this click should be ignored
15194 * @method isValidHandleChild
15195 * @param {HTMLElement} node the HTMLElement to evaluate
15196 * @return {boolean} true if this is a valid tag type, false if not
15198 isValidHandleChild: function(node) {
15201 // var n = (node.nodeName == "#text") ? node.parentNode : node;
15204 nodeName = node.nodeName.toUpperCase();
15206 nodeName = node.nodeName;
15208 valid = valid && !this.invalidHandleTypes[nodeName];
15209 valid = valid && !this.invalidHandleIds[node.id];
15211 for (var i=0, len=this.invalidHandleClasses.length; valid && i<len; ++i) {
15212 valid = !Dom.hasClass(node, this.invalidHandleClasses[i]);
15221 * Create the array of horizontal tick marks if an interval was specified
15222 * in setXConstraint().
15223 * @method setXTicks
15226 setXTicks: function(iStartX, iTickSize) {
15228 this.xTickSize = iTickSize;
15232 for (var i = this.initPageX; i >= this.minX; i = i - iTickSize) {
15234 this.xTicks[this.xTicks.length] = i;
15239 for (i = this.initPageX; i <= this.maxX; i = i + iTickSize) {
15241 this.xTicks[this.xTicks.length] = i;
15246 this.xTicks.sort(this.DDM.numericSort) ;
15250 * Create the array of vertical tick marks if an interval was specified in
15251 * setYConstraint().
15252 * @method setYTicks
15255 setYTicks: function(iStartY, iTickSize) {
15257 this.yTickSize = iTickSize;
15261 for (var i = this.initPageY; i >= this.minY; i = i - iTickSize) {
15263 this.yTicks[this.yTicks.length] = i;
15268 for (i = this.initPageY; i <= this.maxY; i = i + iTickSize) {
15270 this.yTicks[this.yTicks.length] = i;
15275 this.yTicks.sort(this.DDM.numericSort) ;
15279 * By default, the element can be dragged any place on the screen. Use
15280 * this method to limit the horizontal travel of the element. Pass in
15281 * 0,0 for the parameters if you want to lock the drag to the y axis.
15282 * @method setXConstraint
15283 * @param {int} iLeft the number of pixels the element can move to the left
15284 * @param {int} iRight the number of pixels the element can move to the
15286 * @param {int} iTickSize optional parameter for specifying that the
15288 * should move iTickSize pixels at a time.
15290 setXConstraint: function(iLeft, iRight, iTickSize) {
15291 this.leftConstraint = iLeft;
15292 this.rightConstraint = iRight;
15294 this.minX = this.initPageX - iLeft;
15295 this.maxX = this.initPageX + iRight;
15296 if (iTickSize) { this.setXTicks(this.initPageX, iTickSize); }
15298 this.constrainX = true;
15302 * Clears any constraints applied to this instance. Also clears ticks
15303 * since they can't exist independent of a constraint at this time.
15304 * @method clearConstraints
15306 clearConstraints: function() {
15307 this.constrainX = false;
15308 this.constrainY = false;
15313 * Clears any tick interval defined for this instance
15314 * @method clearTicks
15316 clearTicks: function() {
15317 this.xTicks = null;
15318 this.yTicks = null;
15319 this.xTickSize = 0;
15320 this.yTickSize = 0;
15324 * By default, the element can be dragged any place on the screen. Set
15325 * this to limit the vertical travel of the element. Pass in 0,0 for the
15326 * parameters if you want to lock the drag to the x axis.
15327 * @method setYConstraint
15328 * @param {int} iUp the number of pixels the element can move up
15329 * @param {int} iDown the number of pixels the element can move down
15330 * @param {int} iTickSize optional parameter for specifying that the
15331 * element should move iTickSize pixels at a time.
15333 setYConstraint: function(iUp, iDown, iTickSize) {
15334 this.topConstraint = iUp;
15335 this.bottomConstraint = iDown;
15337 this.minY = this.initPageY - iUp;
15338 this.maxY = this.initPageY + iDown;
15339 if (iTickSize) { this.setYTicks(this.initPageY, iTickSize); }
15341 this.constrainY = true;
15346 * resetConstraints must be called if you manually reposition a dd element.
15347 * @method resetConstraints
15348 * @param {boolean} maintainOffset
15350 resetConstraints: function() {
15353 // Maintain offsets if necessary
15354 if (this.initPageX || this.initPageX === 0) {
15355 // figure out how much this thing has moved
15356 var dx = (this.maintainOffset) ? this.lastPageX - this.initPageX : 0;
15357 var dy = (this.maintainOffset) ? this.lastPageY - this.initPageY : 0;
15359 this.setInitPosition(dx, dy);
15361 // This is the first time we have detected the element's position
15363 this.setInitPosition();
15366 if (this.constrainX) {
15367 this.setXConstraint( this.leftConstraint,
15368 this.rightConstraint,
15372 if (this.constrainY) {
15373 this.setYConstraint( this.topConstraint,
15374 this.bottomConstraint,
15380 * Normally the drag element is moved pixel by pixel, but we can specify
15381 * that it move a number of pixels at a time. This method resolves the
15382 * location when we have it set up like this.
15384 * @param {int} val where we want to place the object
15385 * @param {int[]} tickArray sorted array of valid points
15386 * @return {int} the closest tick
15389 getTick: function(val, tickArray) {
15392 // If tick interval is not defined, it is effectively 1 pixel,
15393 // so we return the value passed to us.
15395 } else if (tickArray[0] >= val) {
15396 // The value is lower than the first tick, so we return the first
15398 return tickArray[0];
15400 for (var i=0, len=tickArray.length; i<len; ++i) {
15402 if (tickArray[next] && tickArray[next] >= val) {
15403 var diff1 = val - tickArray[i];
15404 var diff2 = tickArray[next] - val;
15405 return (diff2 > diff1) ? tickArray[i] : tickArray[next];
15409 // The value is larger than the last tick, so we return the last
15411 return tickArray[tickArray.length - 1];
15418 * @return {string} string representation of the dd obj
15420 toString: function() {
15421 return ("DragDrop " + this.id);
15429 * Ext JS Library 1.1.1
15430 * Copyright(c) 2006-2007, Ext JS, LLC.
15432 * Originally Released Under LGPL - original licence link has changed is not relivant.
15435 * <script type="text/javascript">
15440 * The drag and drop utility provides a framework for building drag and drop
15441 * applications. In addition to enabling drag and drop for specific elements,
15442 * the drag and drop elements are tracked by the manager class, and the
15443 * interactions between the various elements are tracked during the drag and
15444 * the implementing code is notified about these important moments.
15447 // Only load the library once. Rewriting the manager class would orphan
15448 // existing drag and drop instances.
15449 if (!Roo.dd.DragDropMgr) {
15452 * @class Roo.dd.DragDropMgr
15453 * DragDropMgr is a singleton that tracks the element interaction for
15454 * all DragDrop items in the window. Generally, you will not call
15455 * this class directly, but it does have helper methods that could
15456 * be useful in your DragDrop implementations.
15459 Roo.dd.DragDropMgr = function() {
15461 var Event = Roo.EventManager;
15466 * Two dimensional Array of registered DragDrop objects. The first
15467 * dimension is the DragDrop item group, the second the DragDrop
15470 * @type {string: string}
15477 * Array of element ids defined as drag handles. Used to determine
15478 * if the element that generated the mousedown event is actually the
15479 * handle and not the html element itself.
15480 * @property handleIds
15481 * @type {string: string}
15488 * the DragDrop object that is currently being dragged
15489 * @property dragCurrent
15497 * the DragDrop object(s) that are being hovered over
15498 * @property dragOvers
15506 * the X distance between the cursor and the object being dragged
15515 * the Y distance between the cursor and the object being dragged
15524 * Flag to determine if we should prevent the default behavior of the
15525 * events we define. By default this is true, but this can be set to
15526 * false if you need the default behavior (not recommended)
15527 * @property preventDefault
15531 preventDefault: true,
15534 * Flag to determine if we should stop the propagation of the events
15535 * we generate. This is true by default but you may want to set it to
15536 * false if the html element contains other features that require the
15538 * @property stopPropagation
15542 stopPropagation: true,
15545 * Internal flag that is set to true when drag and drop has been
15547 * @property initialized
15554 * All drag and drop can be disabled.
15562 * Called the first time an element is registered.
15568 this.initialized = true;
15572 * In point mode, drag and drop interaction is defined by the
15573 * location of the cursor during the drag/drop
15581 * In intersect mode, drag and drop interactio nis defined by the
15582 * overlap of two or more drag and drop objects.
15583 * @property INTERSECT
15590 * The current drag and drop mode. Default: POINT
15598 * Runs method on all drag and drop objects
15599 * @method _execOnAll
15603 _execOnAll: function(sMethod, args) {
15604 for (var i in this.ids) {
15605 for (var j in this.ids[i]) {
15606 var oDD = this.ids[i][j];
15607 if (! this.isTypeOfDD(oDD)) {
15610 oDD[sMethod].apply(oDD, args);
15616 * Drag and drop initialization. Sets up the global event handlers
15621 _onLoad: function() {
15626 Event.on(document, "mouseup", this.handleMouseUp, this, true);
15627 Event.on(document, "mousemove", this.handleMouseMove, this, true);
15628 Event.on(window, "unload", this._onUnload, this, true);
15629 Event.on(window, "resize", this._onResize, this, true);
15630 // Event.on(window, "mouseout", this._test);
15635 * Reset constraints on all drag and drop objs
15636 * @method _onResize
15640 _onResize: function(e) {
15641 this._execOnAll("resetConstraints", []);
15645 * Lock all drag and drop functionality
15649 lock: function() { this.locked = true; },
15652 * Unlock all drag and drop functionality
15656 unlock: function() { this.locked = false; },
15659 * Is drag and drop locked?
15661 * @return {boolean} True if drag and drop is locked, false otherwise.
15664 isLocked: function() { return this.locked; },
15667 * Location cache that is set for all drag drop objects when a drag is
15668 * initiated, cleared when the drag is finished.
15669 * @property locationCache
15676 * Set useCache to false if you want to force object the lookup of each
15677 * drag and drop linked element constantly during a drag.
15678 * @property useCache
15685 * The number of pixels that the mouse needs to move after the
15686 * mousedown before the drag is initiated. Default=3;
15687 * @property clickPixelThresh
15691 clickPixelThresh: 3,
15694 * The number of milliseconds after the mousedown event to initiate the
15695 * drag if we don't get a mouseup event. Default=1000
15696 * @property clickTimeThresh
15700 clickTimeThresh: 350,
15703 * Flag that indicates that either the drag pixel threshold or the
15704 * mousdown time threshold has been met
15705 * @property dragThreshMet
15710 dragThreshMet: false,
15713 * Timeout used for the click time threshold
15714 * @property clickTimeout
15719 clickTimeout: null,
15722 * The X position of the mousedown event stored for later use when a
15723 * drag threshold is met.
15732 * The Y position of the mousedown event stored for later use when a
15733 * drag threshold is met.
15742 * Each DragDrop instance must be registered with the DragDropMgr.
15743 * This is executed in DragDrop.init()
15744 * @method regDragDrop
15745 * @param {DragDrop} oDD the DragDrop object to register
15746 * @param {String} sGroup the name of the group this element belongs to
15749 regDragDrop: function(oDD, sGroup) {
15750 if (!this.initialized) { this.init(); }
15752 if (!this.ids[sGroup]) {
15753 this.ids[sGroup] = {};
15755 this.ids[sGroup][oDD.id] = oDD;
15759 * Removes the supplied dd instance from the supplied group. Executed
15760 * by DragDrop.removeFromGroup, so don't call this function directly.
15761 * @method removeDDFromGroup
15765 removeDDFromGroup: function(oDD, sGroup) {
15766 if (!this.ids[sGroup]) {
15767 this.ids[sGroup] = {};
15770 var obj = this.ids[sGroup];
15771 if (obj && obj[oDD.id]) {
15772 delete obj[oDD.id];
15777 * Unregisters a drag and drop item. This is executed in
15778 * DragDrop.unreg, use that method instead of calling this directly.
15783 _remove: function(oDD) {
15784 for (var g in oDD.groups) {
15785 if (g && this.ids[g][oDD.id]) {
15786 delete this.ids[g][oDD.id];
15789 delete this.handleIds[oDD.id];
15793 * Each DragDrop handle element must be registered. This is done
15794 * automatically when executing DragDrop.setHandleElId()
15795 * @method regHandle
15796 * @param {String} sDDId the DragDrop id this element is a handle for
15797 * @param {String} sHandleId the id of the element that is the drag
15801 regHandle: function(sDDId, sHandleId) {
15802 if (!this.handleIds[sDDId]) {
15803 this.handleIds[sDDId] = {};
15805 this.handleIds[sDDId][sHandleId] = sHandleId;
15809 * Utility function to determine if a given element has been
15810 * registered as a drag drop item.
15811 * @method isDragDrop
15812 * @param {String} id the element id to check
15813 * @return {boolean} true if this element is a DragDrop item,
15817 isDragDrop: function(id) {
15818 return ( this.getDDById(id) ) ? true : false;
15822 * Returns the drag and drop instances that are in all groups the
15823 * passed in instance belongs to.
15824 * @method getRelated
15825 * @param {DragDrop} p_oDD the obj to get related data for
15826 * @param {boolean} bTargetsOnly if true, only return targetable objs
15827 * @return {DragDrop[]} the related instances
15830 getRelated: function(p_oDD, bTargetsOnly) {
15832 for (var i in p_oDD.groups) {
15833 for (j in this.ids[i]) {
15834 var dd = this.ids[i][j];
15835 if (! this.isTypeOfDD(dd)) {
15838 if (!bTargetsOnly || dd.isTarget) {
15839 oDDs[oDDs.length] = dd;
15848 * Returns true if the specified dd target is a legal target for
15849 * the specifice drag obj
15850 * @method isLegalTarget
15851 * @param {DragDrop} the drag obj
15852 * @param {DragDrop} the target
15853 * @return {boolean} true if the target is a legal target for the
15857 isLegalTarget: function (oDD, oTargetDD) {
15858 var targets = this.getRelated(oDD, true);
15859 for (var i=0, len=targets.length;i<len;++i) {
15860 if (targets[i].id == oTargetDD.id) {
15869 * My goal is to be able to transparently determine if an object is
15870 * typeof DragDrop, and the exact subclass of DragDrop. typeof
15871 * returns "object", oDD.constructor.toString() always returns
15872 * "DragDrop" and not the name of the subclass. So for now it just
15873 * evaluates a well-known variable in DragDrop.
15874 * @method isTypeOfDD
15875 * @param {Object} the object to evaluate
15876 * @return {boolean} true if typeof oDD = DragDrop
15879 isTypeOfDD: function (oDD) {
15880 return (oDD && oDD.__ygDragDrop);
15884 * Utility function to determine if a given element has been
15885 * registered as a drag drop handle for the given Drag Drop object.
15887 * @param {String} id the element id to check
15888 * @return {boolean} true if this element is a DragDrop handle, false
15892 isHandle: function(sDDId, sHandleId) {
15893 return ( this.handleIds[sDDId] &&
15894 this.handleIds[sDDId][sHandleId] );
15898 * Returns the DragDrop instance for a given id
15899 * @method getDDById
15900 * @param {String} id the id of the DragDrop object
15901 * @return {DragDrop} the drag drop object, null if it is not found
15904 getDDById: function(id) {
15905 for (var i in this.ids) {
15906 if (this.ids[i][id]) {
15907 return this.ids[i][id];
15914 * Fired after a registered DragDrop object gets the mousedown event.
15915 * Sets up the events required to track the object being dragged
15916 * @method handleMouseDown
15917 * @param {Event} e the event
15918 * @param oDD the DragDrop object being dragged
15922 handleMouseDown: function(e, oDD) {
15924 Roo.QuickTips.disable();
15926 this.currentTarget = e.getTarget();
15928 this.dragCurrent = oDD;
15930 var el = oDD.getEl();
15932 // track start position
15933 this.startX = e.getPageX();
15934 this.startY = e.getPageY();
15936 this.deltaX = this.startX - el.offsetLeft;
15937 this.deltaY = this.startY - el.offsetTop;
15939 this.dragThreshMet = false;
15941 this.clickTimeout = setTimeout(
15943 var DDM = Roo.dd.DDM;
15944 DDM.startDrag(DDM.startX, DDM.startY);
15946 this.clickTimeThresh );
15950 * Fired when either the drag pixel threshol or the mousedown hold
15951 * time threshold has been met.
15952 * @method startDrag
15953 * @param x {int} the X position of the original mousedown
15954 * @param y {int} the Y position of the original mousedown
15957 startDrag: function(x, y) {
15958 clearTimeout(this.clickTimeout);
15959 if (this.dragCurrent) {
15960 this.dragCurrent.b4StartDrag(x, y);
15961 this.dragCurrent.startDrag(x, y);
15963 this.dragThreshMet = true;
15967 * Internal function to handle the mouseup event. Will be invoked
15968 * from the context of the document.
15969 * @method handleMouseUp
15970 * @param {Event} e the event
15974 handleMouseUp: function(e) {
15977 Roo.QuickTips.enable();
15979 if (! this.dragCurrent) {
15983 clearTimeout(this.clickTimeout);
15985 if (this.dragThreshMet) {
15986 this.fireEvents(e, true);
15996 * Utility to stop event propagation and event default, if these
15997 * features are turned on.
15998 * @method stopEvent
15999 * @param {Event} e the event as returned by this.getEvent()
16002 stopEvent: function(e){
16003 if(this.stopPropagation) {
16004 e.stopPropagation();
16007 if (this.preventDefault) {
16008 e.preventDefault();
16013 * Internal function to clean up event handlers after the drag
16014 * operation is complete
16016 * @param {Event} e the event
16020 stopDrag: function(e) {
16021 // Fire the drag end event for the item that was dragged
16022 if (this.dragCurrent) {
16023 if (this.dragThreshMet) {
16024 this.dragCurrent.b4EndDrag(e);
16025 this.dragCurrent.endDrag(e);
16028 this.dragCurrent.onMouseUp(e);
16031 this.dragCurrent = null;
16032 this.dragOvers = {};
16036 * Internal function to handle the mousemove event. Will be invoked
16037 * from the context of the html element.
16039 * @TODO figure out what we can do about mouse events lost when the
16040 * user drags objects beyond the window boundary. Currently we can
16041 * detect this in internet explorer by verifying that the mouse is
16042 * down during the mousemove event. Firefox doesn't give us the
16043 * button state on the mousemove event.
16044 * @method handleMouseMove
16045 * @param {Event} e the event
16049 handleMouseMove: function(e) {
16050 if (! this.dragCurrent) {
16054 // var button = e.which || e.button;
16056 // check for IE mouseup outside of page boundary
16057 if (Roo.isIE && (e.button !== 0 && e.button !== 1 && e.button !== 2)) {
16059 return this.handleMouseUp(e);
16062 if (!this.dragThreshMet) {
16063 var diffX = Math.abs(this.startX - e.getPageX());
16064 var diffY = Math.abs(this.startY - e.getPageY());
16065 if (diffX > this.clickPixelThresh ||
16066 diffY > this.clickPixelThresh) {
16067 this.startDrag(this.startX, this.startY);
16071 if (this.dragThreshMet) {
16072 this.dragCurrent.b4Drag(e);
16073 this.dragCurrent.onDrag(e);
16074 if(!this.dragCurrent.moveOnly){
16075 this.fireEvents(e, false);
16085 * Iterates over all of the DragDrop elements to find ones we are
16086 * hovering over or dropping on
16087 * @method fireEvents
16088 * @param {Event} e the event
16089 * @param {boolean} isDrop is this a drop op or a mouseover op?
16093 fireEvents: function(e, isDrop) {
16094 var dc = this.dragCurrent;
16096 // If the user did the mouse up outside of the window, we could
16097 // get here even though we have ended the drag.
16098 if (!dc || dc.isLocked()) {
16102 var pt = e.getPoint();
16104 // cache the previous dragOver array
16110 var enterEvts = [];
16112 // Check to see if the object(s) we were hovering over is no longer
16113 // being hovered over so we can fire the onDragOut event
16114 for (var i in this.dragOvers) {
16116 var ddo = this.dragOvers[i];
16118 if (! this.isTypeOfDD(ddo)) {
16122 if (! this.isOverTarget(pt, ddo, this.mode)) {
16123 outEvts.push( ddo );
16126 oldOvers[i] = true;
16127 delete this.dragOvers[i];
16130 for (var sGroup in dc.groups) {
16132 if ("string" != typeof sGroup) {
16136 for (i in this.ids[sGroup]) {
16137 var oDD = this.ids[sGroup][i];
16138 if (! this.isTypeOfDD(oDD)) {
16142 if (oDD.isTarget && !oDD.isLocked() && oDD != dc) {
16143 if (this.isOverTarget(pt, oDD, this.mode)) {
16144 // look for drop interactions
16146 dropEvts.push( oDD );
16147 // look for drag enter and drag over interactions
16150 // initial drag over: dragEnter fires
16151 if (!oldOvers[oDD.id]) {
16152 enterEvts.push( oDD );
16153 // subsequent drag overs: dragOver fires
16155 overEvts.push( oDD );
16158 this.dragOvers[oDD.id] = oDD;
16166 if (outEvts.length) {
16167 dc.b4DragOut(e, outEvts);
16168 dc.onDragOut(e, outEvts);
16171 if (enterEvts.length) {
16172 dc.onDragEnter(e, enterEvts);
16175 if (overEvts.length) {
16176 dc.b4DragOver(e, overEvts);
16177 dc.onDragOver(e, overEvts);
16180 if (dropEvts.length) {
16181 dc.b4DragDrop(e, dropEvts);
16182 dc.onDragDrop(e, dropEvts);
16186 // fire dragout events
16188 for (i=0, len=outEvts.length; i<len; ++i) {
16189 dc.b4DragOut(e, outEvts[i].id);
16190 dc.onDragOut(e, outEvts[i].id);
16193 // fire enter events
16194 for (i=0,len=enterEvts.length; i<len; ++i) {
16195 // dc.b4DragEnter(e, oDD.id);
16196 dc.onDragEnter(e, enterEvts[i].id);
16199 // fire over events
16200 for (i=0,len=overEvts.length; i<len; ++i) {
16201 dc.b4DragOver(e, overEvts[i].id);
16202 dc.onDragOver(e, overEvts[i].id);
16205 // fire drop events
16206 for (i=0, len=dropEvts.length; i<len; ++i) {
16207 dc.b4DragDrop(e, dropEvts[i].id);
16208 dc.onDragDrop(e, dropEvts[i].id);
16213 // notify about a drop that did not find a target
16214 if (isDrop && !dropEvts.length) {
16215 dc.onInvalidDrop(e);
16221 * Helper function for getting the best match from the list of drag
16222 * and drop objects returned by the drag and drop events when we are
16223 * in INTERSECT mode. It returns either the first object that the
16224 * cursor is over, or the object that has the greatest overlap with
16225 * the dragged element.
16226 * @method getBestMatch
16227 * @param {DragDrop[]} dds The array of drag and drop objects
16229 * @return {DragDrop} The best single match
16232 getBestMatch: function(dds) {
16234 // Return null if the input is not what we expect
16235 //if (!dds || !dds.length || dds.length == 0) {
16237 // If there is only one item, it wins
16238 //} else if (dds.length == 1) {
16240 var len = dds.length;
16245 // Loop through the targeted items
16246 for (var i=0; i<len; ++i) {
16248 // If the cursor is over the object, it wins. If the
16249 // cursor is over multiple matches, the first one we come
16251 if (dd.cursorIsOver) {
16254 // Otherwise the object with the most overlap wins
16257 winner.overlap.getArea() < dd.overlap.getArea()) {
16268 * Refreshes the cache of the top-left and bottom-right points of the
16269 * drag and drop objects in the specified group(s). This is in the
16270 * format that is stored in the drag and drop instance, so typical
16273 * Roo.dd.DragDropMgr.refreshCache(ddinstance.groups);
16277 * Roo.dd.DragDropMgr.refreshCache({group1:true, group2:true});
16279 * @TODO this really should be an indexed array. Alternatively this
16280 * method could accept both.
16281 * @method refreshCache
16282 * @param {Object} groups an associative array of groups to refresh
16285 refreshCache: function(groups) {
16286 for (var sGroup in groups) {
16287 if ("string" != typeof sGroup) {
16290 for (var i in this.ids[sGroup]) {
16291 var oDD = this.ids[sGroup][i];
16293 if (this.isTypeOfDD(oDD)) {
16294 // if (this.isTypeOfDD(oDD) && oDD.isTarget) {
16295 var loc = this.getLocation(oDD);
16297 this.locationCache[oDD.id] = loc;
16299 delete this.locationCache[oDD.id];
16300 // this will unregister the drag and drop object if
16301 // the element is not in a usable state
16310 * This checks to make sure an element exists and is in the DOM. The
16311 * main purpose is to handle cases where innerHTML is used to remove
16312 * drag and drop objects from the DOM. IE provides an 'unspecified
16313 * error' when trying to access the offsetParent of such an element
16315 * @param {HTMLElement} el the element to check
16316 * @return {boolean} true if the element looks usable
16319 verifyEl: function(el) {
16324 parent = el.offsetParent;
16327 parent = el.offsetParent;
16338 * Returns a Region object containing the drag and drop element's position
16339 * and size, including the padding configured for it
16340 * @method getLocation
16341 * @param {DragDrop} oDD the drag and drop object to get the
16343 * @return {Roo.lib.Region} a Region object representing the total area
16344 * the element occupies, including any padding
16345 * the instance is configured for.
16348 getLocation: function(oDD) {
16349 if (! this.isTypeOfDD(oDD)) {
16353 var el = oDD.getEl(), pos, x1, x2, y1, y2, t, r, b, l;
16356 pos= Roo.lib.Dom.getXY(el);
16364 x2 = x1 + el.offsetWidth;
16366 y2 = y1 + el.offsetHeight;
16368 t = y1 - oDD.padding[0];
16369 r = x2 + oDD.padding[1];
16370 b = y2 + oDD.padding[2];
16371 l = x1 - oDD.padding[3];
16373 return new Roo.lib.Region( t, r, b, l );
16377 * Checks the cursor location to see if it over the target
16378 * @method isOverTarget
16379 * @param {Roo.lib.Point} pt The point to evaluate
16380 * @param {DragDrop} oTarget the DragDrop object we are inspecting
16381 * @return {boolean} true if the mouse is over the target
16385 isOverTarget: function(pt, oTarget, intersect) {
16386 // use cache if available
16387 var loc = this.locationCache[oTarget.id];
16388 if (!loc || !this.useCache) {
16389 loc = this.getLocation(oTarget);
16390 this.locationCache[oTarget.id] = loc;
16398 oTarget.cursorIsOver = loc.contains( pt );
16400 // DragDrop is using this as a sanity check for the initial mousedown
16401 // in this case we are done. In POINT mode, if the drag obj has no
16402 // contraints, we are also done. Otherwise we need to evaluate the
16403 // location of the target as related to the actual location of the
16404 // dragged element.
16405 var dc = this.dragCurrent;
16406 if (!dc || !dc.getTargetCoord ||
16407 (!intersect && !dc.constrainX && !dc.constrainY)) {
16408 return oTarget.cursorIsOver;
16411 oTarget.overlap = null;
16413 // Get the current location of the drag element, this is the
16414 // location of the mouse event less the delta that represents
16415 // where the original mousedown happened on the element. We
16416 // need to consider constraints and ticks as well.
16417 var pos = dc.getTargetCoord(pt.x, pt.y);
16419 var el = dc.getDragEl();
16420 var curRegion = new Roo.lib.Region( pos.y,
16421 pos.x + el.offsetWidth,
16422 pos.y + el.offsetHeight,
16425 var overlap = curRegion.intersect(loc);
16428 oTarget.overlap = overlap;
16429 return (intersect) ? true : oTarget.cursorIsOver;
16436 * unload event handler
16437 * @method _onUnload
16441 _onUnload: function(e, me) {
16442 Roo.dd.DragDropMgr.unregAll();
16446 * Cleans up the drag and drop events and objects.
16451 unregAll: function() {
16453 if (this.dragCurrent) {
16455 this.dragCurrent = null;
16458 this._execOnAll("unreg", []);
16460 for (i in this.elementCache) {
16461 delete this.elementCache[i];
16464 this.elementCache = {};
16469 * A cache of DOM elements
16470 * @property elementCache
16477 * Get the wrapper for the DOM element specified
16478 * @method getElWrapper
16479 * @param {String} id the id of the element to get
16480 * @return {Roo.dd.DDM.ElementWrapper} the wrapped element
16482 * @deprecated This wrapper isn't that useful
16485 getElWrapper: function(id) {
16486 var oWrapper = this.elementCache[id];
16487 if (!oWrapper || !oWrapper.el) {
16488 oWrapper = this.elementCache[id] =
16489 new this.ElementWrapper(Roo.getDom(id));
16495 * Returns the actual DOM element
16496 * @method getElement
16497 * @param {String} id the id of the elment to get
16498 * @return {Object} The element
16499 * @deprecated use Roo.getDom instead
16502 getElement: function(id) {
16503 return Roo.getDom(id);
16507 * Returns the style property for the DOM element (i.e.,
16508 * document.getElById(id).style)
16510 * @param {String} id the id of the elment to get
16511 * @return {Object} The style property of the element
16512 * @deprecated use Roo.getDom instead
16515 getCss: function(id) {
16516 var el = Roo.getDom(id);
16517 return (el) ? el.style : null;
16521 * Inner class for cached elements
16522 * @class DragDropMgr.ElementWrapper
16527 ElementWrapper: function(el) {
16532 this.el = el || null;
16537 this.id = this.el && el.id;
16539 * A reference to the style property
16542 this.css = this.el && el.style;
16546 * Returns the X position of an html element
16548 * @param el the element for which to get the position
16549 * @return {int} the X coordinate
16551 * @deprecated use Roo.lib.Dom.getX instead
16554 getPosX: function(el) {
16555 return Roo.lib.Dom.getX(el);
16559 * Returns the Y position of an html element
16561 * @param el the element for which to get the position
16562 * @return {int} the Y coordinate
16563 * @deprecated use Roo.lib.Dom.getY instead
16566 getPosY: function(el) {
16567 return Roo.lib.Dom.getY(el);
16571 * Swap two nodes. In IE, we use the native method, for others we
16572 * emulate the IE behavior
16574 * @param n1 the first node to swap
16575 * @param n2 the other node to swap
16578 swapNode: function(n1, n2) {
16582 var p = n2.parentNode;
16583 var s = n2.nextSibling;
16586 p.insertBefore(n1, n2);
16587 } else if (n2 == n1.nextSibling) {
16588 p.insertBefore(n2, n1);
16590 n1.parentNode.replaceChild(n2, n1);
16591 p.insertBefore(n1, s);
16597 * Returns the current scroll position
16598 * @method getScroll
16602 getScroll: function () {
16603 var t, l, dde=document.documentElement, db=document.body;
16604 if (dde && (dde.scrollTop || dde.scrollLeft)) {
16606 l = dde.scrollLeft;
16613 return { top: t, left: l };
16617 * Returns the specified element style property
16619 * @param {HTMLElement} el the element
16620 * @param {string} styleProp the style property
16621 * @return {string} The value of the style property
16622 * @deprecated use Roo.lib.Dom.getStyle
16625 getStyle: function(el, styleProp) {
16626 return Roo.fly(el).getStyle(styleProp);
16630 * Gets the scrollTop
16631 * @method getScrollTop
16632 * @return {int} the document's scrollTop
16635 getScrollTop: function () { return this.getScroll().top; },
16638 * Gets the scrollLeft
16639 * @method getScrollLeft
16640 * @return {int} the document's scrollTop
16643 getScrollLeft: function () { return this.getScroll().left; },
16646 * Sets the x/y position of an element to the location of the
16649 * @param {HTMLElement} moveEl The element to move
16650 * @param {HTMLElement} targetEl The position reference element
16653 moveToEl: function (moveEl, targetEl) {
16654 var aCoord = Roo.lib.Dom.getXY(targetEl);
16655 Roo.lib.Dom.setXY(moveEl, aCoord);
16659 * Numeric array sort function
16660 * @method numericSort
16663 numericSort: function(a, b) { return (a - b); },
16667 * @property _timeoutCount
16674 * Trying to make the load order less important. Without this we get
16675 * an error if this file is loaded before the Event Utility.
16676 * @method _addListeners
16680 _addListeners: function() {
16681 var DDM = Roo.dd.DDM;
16682 if ( Roo.lib.Event && document ) {
16685 if (DDM._timeoutCount > 2000) {
16687 setTimeout(DDM._addListeners, 10);
16688 if (document && document.body) {
16689 DDM._timeoutCount += 1;
16696 * Recursively searches the immediate parent and all child nodes for
16697 * the handle element in order to determine wheter or not it was
16699 * @method handleWasClicked
16700 * @param node the html element to inspect
16703 handleWasClicked: function(node, id) {
16704 if (this.isHandle(id, node.id)) {
16707 // check to see if this is a text node child of the one we want
16708 var p = node.parentNode;
16711 if (this.isHandle(id, p.id)) {
16726 // shorter alias, save a few bytes
16727 Roo.dd.DDM = Roo.dd.DragDropMgr;
16728 Roo.dd.DDM._addListeners();
16732 * Ext JS Library 1.1.1
16733 * Copyright(c) 2006-2007, Ext JS, LLC.
16735 * Originally Released Under LGPL - original licence link has changed is not relivant.
16738 * <script type="text/javascript">
16743 * A DragDrop implementation where the linked element follows the
16744 * mouse cursor during a drag.
16745 * @extends Roo.dd.DragDrop
16747 * @param {String} id the id of the linked element
16748 * @param {String} sGroup the group of related DragDrop items
16749 * @param {object} config an object containing configurable attributes
16750 * Valid properties for DD:
16753 Roo.dd.DD = function(id, sGroup, config) {
16755 this.init(id, sGroup, config);
16759 Roo.extend(Roo.dd.DD, Roo.dd.DragDrop, {
16762 * When set to true, the utility automatically tries to scroll the browser
16763 * window wehn a drag and drop element is dragged near the viewport boundary.
16764 * Defaults to true.
16771 * Sets the pointer offset to the distance between the linked element's top
16772 * left corner and the location the element was clicked
16773 * @method autoOffset
16774 * @param {int} iPageX the X coordinate of the click
16775 * @param {int} iPageY the Y coordinate of the click
16777 autoOffset: function(iPageX, iPageY) {
16778 var x = iPageX - this.startPageX;
16779 var y = iPageY - this.startPageY;
16780 this.setDelta(x, y);
16784 * Sets the pointer offset. You can call this directly to force the
16785 * offset to be in a particular location (e.g., pass in 0,0 to set it
16786 * to the center of the object)
16788 * @param {int} iDeltaX the distance from the left
16789 * @param {int} iDeltaY the distance from the top
16791 setDelta: function(iDeltaX, iDeltaY) {
16792 this.deltaX = iDeltaX;
16793 this.deltaY = iDeltaY;
16797 * Sets the drag element to the location of the mousedown or click event,
16798 * maintaining the cursor location relative to the location on the element
16799 * that was clicked. Override this if you want to place the element in a
16800 * location other than where the cursor is.
16801 * @method setDragElPos
16802 * @param {int} iPageX the X coordinate of the mousedown or drag event
16803 * @param {int} iPageY the Y coordinate of the mousedown or drag event
16805 setDragElPos: function(iPageX, iPageY) {
16806 // the first time we do this, we are going to check to make sure
16807 // the element has css positioning
16809 var el = this.getDragEl();
16810 this.alignElWithMouse(el, iPageX, iPageY);
16814 * Sets the element to the location of the mousedown or click event,
16815 * maintaining the cursor location relative to the location on the element
16816 * that was clicked. Override this if you want to place the element in a
16817 * location other than where the cursor is.
16818 * @method alignElWithMouse
16819 * @param {HTMLElement} el the element to move
16820 * @param {int} iPageX the X coordinate of the mousedown or drag event
16821 * @param {int} iPageY the Y coordinate of the mousedown or drag event
16823 alignElWithMouse: function(el, iPageX, iPageY) {
16824 var oCoord = this.getTargetCoord(iPageX, iPageY);
16825 var fly = el.dom ? el : Roo.fly(el);
16826 if (!this.deltaSetXY) {
16827 var aCoord = [oCoord.x, oCoord.y];
16829 var newLeft = fly.getLeft(true);
16830 var newTop = fly.getTop(true);
16831 this.deltaSetXY = [ newLeft - oCoord.x, newTop - oCoord.y ];
16833 fly.setLeftTop(oCoord.x + this.deltaSetXY[0], oCoord.y + this.deltaSetXY[1]);
16836 this.cachePosition(oCoord.x, oCoord.y);
16837 this.autoScroll(oCoord.x, oCoord.y, el.offsetHeight, el.offsetWidth);
16842 * Saves the most recent position so that we can reset the constraints and
16843 * tick marks on-demand. We need to know this so that we can calculate the
16844 * number of pixels the element is offset from its original position.
16845 * @method cachePosition
16846 * @param iPageX the current x position (optional, this just makes it so we
16847 * don't have to look it up again)
16848 * @param iPageY the current y position (optional, this just makes it so we
16849 * don't have to look it up again)
16851 cachePosition: function(iPageX, iPageY) {
16853 this.lastPageX = iPageX;
16854 this.lastPageY = iPageY;
16856 var aCoord = Roo.lib.Dom.getXY(this.getEl());
16857 this.lastPageX = aCoord[0];
16858 this.lastPageY = aCoord[1];
16863 * Auto-scroll the window if the dragged object has been moved beyond the
16864 * visible window boundary.
16865 * @method autoScroll
16866 * @param {int} x the drag element's x position
16867 * @param {int} y the drag element's y position
16868 * @param {int} h the height of the drag element
16869 * @param {int} w the width of the drag element
16872 autoScroll: function(x, y, h, w) {
16875 // The client height
16876 var clientH = Roo.lib.Dom.getViewWidth();
16878 // The client width
16879 var clientW = Roo.lib.Dom.getViewHeight();
16881 // The amt scrolled down
16882 var st = this.DDM.getScrollTop();
16884 // The amt scrolled right
16885 var sl = this.DDM.getScrollLeft();
16887 // Location of the bottom of the element
16890 // Location of the right of the element
16893 // The distance from the cursor to the bottom of the visible area,
16894 // adjusted so that we don't scroll if the cursor is beyond the
16895 // element drag constraints
16896 var toBot = (clientH + st - y - this.deltaY);
16898 // The distance from the cursor to the right of the visible area
16899 var toRight = (clientW + sl - x - this.deltaX);
16902 // How close to the edge the cursor must be before we scroll
16903 // var thresh = (document.all) ? 100 : 40;
16906 // How many pixels to scroll per autoscroll op. This helps to reduce
16907 // clunky scrolling. IE is more sensitive about this ... it needs this
16908 // value to be higher.
16909 var scrAmt = (document.all) ? 80 : 30;
16911 // Scroll down if we are near the bottom of the visible page and the
16912 // obj extends below the crease
16913 if ( bot > clientH && toBot < thresh ) {
16914 window.scrollTo(sl, st + scrAmt);
16917 // Scroll up if the window is scrolled down and the top of the object
16918 // goes above the top border
16919 if ( y < st && st > 0 && y - st < thresh ) {
16920 window.scrollTo(sl, st - scrAmt);
16923 // Scroll right if the obj is beyond the right border and the cursor is
16924 // near the border.
16925 if ( right > clientW && toRight < thresh ) {
16926 window.scrollTo(sl + scrAmt, st);
16929 // Scroll left if the window has been scrolled to the right and the obj
16930 // extends past the left border
16931 if ( x < sl && sl > 0 && x - sl < thresh ) {
16932 window.scrollTo(sl - scrAmt, st);
16938 * Finds the location the element should be placed if we want to move
16939 * it to where the mouse location less the click offset would place us.
16940 * @method getTargetCoord
16941 * @param {int} iPageX the X coordinate of the click
16942 * @param {int} iPageY the Y coordinate of the click
16943 * @return an object that contains the coordinates (Object.x and Object.y)
16946 getTargetCoord: function(iPageX, iPageY) {
16949 var x = iPageX - this.deltaX;
16950 var y = iPageY - this.deltaY;
16952 if (this.constrainX) {
16953 if (x < this.minX) { x = this.minX; }
16954 if (x > this.maxX) { x = this.maxX; }
16957 if (this.constrainY) {
16958 if (y < this.minY) { y = this.minY; }
16959 if (y > this.maxY) { y = this.maxY; }
16962 x = this.getTick(x, this.xTicks);
16963 y = this.getTick(y, this.yTicks);
16970 * Sets up config options specific to this class. Overrides
16971 * Roo.dd.DragDrop, but all versions of this method through the
16972 * inheritance chain are called
16974 applyConfig: function() {
16975 Roo.dd.DD.superclass.applyConfig.call(this);
16976 this.scroll = (this.config.scroll !== false);
16980 * Event that fires prior to the onMouseDown event. Overrides
16983 b4MouseDown: function(e) {
16984 // this.resetConstraints();
16985 this.autoOffset(e.getPageX(),
16990 * Event that fires prior to the onDrag event. Overrides
16993 b4Drag: function(e) {
16994 this.setDragElPos(e.getPageX(),
16998 toString: function() {
16999 return ("DD " + this.id);
17002 //////////////////////////////////////////////////////////////////////////
17003 // Debugging ygDragDrop events that can be overridden
17004 //////////////////////////////////////////////////////////////////////////
17006 startDrag: function(x, y) {
17009 onDrag: function(e) {
17012 onDragEnter: function(e, id) {
17015 onDragOver: function(e, id) {
17018 onDragOut: function(e, id) {
17021 onDragDrop: function(e, id) {
17024 endDrag: function(e) {
17031 * Ext JS Library 1.1.1
17032 * Copyright(c) 2006-2007, Ext JS, LLC.
17034 * Originally Released Under LGPL - original licence link has changed is not relivant.
17037 * <script type="text/javascript">
17041 * @class Roo.dd.DDProxy
17042 * A DragDrop implementation that inserts an empty, bordered div into
17043 * the document that follows the cursor during drag operations. At the time of
17044 * the click, the frame div is resized to the dimensions of the linked html
17045 * element, and moved to the exact location of the linked element.
17047 * References to the "frame" element refer to the single proxy element that
17048 * was created to be dragged in place of all DDProxy elements on the
17051 * @extends Roo.dd.DD
17053 * @param {String} id the id of the linked html element
17054 * @param {String} sGroup the group of related DragDrop objects
17055 * @param {object} config an object containing configurable attributes
17056 * Valid properties for DDProxy in addition to those in DragDrop:
17057 * resizeFrame, centerFrame, dragElId
17059 Roo.dd.DDProxy = function(id, sGroup, config) {
17061 this.init(id, sGroup, config);
17067 * The default drag frame div id
17068 * @property Roo.dd.DDProxy.dragElId
17072 Roo.dd.DDProxy.dragElId = "ygddfdiv";
17074 Roo.extend(Roo.dd.DDProxy, Roo.dd.DD, {
17077 * By default we resize the drag frame to be the same size as the element
17078 * we want to drag (this is to get the frame effect). We can turn it off
17079 * if we want a different behavior.
17080 * @property resizeFrame
17086 * By default the frame is positioned exactly where the drag element is, so
17087 * we use the cursor offset provided by Roo.dd.DD. Another option that works only if
17088 * you do not have constraints on the obj is to have the drag frame centered
17089 * around the cursor. Set centerFrame to true for this effect.
17090 * @property centerFrame
17093 centerFrame: false,
17096 * Creates the proxy element if it does not yet exist
17097 * @method createFrame
17099 createFrame: function() {
17101 var body = document.body;
17103 if (!body || !body.firstChild) {
17104 setTimeout( function() { self.createFrame(); }, 50 );
17108 var div = this.getDragEl();
17111 div = document.createElement("div");
17112 div.id = this.dragElId;
17115 s.position = "absolute";
17116 s.visibility = "hidden";
17118 s.border = "2px solid #aaa";
17121 // appendChild can blow up IE if invoked prior to the window load event
17122 // while rendering a table. It is possible there are other scenarios
17123 // that would cause this to happen as well.
17124 body.insertBefore(div, body.firstChild);
17129 * Initialization for the drag frame element. Must be called in the
17130 * constructor of all subclasses
17131 * @method initFrame
17133 initFrame: function() {
17134 this.createFrame();
17137 applyConfig: function() {
17138 Roo.dd.DDProxy.superclass.applyConfig.call(this);
17140 this.resizeFrame = (this.config.resizeFrame !== false);
17141 this.centerFrame = (this.config.centerFrame);
17142 this.setDragElId(this.config.dragElId || Roo.dd.DDProxy.dragElId);
17146 * Resizes the drag frame to the dimensions of the clicked object, positions
17147 * it over the object, and finally displays it
17148 * @method showFrame
17149 * @param {int} iPageX X click position
17150 * @param {int} iPageY Y click position
17153 showFrame: function(iPageX, iPageY) {
17154 var el = this.getEl();
17155 var dragEl = this.getDragEl();
17156 var s = dragEl.style;
17158 this._resizeProxy();
17160 if (this.centerFrame) {
17161 this.setDelta( Math.round(parseInt(s.width, 10)/2),
17162 Math.round(parseInt(s.height, 10)/2) );
17165 this.setDragElPos(iPageX, iPageY);
17167 Roo.fly(dragEl).show();
17171 * The proxy is automatically resized to the dimensions of the linked
17172 * element when a drag is initiated, unless resizeFrame is set to false
17173 * @method _resizeProxy
17176 _resizeProxy: function() {
17177 if (this.resizeFrame) {
17178 var el = this.getEl();
17179 Roo.fly(this.getDragEl()).setSize(el.offsetWidth, el.offsetHeight);
17183 // overrides Roo.dd.DragDrop
17184 b4MouseDown: function(e) {
17185 var x = e.getPageX();
17186 var y = e.getPageY();
17187 this.autoOffset(x, y);
17188 this.setDragElPos(x, y);
17191 // overrides Roo.dd.DragDrop
17192 b4StartDrag: function(x, y) {
17193 // show the drag frame
17194 this.showFrame(x, y);
17197 // overrides Roo.dd.DragDrop
17198 b4EndDrag: function(e) {
17199 Roo.fly(this.getDragEl()).hide();
17202 // overrides Roo.dd.DragDrop
17203 // By default we try to move the element to the last location of the frame.
17204 // This is so that the default behavior mirrors that of Roo.dd.DD.
17205 endDrag: function(e) {
17207 var lel = this.getEl();
17208 var del = this.getDragEl();
17210 // Show the drag frame briefly so we can get its position
17211 del.style.visibility = "";
17214 // Hide the linked element before the move to get around a Safari
17216 lel.style.visibility = "hidden";
17217 Roo.dd.DDM.moveToEl(lel, del);
17218 del.style.visibility = "hidden";
17219 lel.style.visibility = "";
17224 beforeMove : function(){
17228 afterDrag : function(){
17232 toString: function() {
17233 return ("DDProxy " + this.id);
17239 * Ext JS Library 1.1.1
17240 * Copyright(c) 2006-2007, Ext JS, LLC.
17242 * Originally Released Under LGPL - original licence link has changed is not relivant.
17245 * <script type="text/javascript">
17249 * @class Roo.dd.DDTarget
17250 * A DragDrop implementation that does not move, but can be a drop
17251 * target. You would get the same result by simply omitting implementation
17252 * for the event callbacks, but this way we reduce the processing cost of the
17253 * event listener and the callbacks.
17254 * @extends Roo.dd.DragDrop
17256 * @param {String} id the id of the element that is a drop target
17257 * @param {String} sGroup the group of related DragDrop objects
17258 * @param {object} config an object containing configurable attributes
17259 * Valid properties for DDTarget in addition to those in
17263 Roo.dd.DDTarget = function(id, sGroup, config) {
17265 this.initTarget(id, sGroup, config);
17269 // Roo.dd.DDTarget.prototype = new Roo.dd.DragDrop();
17270 Roo.extend(Roo.dd.DDTarget, Roo.dd.DragDrop, {
17271 toString: function() {
17272 return ("DDTarget " + this.id);
17277 * Ext JS Library 1.1.1
17278 * Copyright(c) 2006-2007, Ext JS, LLC.
17280 * Originally Released Under LGPL - original licence link has changed is not relivant.
17283 * <script type="text/javascript">
17288 * @class Roo.dd.ScrollManager
17289 * Provides automatic scrolling of overflow regions in the page during drag operations.<br><br>
17290 * <b>Note: This class uses "Point Mode" and is untested in "Intersect Mode".</b>
17293 Roo.dd.ScrollManager = function(){
17294 var ddm = Roo.dd.DragDropMgr;
17299 var onStop = function(e){
17304 var triggerRefresh = function(){
17305 if(ddm.dragCurrent){
17306 ddm.refreshCache(ddm.dragCurrent.groups);
17310 var doScroll = function(){
17311 if(ddm.dragCurrent){
17312 var dds = Roo.dd.ScrollManager;
17314 if(proc.el.scroll(proc.dir, dds.increment)){
17318 proc.el.scroll(proc.dir, dds.increment, true, dds.animDuration, triggerRefresh);
17323 var clearProc = function(){
17325 clearInterval(proc.id);
17332 var startProc = function(el, dir){
17336 proc.id = setInterval(doScroll, Roo.dd.ScrollManager.frequency);
17339 var onFire = function(e, isDrop){
17340 if(isDrop || !ddm.dragCurrent){ return; }
17341 var dds = Roo.dd.ScrollManager;
17342 if(!dragEl || dragEl != ddm.dragCurrent){
17343 dragEl = ddm.dragCurrent;
17344 // refresh regions on drag start
17345 dds.refreshCache();
17348 var xy = Roo.lib.Event.getXY(e);
17349 var pt = new Roo.lib.Point(xy[0], xy[1]);
17350 for(var id in els){
17351 var el = els[id], r = el._region;
17352 if(r && r.contains(pt) && el.isScrollable()){
17353 if(r.bottom - pt.y <= dds.thresh){
17355 startProc(el, "down");
17358 }else if(r.right - pt.x <= dds.thresh){
17360 startProc(el, "left");
17363 }else if(pt.y - r.top <= dds.thresh){
17365 startProc(el, "up");
17368 }else if(pt.x - r.left <= dds.thresh){
17370 startProc(el, "right");
17379 ddm.fireEvents = ddm.fireEvents.createSequence(onFire, ddm);
17380 ddm.stopDrag = ddm.stopDrag.createSequence(onStop, ddm);
17384 * Registers new overflow element(s) to auto scroll
17385 * @param {String/HTMLElement/Element/Array} el The id of or the element to be scrolled or an array of either
17387 register : function(el){
17388 if(el instanceof Array){
17389 for(var i = 0, len = el.length; i < len; i++) {
17390 this.register(el[i]);
17399 * Unregisters overflow element(s) so they are no longer scrolled
17400 * @param {String/HTMLElement/Element/Array} el The id of or the element to be removed or an array of either
17402 unregister : function(el){
17403 if(el instanceof Array){
17404 for(var i = 0, len = el.length; i < len; i++) {
17405 this.unregister(el[i]);
17414 * The number of pixels from the edge of a container the pointer needs to be to
17415 * trigger scrolling (defaults to 25)
17421 * The number of pixels to scroll in each scroll increment (defaults to 50)
17427 * The frequency of scrolls in milliseconds (defaults to 500)
17433 * True to animate the scroll (defaults to true)
17439 * The animation duration in seconds -
17440 * MUST BE less than Roo.dd.ScrollManager.frequency! (defaults to .4)
17446 * Manually trigger a cache refresh.
17448 refreshCache : function(){
17449 for(var id in els){
17450 if(typeof els[id] == 'object'){ // for people extending the object prototype
17451 els[id]._region = els[id].getRegion();
17458 * Ext JS Library 1.1.1
17459 * Copyright(c) 2006-2007, Ext JS, LLC.
17461 * Originally Released Under LGPL - original licence link has changed is not relivant.
17464 * <script type="text/javascript">
17469 * @class Roo.dd.Registry
17470 * Provides easy access to all drag drop components that are registered on a page. Items can be retrieved either
17471 * directly by DOM node id, or by passing in the drag drop event that occurred and looking up the event target.
17474 Roo.dd.Registry = function(){
17477 var autoIdSeed = 0;
17479 var getId = function(el, autogen){
17480 if(typeof el == "string"){
17484 if(!id && autogen !== false){
17485 id = "roodd-" + (++autoIdSeed);
17493 * Register a drag drop element
17494 * @param {String|HTMLElement} element The id or DOM node to register
17495 * @param {Object} data (optional) A custom data object that will be passed between the elements that are involved
17496 * in drag drop operations. You can populate this object with any arbitrary properties that your own code
17497 * knows how to interpret, plus there are some specific properties known to the Registry that should be
17498 * populated in the data object (if applicable):
17500 Value Description<br />
17501 --------- ------------------------------------------<br />
17502 handles Array of DOM nodes that trigger dragging<br />
17503 for the element being registered<br />
17504 isHandle True if the element passed in triggers<br />
17505 dragging itself, else false
17508 register : function(el, data){
17510 if(typeof el == "string"){
17511 el = document.getElementById(el);
17514 elements[getId(el)] = data;
17515 if(data.isHandle !== false){
17516 handles[data.ddel.id] = data;
17519 var hs = data.handles;
17520 for(var i = 0, len = hs.length; i < len; i++){
17521 handles[getId(hs[i])] = data;
17527 * Unregister a drag drop element
17528 * @param {String|HTMLElement} element The id or DOM node to unregister
17530 unregister : function(el){
17531 var id = getId(el, false);
17532 var data = elements[id];
17534 delete elements[id];
17536 var hs = data.handles;
17537 for(var i = 0, len = hs.length; i < len; i++){
17538 delete handles[getId(hs[i], false)];
17545 * Returns the handle registered for a DOM Node by id
17546 * @param {String|HTMLElement} id The DOM node or id to look up
17547 * @return {Object} handle The custom handle data
17549 getHandle : function(id){
17550 if(typeof id != "string"){ // must be element?
17553 return handles[id];
17557 * Returns the handle that is registered for the DOM node that is the target of the event
17558 * @param {Event} e The event
17559 * @return {Object} handle The custom handle data
17561 getHandleFromEvent : function(e){
17562 var t = Roo.lib.Event.getTarget(e);
17563 return t ? handles[t.id] : null;
17567 * Returns a custom data object that is registered for a DOM node by id
17568 * @param {String|HTMLElement} id The DOM node or id to look up
17569 * @return {Object} data The custom data
17571 getTarget : function(id){
17572 if(typeof id != "string"){ // must be element?
17575 return elements[id];
17579 * Returns a custom data object that is registered for the DOM node that is the target of the event
17580 * @param {Event} e The event
17581 * @return {Object} data The custom data
17583 getTargetFromEvent : function(e){
17584 var t = Roo.lib.Event.getTarget(e);
17585 return t ? elements[t.id] || handles[t.id] : null;
17590 * Ext JS Library 1.1.1
17591 * Copyright(c) 2006-2007, Ext JS, LLC.
17593 * Originally Released Under LGPL - original licence link has changed is not relivant.
17596 * <script type="text/javascript">
17601 * @class Roo.dd.StatusProxy
17602 * A specialized drag proxy that supports a drop status icon, {@link Roo.Layer} styles and auto-repair. This is the
17603 * default drag proxy used by all Roo.dd components.
17605 * @param {Object} config
17607 Roo.dd.StatusProxy = function(config){
17608 Roo.apply(this, config);
17609 this.id = this.id || Roo.id();
17610 this.el = new Roo.Layer({
17612 id: this.id, tag: "div", cls: "x-dd-drag-proxy "+this.dropNotAllowed, children: [
17613 {tag: "div", cls: "x-dd-drop-icon"},
17614 {tag: "div", cls: "x-dd-drag-ghost"}
17617 shadow: !config || config.shadow !== false
17619 this.ghost = Roo.get(this.el.dom.childNodes[1]);
17620 this.dropStatus = this.dropNotAllowed;
17623 Roo.dd.StatusProxy.prototype = {
17625 * @cfg {String} dropAllowed
17626 * The CSS class to apply to the status element when drop is allowed (defaults to "x-dd-drop-ok").
17628 dropAllowed : "x-dd-drop-ok",
17630 * @cfg {String} dropNotAllowed
17631 * The CSS class to apply to the status element when drop is not allowed (defaults to "x-dd-drop-nodrop").
17633 dropNotAllowed : "x-dd-drop-nodrop",
17636 * Updates the proxy's visual element to indicate the status of whether or not drop is allowed
17637 * over the current target element.
17638 * @param {String} cssClass The css class for the new drop status indicator image
17640 setStatus : function(cssClass){
17641 cssClass = cssClass || this.dropNotAllowed;
17642 if(this.dropStatus != cssClass){
17643 this.el.replaceClass(this.dropStatus, cssClass);
17644 this.dropStatus = cssClass;
17649 * Resets the status indicator to the default dropNotAllowed value
17650 * @param {Boolean} clearGhost True to also remove all content from the ghost, false to preserve it
17652 reset : function(clearGhost){
17653 this.el.dom.className = "x-dd-drag-proxy " + this.dropNotAllowed;
17654 this.dropStatus = this.dropNotAllowed;
17656 this.ghost.update("");
17661 * Updates the contents of the ghost element
17662 * @param {String} html The html that will replace the current innerHTML of the ghost element
17664 update : function(html){
17665 if(typeof html == "string"){
17666 this.ghost.update(html);
17668 this.ghost.update("");
17669 html.style.margin = "0";
17670 this.ghost.dom.appendChild(html);
17672 // ensure float = none set?? cant remember why though.
17673 var el = this.ghost.dom.firstChild;
17675 Roo.fly(el).setStyle('float', 'none');
17680 * Returns the underlying proxy {@link Roo.Layer}
17681 * @return {Roo.Layer} el
17683 getEl : function(){
17688 * Returns the ghost element
17689 * @return {Roo.Element} el
17691 getGhost : function(){
17697 * @param {Boolean} clear True to reset the status and clear the ghost contents, false to preserve them
17699 hide : function(clear){
17707 * Stops the repair animation if it's currently running
17710 if(this.anim && this.anim.isAnimated && this.anim.isAnimated()){
17716 * Displays this proxy
17723 * Force the Layer to sync its shadow and shim positions to the element
17730 * Causes the proxy to return to its position of origin via an animation. Should be called after an
17731 * invalid drop operation by the item being dragged.
17732 * @param {Array} xy The XY position of the element ([x, y])
17733 * @param {Function} callback The function to call after the repair is complete
17734 * @param {Object} scope The scope in which to execute the callback
17736 repair : function(xy, callback, scope){
17737 this.callback = callback;
17738 this.scope = scope;
17739 if(xy && this.animRepair !== false){
17740 this.el.addClass("x-dd-drag-repair");
17741 this.el.hideUnders(true);
17742 this.anim = this.el.shift({
17743 duration: this.repairDuration || .5,
17747 callback: this.afterRepair,
17751 this.afterRepair();
17756 afterRepair : function(){
17758 if(typeof this.callback == "function"){
17759 this.callback.call(this.scope || this);
17761 this.callback = null;
17766 * Ext JS Library 1.1.1
17767 * Copyright(c) 2006-2007, Ext JS, LLC.
17769 * Originally Released Under LGPL - original licence link has changed is not relivant.
17772 * <script type="text/javascript">
17776 * @class Roo.dd.DragSource
17777 * @extends Roo.dd.DDProxy
17778 * A simple class that provides the basic implementation needed to make any element draggable.
17780 * @param {String/HTMLElement/Element} el The container element
17781 * @param {Object} config
17783 Roo.dd.DragSource = function(el, config){
17784 this.el = Roo.get(el);
17785 this.dragData = {};
17787 Roo.apply(this, config);
17790 this.proxy = new Roo.dd.StatusProxy();
17793 Roo.dd.DragSource.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
17794 {dragElId : this.proxy.id, resizeFrame: false, isTarget: false, scroll: this.scroll === true});
17796 this.dragging = false;
17799 Roo.extend(Roo.dd.DragSource, Roo.dd.DDProxy, {
17801 * @cfg {String} dropAllowed
17802 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
17804 dropAllowed : "x-dd-drop-ok",
17806 * @cfg {String} dropNotAllowed
17807 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
17809 dropNotAllowed : "x-dd-drop-nodrop",
17812 * Returns the data object associated with this drag source
17813 * @return {Object} data An object containing arbitrary data
17815 getDragData : function(e){
17816 return this.dragData;
17820 onDragEnter : function(e, id){
17821 var target = Roo.dd.DragDropMgr.getDDById(id);
17822 this.cachedTarget = target;
17823 if(this.beforeDragEnter(target, e, id) !== false){
17824 if(target.isNotifyTarget){
17825 var status = target.notifyEnter(this, e, this.dragData);
17826 this.proxy.setStatus(status);
17828 this.proxy.setStatus(this.dropAllowed);
17831 if(this.afterDragEnter){
17833 * An empty function by default, but provided so that you can perform a custom action
17834 * when the dragged item enters the drop target by providing an implementation.
17835 * @param {Roo.dd.DragDrop} target The drop target
17836 * @param {Event} e The event object
17837 * @param {String} id The id of the dragged element
17838 * @method afterDragEnter
17840 this.afterDragEnter(target, e, id);
17846 * An empty function by default, but provided so that you can perform a custom action
17847 * before the dragged item enters the drop target and optionally cancel the onDragEnter.
17848 * @param {Roo.dd.DragDrop} target The drop target
17849 * @param {Event} e The event object
17850 * @param {String} id The id of the dragged element
17851 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
17853 beforeDragEnter : function(target, e, id){
17858 alignElWithMouse: function() {
17859 Roo.dd.DragSource.superclass.alignElWithMouse.apply(this, arguments);
17864 onDragOver : function(e, id){
17865 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
17866 if(this.beforeDragOver(target, e, id) !== false){
17867 if(target.isNotifyTarget){
17868 var status = target.notifyOver(this, e, this.dragData);
17869 this.proxy.setStatus(status);
17872 if(this.afterDragOver){
17874 * An empty function by default, but provided so that you can perform a custom action
17875 * while the dragged item is over the drop target by providing an implementation.
17876 * @param {Roo.dd.DragDrop} target The drop target
17877 * @param {Event} e The event object
17878 * @param {String} id The id of the dragged element
17879 * @method afterDragOver
17881 this.afterDragOver(target, e, id);
17887 * An empty function by default, but provided so that you can perform a custom action
17888 * while the dragged item is over the drop target and optionally cancel the onDragOver.
17889 * @param {Roo.dd.DragDrop} target The drop target
17890 * @param {Event} e The event object
17891 * @param {String} id The id of the dragged element
17892 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
17894 beforeDragOver : function(target, e, id){
17899 onDragOut : function(e, id){
17900 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
17901 if(this.beforeDragOut(target, e, id) !== false){
17902 if(target.isNotifyTarget){
17903 target.notifyOut(this, e, this.dragData);
17905 this.proxy.reset();
17906 if(this.afterDragOut){
17908 * An empty function by default, but provided so that you can perform a custom action
17909 * after the dragged item is dragged out of the target without dropping.
17910 * @param {Roo.dd.DragDrop} target The drop target
17911 * @param {Event} e The event object
17912 * @param {String} id The id of the dragged element
17913 * @method afterDragOut
17915 this.afterDragOut(target, e, id);
17918 this.cachedTarget = null;
17922 * An empty function by default, but provided so that you can perform a custom action before the dragged
17923 * item is dragged out of the target without dropping, and optionally cancel the onDragOut.
17924 * @param {Roo.dd.DragDrop} target The drop target
17925 * @param {Event} e The event object
17926 * @param {String} id The id of the dragged element
17927 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
17929 beforeDragOut : function(target, e, id){
17934 onDragDrop : function(e, id){
17935 var target = this.cachedTarget || Roo.dd.DragDropMgr.getDDById(id);
17936 if(this.beforeDragDrop(target, e, id) !== false){
17937 if(target.isNotifyTarget){
17938 if(target.notifyDrop(this, e, this.dragData)){ // valid drop?
17939 this.onValidDrop(target, e, id);
17941 this.onInvalidDrop(target, e, id);
17944 this.onValidDrop(target, e, id);
17947 if(this.afterDragDrop){
17949 * An empty function by default, but provided so that you can perform a custom action
17950 * after a valid drag drop has occurred by providing an implementation.
17951 * @param {Roo.dd.DragDrop} target The drop target
17952 * @param {Event} e The event object
17953 * @param {String} id The id of the dropped element
17954 * @method afterDragDrop
17956 this.afterDragDrop(target, e, id);
17959 delete this.cachedTarget;
17963 * An empty function by default, but provided so that you can perform a custom action before the dragged
17964 * item is dropped onto the target and optionally cancel the onDragDrop.
17965 * @param {Roo.dd.DragDrop} target The drop target
17966 * @param {Event} e The event object
17967 * @param {String} id The id of the dragged element
17968 * @return {Boolean} isValid True if the drag drop event is valid, else false to cancel
17970 beforeDragDrop : function(target, e, id){
17975 onValidDrop : function(target, e, id){
17977 if(this.afterValidDrop){
17979 * An empty function by default, but provided so that you can perform a custom action
17980 * after a valid drop has occurred by providing an implementation.
17981 * @param {Object} target The target DD
17982 * @param {Event} e The event object
17983 * @param {String} id The id of the dropped element
17984 * @method afterInvalidDrop
17986 this.afterValidDrop(target, e, id);
17991 getRepairXY : function(e, data){
17992 return this.el.getXY();
17996 onInvalidDrop : function(target, e, id){
17997 this.beforeInvalidDrop(target, e, id);
17998 if(this.cachedTarget){
17999 if(this.cachedTarget.isNotifyTarget){
18000 this.cachedTarget.notifyOut(this, e, this.dragData);
18002 this.cacheTarget = null;
18004 this.proxy.repair(this.getRepairXY(e, this.dragData), this.afterRepair, this);
18006 if(this.afterInvalidDrop){
18008 * An empty function by default, but provided so that you can perform a custom action
18009 * after an invalid drop has occurred by providing an implementation.
18010 * @param {Event} e The event object
18011 * @param {String} id The id of the dropped element
18012 * @method afterInvalidDrop
18014 this.afterInvalidDrop(e, id);
18019 afterRepair : function(){
18021 this.el.highlight(this.hlColor || "c3daf9");
18023 this.dragging = false;
18027 * An empty function by default, but provided so that you can perform a custom action after an invalid
18028 * drop has occurred.
18029 * @param {Roo.dd.DragDrop} target The drop target
18030 * @param {Event} e The event object
18031 * @param {String} id The id of the dragged element
18032 * @return {Boolean} isValid True if the invalid drop should proceed, else false to cancel
18034 beforeInvalidDrop : function(target, e, id){
18039 handleMouseDown : function(e){
18040 if(this.dragging) {
18043 var data = this.getDragData(e);
18044 if(data && this.onBeforeDrag(data, e) !== false){
18045 this.dragData = data;
18047 Roo.dd.DragSource.superclass.handleMouseDown.apply(this, arguments);
18052 * An empty function by default, but provided so that you can perform a custom action before the initial
18053 * drag event begins and optionally cancel it.
18054 * @param {Object} data An object containing arbitrary data to be shared with drop targets
18055 * @param {Event} e The event object
18056 * @return {Boolean} isValid True if the drag event is valid, else false to cancel
18058 onBeforeDrag : function(data, e){
18063 * An empty function by default, but provided so that you can perform a custom action once the initial
18064 * drag event has begun. The drag cannot be canceled from this function.
18065 * @param {Number} x The x position of the click on the dragged object
18066 * @param {Number} y The y position of the click on the dragged object
18068 onStartDrag : Roo.emptyFn,
18070 // private - YUI override
18071 startDrag : function(x, y){
18072 this.proxy.reset();
18073 this.dragging = true;
18074 this.proxy.update("");
18075 this.onInitDrag(x, y);
18080 onInitDrag : function(x, y){
18081 var clone = this.el.dom.cloneNode(true);
18082 clone.id = Roo.id(); // prevent duplicate ids
18083 this.proxy.update(clone);
18084 this.onStartDrag(x, y);
18089 * Returns the drag source's underlying {@link Roo.dd.StatusProxy}
18090 * @return {Roo.dd.StatusProxy} proxy The StatusProxy
18092 getProxy : function(){
18097 * Hides the drag source's {@link Roo.dd.StatusProxy}
18099 hideProxy : function(){
18101 this.proxy.reset(true);
18102 this.dragging = false;
18106 triggerCacheRefresh : function(){
18107 Roo.dd.DDM.refreshCache(this.groups);
18110 // private - override to prevent hiding
18111 b4EndDrag: function(e) {
18114 // private - override to prevent moving
18115 endDrag : function(e){
18116 this.onEndDrag(this.dragData, e);
18120 onEndDrag : function(data, e){
18123 // private - pin to cursor
18124 autoOffset : function(x, y) {
18125 this.setDelta(-12, -20);
18129 * Ext JS Library 1.1.1
18130 * Copyright(c) 2006-2007, Ext JS, LLC.
18132 * Originally Released Under LGPL - original licence link has changed is not relivant.
18135 * <script type="text/javascript">
18140 * @class Roo.dd.DropTarget
18141 * @extends Roo.dd.DDTarget
18142 * A simple class that provides the basic implementation needed to make any element a drop target that can have
18143 * draggable items dropped onto it. The drop has no effect until an implementation of notifyDrop is provided.
18145 * @param {String/HTMLElement/Element} el The container element
18146 * @param {Object} config
18148 Roo.dd.DropTarget = function(el, config){
18149 this.el = Roo.get(el);
18151 Roo.apply(this, config);
18153 if(this.containerScroll){
18154 Roo.dd.ScrollManager.register(this.el);
18157 Roo.dd.DropTarget.superclass.constructor.call(this, this.el.dom, this.ddGroup || this.group,
18162 Roo.extend(Roo.dd.DropTarget, Roo.dd.DDTarget, {
18164 * @cfg {String} overClass
18165 * The CSS class applied to the drop target element while the drag source is over it (defaults to "").
18168 * @cfg {String} dropAllowed
18169 * The CSS class returned to the drag source when drop is allowed (defaults to "x-dd-drop-ok").
18171 dropAllowed : "x-dd-drop-ok",
18173 * @cfg {String} dropNotAllowed
18174 * The CSS class returned to the drag source when drop is not allowed (defaults to "x-dd-drop-nodrop").
18176 dropNotAllowed : "x-dd-drop-nodrop",
18182 isNotifyTarget : true,
18185 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source is now over the
18186 * target. This default implementation adds the CSS class specified by overClass (if any) to the drop element
18187 * and returns the dropAllowed config value. This method should be overridden if drop validation is required.
18188 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18189 * @param {Event} e The event
18190 * @param {Object} data An object containing arbitrary data supplied by the drag source
18191 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18192 * underlying {@link Roo.dd.StatusProxy} can be updated
18194 notifyEnter : function(dd, e, data){
18195 if(this.overClass){
18196 this.el.addClass(this.overClass);
18198 return this.dropAllowed;
18202 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the target.
18203 * This method will be called on every mouse movement while the drag source is over the drop target.
18204 * This default implementation simply returns the dropAllowed config value.
18205 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18206 * @param {Event} e The event
18207 * @param {Object} data An object containing arbitrary data supplied by the drag source
18208 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18209 * underlying {@link Roo.dd.StatusProxy} can be updated
18211 notifyOver : function(dd, e, data){
18212 return this.dropAllowed;
18216 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the source has been dragged
18217 * out of the target without dropping. This default implementation simply removes the CSS class specified by
18218 * overClass (if any) from the drop element.
18219 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18220 * @param {Event} e The event
18221 * @param {Object} data An object containing arbitrary data supplied by the drag source
18223 notifyOut : function(dd, e, data){
18224 if(this.overClass){
18225 this.el.removeClass(this.overClass);
18230 * The function a {@link Roo.dd.DragSource} calls once to notify this drop target that the dragged item has
18231 * been dropped on it. This method has no default implementation and returns false, so you must provide an
18232 * implementation that does something to process the drop event and returns true so that the drag source's
18233 * repair action does not run.
18234 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18235 * @param {Event} e The event
18236 * @param {Object} data An object containing arbitrary data supplied by the drag source
18237 * @return {Boolean} True if the drop was valid, else false
18239 notifyDrop : function(dd, e, data){
18244 * Ext JS Library 1.1.1
18245 * Copyright(c) 2006-2007, Ext JS, LLC.
18247 * Originally Released Under LGPL - original licence link has changed is not relivant.
18250 * <script type="text/javascript">
18255 * @class Roo.dd.DragZone
18256 * @extends Roo.dd.DragSource
18257 * This class provides a container DD instance that proxies for multiple child node sources.<br />
18258 * By default, this class requires that draggable child nodes are registered with {@link Roo.dd.Registry}.
18260 * @param {String/HTMLElement/Element} el The container element
18261 * @param {Object} config
18263 Roo.dd.DragZone = function(el, config){
18264 Roo.dd.DragZone.superclass.constructor.call(this, el, config);
18265 if(this.containerScroll){
18266 Roo.dd.ScrollManager.register(this.el);
18270 Roo.extend(Roo.dd.DragZone, Roo.dd.DragSource, {
18272 * @cfg {Boolean} containerScroll True to register this container with the Scrollmanager
18273 * for auto scrolling during drag operations.
18276 * @cfg {String} hlColor The color to use when visually highlighting the drag source in the afterRepair
18277 * method after a failed drop (defaults to "c3daf9" - light blue)
18281 * Called when a mousedown occurs in this container. Looks in {@link Roo.dd.Registry}
18282 * for a valid target to drag based on the mouse down. Override this method
18283 * to provide your own lookup logic (e.g. finding a child by class name). Make sure your returned
18284 * object has a "ddel" attribute (with an HTML Element) for other functions to work.
18285 * @param {EventObject} e The mouse down event
18286 * @return {Object} The dragData
18288 getDragData : function(e){
18289 return Roo.dd.Registry.getHandleFromEvent(e);
18293 * Called once drag threshold has been reached to initialize the proxy element. By default, it clones the
18294 * this.dragData.ddel
18295 * @param {Number} x The x position of the click on the dragged object
18296 * @param {Number} y The y position of the click on the dragged object
18297 * @return {Boolean} true to continue the drag, false to cancel
18299 onInitDrag : function(x, y){
18300 this.proxy.update(this.dragData.ddel.cloneNode(true));
18301 this.onStartDrag(x, y);
18306 * Called after a repair of an invalid drop. By default, highlights this.dragData.ddel
18308 afterRepair : function(){
18310 Roo.Element.fly(this.dragData.ddel).highlight(this.hlColor || "c3daf9");
18312 this.dragging = false;
18316 * Called before a repair of an invalid drop to get the XY to animate to. By default returns
18317 * the XY of this.dragData.ddel
18318 * @param {EventObject} e The mouse up event
18319 * @return {Array} The xy location (e.g. [100, 200])
18321 getRepairXY : function(e){
18322 return Roo.Element.fly(this.dragData.ddel).getXY();
18326 * Ext JS Library 1.1.1
18327 * Copyright(c) 2006-2007, Ext JS, LLC.
18329 * Originally Released Under LGPL - original licence link has changed is not relivant.
18332 * <script type="text/javascript">
18335 * @class Roo.dd.DropZone
18336 * @extends Roo.dd.DropTarget
18337 * This class provides a container DD instance that proxies for multiple child node targets.<br />
18338 * By default, this class requires that child nodes accepting drop are registered with {@link Roo.dd.Registry}.
18340 * @param {String/HTMLElement/Element} el The container element
18341 * @param {Object} config
18343 Roo.dd.DropZone = function(el, config){
18344 Roo.dd.DropZone.superclass.constructor.call(this, el, config);
18347 Roo.extend(Roo.dd.DropZone, Roo.dd.DropTarget, {
18349 * Returns a custom data object associated with the DOM node that is the target of the event. By default
18350 * this looks up the event target in the {@link Roo.dd.Registry}, although you can override this method to
18351 * provide your own custom lookup.
18352 * @param {Event} e The event
18353 * @return {Object} data The custom data
18355 getTargetFromEvent : function(e){
18356 return Roo.dd.Registry.getTargetFromEvent(e);
18360 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has entered a drop node
18361 * that it has registered. This method has no default implementation and should be overridden to provide
18362 * node-specific processing if necessary.
18363 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18364 * {@link #getTargetFromEvent} for this node)
18365 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18366 * @param {Event} e The event
18367 * @param {Object} data An object containing arbitrary data supplied by the drag source
18369 onNodeEnter : function(n, dd, e, data){
18374 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is over a drop node
18375 * that it has registered. The default implementation returns this.dropNotAllowed, so it should be
18376 * overridden to provide the proper feedback.
18377 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18378 * {@link #getTargetFromEvent} for this node)
18379 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18380 * @param {Event} e The event
18381 * @param {Object} data An object containing arbitrary data supplied by the drag source
18382 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18383 * underlying {@link Roo.dd.StatusProxy} can be updated
18385 onNodeOver : function(n, dd, e, data){
18386 return this.dropAllowed;
18390 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dragged out of
18391 * the drop node without dropping. This method has no default implementation and should be overridden to provide
18392 * node-specific processing if necessary.
18393 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18394 * {@link #getTargetFromEvent} for this node)
18395 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18396 * @param {Event} e The event
18397 * @param {Object} data An object containing arbitrary data supplied by the drag source
18399 onNodeOut : function(n, dd, e, data){
18404 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped onto
18405 * the drop node. The default implementation returns false, so it should be overridden to provide the
18406 * appropriate processing of the drop event and return true so that the drag source's repair action does not run.
18407 * @param {Object} nodeData The custom data associated with the drop node (this is the same value returned from
18408 * {@link #getTargetFromEvent} for this node)
18409 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18410 * @param {Event} e The event
18411 * @param {Object} data An object containing arbitrary data supplied by the drag source
18412 * @return {Boolean} True if the drop was valid, else false
18414 onNodeDrop : function(n, dd, e, data){
18419 * Called internally while the DropZone determines that a {@link Roo.dd.DragSource} is being dragged over it,
18420 * but not over any of its registered drop nodes. The default implementation returns this.dropNotAllowed, so
18421 * it should be overridden to provide the proper feedback if necessary.
18422 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18423 * @param {Event} e The event
18424 * @param {Object} data An object containing arbitrary data supplied by the drag source
18425 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18426 * underlying {@link Roo.dd.StatusProxy} can be updated
18428 onContainerOver : function(dd, e, data){
18429 return this.dropNotAllowed;
18433 * Called internally when the DropZone determines that a {@link Roo.dd.DragSource} has been dropped on it,
18434 * but not on any of its registered drop nodes. The default implementation returns false, so it should be
18435 * overridden to provide the appropriate processing of the drop event if you need the drop zone itself to
18436 * be able to accept drops. It should return true when valid so that the drag source's repair action does not run.
18437 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18438 * @param {Event} e The event
18439 * @param {Object} data An object containing arbitrary data supplied by the drag source
18440 * @return {Boolean} True if the drop was valid, else false
18442 onContainerDrop : function(dd, e, data){
18447 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source is now over
18448 * the zone. The default implementation returns this.dropNotAllowed and expects that only registered drop
18449 * nodes can process drag drop operations, so if you need the drop zone itself to be able to process drops
18450 * you should override this method and provide a custom implementation.
18451 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18452 * @param {Event} e The event
18453 * @param {Object} data An object containing arbitrary data supplied by the drag source
18454 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18455 * underlying {@link Roo.dd.StatusProxy} can be updated
18457 notifyEnter : function(dd, e, data){
18458 return this.dropNotAllowed;
18462 * The function a {@link Roo.dd.DragSource} calls continuously while it is being dragged over the drop zone.
18463 * This method will be called on every mouse movement while the drag source is over the drop zone.
18464 * It will call {@link #onNodeOver} while the drag source is over a registered node, and will also automatically
18465 * delegate to the appropriate node-specific methods as necessary when the drag source enters and exits
18466 * registered nodes ({@link #onNodeEnter}, {@link #onNodeOut}). If the drag source is not currently over a
18467 * registered node, it will call {@link #onContainerOver}.
18468 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18469 * @param {Event} e The event
18470 * @param {Object} data An object containing arbitrary data supplied by the drag source
18471 * @return {String} status The CSS class that communicates the drop status back to the source so that the
18472 * underlying {@link Roo.dd.StatusProxy} can be updated
18474 notifyOver : function(dd, e, data){
18475 var n = this.getTargetFromEvent(e);
18476 if(!n){ // not over valid drop target
18477 if(this.lastOverNode){
18478 this.onNodeOut(this.lastOverNode, dd, e, data);
18479 this.lastOverNode = null;
18481 return this.onContainerOver(dd, e, data);
18483 if(this.lastOverNode != n){
18484 if(this.lastOverNode){
18485 this.onNodeOut(this.lastOverNode, dd, e, data);
18487 this.onNodeEnter(n, dd, e, data);
18488 this.lastOverNode = n;
18490 return this.onNodeOver(n, dd, e, data);
18494 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the source has been dragged
18495 * out of the zone without dropping. If the drag source is currently over a registered node, the notification
18496 * will be delegated to {@link #onNodeOut} for node-specific handling, otherwise it will be ignored.
18497 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop target
18498 * @param {Event} e The event
18499 * @param {Object} data An object containing arbitrary data supplied by the drag zone
18501 notifyOut : function(dd, e, data){
18502 if(this.lastOverNode){
18503 this.onNodeOut(this.lastOverNode, dd, e, data);
18504 this.lastOverNode = null;
18509 * The function a {@link Roo.dd.DragSource} calls once to notify this drop zone that the dragged item has
18510 * been dropped on it. The drag zone will look up the target node based on the event passed in, and if there
18511 * is a node registered for that event, it will delegate to {@link #onNodeDrop} for node-specific handling,
18512 * otherwise it will call {@link #onContainerDrop}.
18513 * @param {Roo.dd.DragSource} source The drag source that was dragged over this drop zone
18514 * @param {Event} e The event
18515 * @param {Object} data An object containing arbitrary data supplied by the drag source
18516 * @return {Boolean} True if the drop was valid, else false
18518 notifyDrop : function(dd, e, data){
18519 if(this.lastOverNode){
18520 this.onNodeOut(this.lastOverNode, dd, e, data);
18521 this.lastOverNode = null;
18523 var n = this.getTargetFromEvent(e);
18525 this.onNodeDrop(n, dd, e, data) :
18526 this.onContainerDrop(dd, e, data);
18530 triggerCacheRefresh : function(){
18531 Roo.dd.DDM.refreshCache(this.groups);
18535 * Ext JS Library 1.1.1
18536 * Copyright(c) 2006-2007, Ext JS, LLC.
18538 * Originally Released Under LGPL - original licence link has changed is not relivant.
18541 * <script type="text/javascript">
18546 * @class Roo.data.SortTypes
18548 * Defines the default sorting (casting?) comparison functions used when sorting data.
18550 Roo.data.SortTypes = {
18552 * Default sort that does nothing
18553 * @param {Mixed} s The value being converted
18554 * @return {Mixed} The comparison value
18556 none : function(s){
18561 * The regular expression used to strip tags
18565 stripTagsRE : /<\/?[^>]+>/gi,
18568 * Strips all HTML tags to sort on text only
18569 * @param {Mixed} s The value being converted
18570 * @return {String} The comparison value
18572 asText : function(s){
18573 return String(s).replace(this.stripTagsRE, "");
18577 * Strips all HTML tags to sort on text only - Case insensitive
18578 * @param {Mixed} s The value being converted
18579 * @return {String} The comparison value
18581 asUCText : function(s){
18582 return String(s).toUpperCase().replace(this.stripTagsRE, "");
18586 * Case insensitive string
18587 * @param {Mixed} s The value being converted
18588 * @return {String} The comparison value
18590 asUCString : function(s) {
18591 return String(s).toUpperCase();
18596 * @param {Mixed} s The value being converted
18597 * @return {Number} The comparison value
18599 asDate : function(s) {
18603 if(s instanceof Date){
18604 return s.getTime();
18606 return Date.parse(String(s));
18611 * @param {Mixed} s The value being converted
18612 * @return {Float} The comparison value
18614 asFloat : function(s) {
18615 var val = parseFloat(String(s).replace(/,/g, ""));
18616 if(isNaN(val)) val = 0;
18622 * @param {Mixed} s The value being converted
18623 * @return {Number} The comparison value
18625 asInt : function(s) {
18626 var val = parseInt(String(s).replace(/,/g, ""));
18627 if(isNaN(val)) val = 0;
18632 * Ext JS Library 1.1.1
18633 * Copyright(c) 2006-2007, Ext JS, LLC.
18635 * Originally Released Under LGPL - original licence link has changed is not relivant.
18638 * <script type="text/javascript">
18642 * @class Roo.data.Record
18643 * Instances of this class encapsulate both record <em>definition</em> information, and record
18644 * <em>value</em> information for use in {@link Roo.data.Store} objects, or any code which needs
18645 * to access Records cached in an {@link Roo.data.Store} object.<br>
18647 * Constructors for this class are generated by passing an Array of field definition objects to {@link #create}.
18648 * Instances are usually only created by {@link Roo.data.Reader} implementations when processing unformatted data
18651 * Record objects generated by this constructor inherit all the methods of Roo.data.Record listed below.
18653 * This constructor should not be used to create Record objects. Instead, use the constructor generated by
18654 * {@link #create}. The parameters are the same.
18655 * @param {Array} data An associative Array of data values keyed by the field name.
18656 * @param {Object} id (Optional) The id of the record. This id should be unique, and is used by the
18657 * {@link Roo.data.Store} object which owns the Record to index its collection of Records. If
18658 * not specified an integer id is generated.
18660 Roo.data.Record = function(data, id){
18661 this.id = (id || id === 0) ? id : ++Roo.data.Record.AUTO_ID;
18666 * Generate a constructor for a specific record layout.
18667 * @param {Array} o An Array of field definition objects which specify field names, and optionally,
18668 * data types, and a mapping for an {@link Roo.data.Reader} to extract the field's value from a data object.
18669 * Each field definition object may contain the following properties: <ul>
18670 * <li><b>name</b> : String<p style="margin-left:1em">The name by which the field is referenced within the Record. This is referenced by,
18671 * for example the <em>dataIndex</em> property in column definition objects passed to {@link Roo.grid.ColumnModel}</p></li>
18672 * <li><b>mapping</b> : String<p style="margin-left:1em">(Optional) A path specification for use by the {@link Roo.data.Reader} implementation
18673 * that is creating the Record to access the data value from the data object. If an {@link Roo.data.JsonReader}
18674 * is being used, then this is a string containing the javascript expression to reference the data relative to
18675 * the record item's root. If an {@link Roo.data.XmlReader} is being used, this is an {@link Roo.DomQuery} path
18676 * to the data item relative to the record element. If the mapping expression is the same as the field name,
18677 * this may be omitted.</p></li>
18678 * <li><b>type</b> : String<p style="margin-left:1em">(Optional) The data type for conversion to displayable value. Possible values are
18679 * <ul><li>auto (Default, implies no conversion)</li>
18684 * <li>date</li></ul></p></li>
18685 * <li><b>sortType</b> : Mixed<p style="margin-left:1em">(Optional) A member of {@link Roo.data.SortTypes}.</p></li>
18686 * <li><b>sortDir</b> : String<p style="margin-left:1em">(Optional) Initial direction to sort. "ASC" or "DESC"</p></li>
18687 * <li><b>convert</b> : Function<p style="margin-left:1em">(Optional) A function which converts the value provided
18688 * by the Reader into an object that will be stored in the Record. It is passed the
18689 * following parameters:<ul>
18690 * <li><b>v</b> : Mixed<p style="margin-left:1em">The data value as read by the Reader.</p></li>
18692 * <li><b>dateFormat</b> : String<p style="margin-left:1em">(Optional) A format String for the Date.parseDate function.</p></li>
18694 * <br>usage:<br><pre><code>
18695 var TopicRecord = Roo.data.Record.create(
18696 {name: 'title', mapping: 'topic_title'},
18697 {name: 'author', mapping: 'username'},
18698 {name: 'totalPosts', mapping: 'topic_replies', type: 'int'},
18699 {name: 'lastPost', mapping: 'post_time', type: 'date'},
18700 {name: 'lastPoster', mapping: 'user2'},
18701 {name: 'excerpt', mapping: 'post_text'}
18704 var myNewRecord = new TopicRecord({
18705 title: 'Do my job please',
18708 lastPost: new Date(),
18709 lastPoster: 'Animal',
18710 excerpt: 'No way dude!'
18712 myStore.add(myNewRecord);
18717 Roo.data.Record.create = function(o){
18718 var f = function(){
18719 f.superclass.constructor.apply(this, arguments);
18721 Roo.extend(f, Roo.data.Record);
18722 var p = f.prototype;
18723 p.fields = new Roo.util.MixedCollection(false, function(field){
18726 for(var i = 0, len = o.length; i < len; i++){
18727 p.fields.add(new Roo.data.Field(o[i]));
18729 f.getField = function(name){
18730 return p.fields.get(name);
18735 Roo.data.Record.AUTO_ID = 1000;
18736 Roo.data.Record.EDIT = 'edit';
18737 Roo.data.Record.REJECT = 'reject';
18738 Roo.data.Record.COMMIT = 'commit';
18740 Roo.data.Record.prototype = {
18742 * Readonly flag - true if this record has been modified.
18751 join : function(store){
18752 this.store = store;
18756 * Set the named field to the specified value.
18757 * @param {String} name The name of the field to set.
18758 * @param {Object} value The value to set the field to.
18760 set : function(name, value){
18761 if(this.data[name] == value){
18765 if(!this.modified){
18766 this.modified = {};
18768 if(typeof this.modified[name] == 'undefined'){
18769 this.modified[name] = this.data[name];
18771 this.data[name] = value;
18773 this.store.afterEdit(this);
18778 * Get the value of the named field.
18779 * @param {String} name The name of the field to get the value of.
18780 * @return {Object} The value of the field.
18782 get : function(name){
18783 return this.data[name];
18787 beginEdit : function(){
18788 this.editing = true;
18789 this.modified = {};
18793 cancelEdit : function(){
18794 this.editing = false;
18795 delete this.modified;
18799 endEdit : function(){
18800 this.editing = false;
18801 if(this.dirty && this.store){
18802 this.store.afterEdit(this);
18807 * Usually called by the {@link Roo.data.Store} which owns the Record.
18808 * Rejects all changes made to the Record since either creation, or the last commit operation.
18809 * Modified fields are reverted to their original values.
18811 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
18812 * of reject operations.
18814 reject : function(){
18815 var m = this.modified;
18817 if(typeof m[n] != "function"){
18818 this.data[n] = m[n];
18821 this.dirty = false;
18822 delete this.modified;
18823 this.editing = false;
18825 this.store.afterReject(this);
18830 * Usually called by the {@link Roo.data.Store} which owns the Record.
18831 * Commits all changes made to the Record since either creation, or the last commit operation.
18833 * Developers should subscribe to the {@link Roo.data.Store#update} event to have their code notified
18834 * of commit operations.
18836 commit : function(){
18837 this.dirty = false;
18838 delete this.modified;
18839 this.editing = false;
18841 this.store.afterCommit(this);
18846 hasError : function(){
18847 return this.error != null;
18851 clearError : function(){
18856 * Creates a copy of this record.
18857 * @param {String} id (optional) A new record id if you don't want to use this record's id
18860 copy : function(newId) {
18861 return new this.constructor(Roo.apply({}, this.data), newId || this.id);
18865 * Ext JS Library 1.1.1
18866 * Copyright(c) 2006-2007, Ext JS, LLC.
18868 * Originally Released Under LGPL - original licence link has changed is not relivant.
18871 * <script type="text/javascript">
18877 * @class Roo.data.Store
18878 * @extends Roo.util.Observable
18879 * The Store class encapsulates a client side cache of {@link Roo.data.Record} objects which provide input data
18880 * for widgets such as the Roo.grid.Grid, or the Roo.form.ComboBox.<br>
18882 * A Store object uses an implementation of {@link Roo.data.DataProxy} to access a data object unless you call loadData() directly and pass in your data. The Store object
18883 * has no knowledge of the format of the data returned by the Proxy.<br>
18885 * A Store object uses its configured implementation of {@link Roo.data.DataReader} to create {@link Roo.data.Record}
18886 * instances from the data object. These records are cached and made available through accessor functions.
18888 * Creates a new Store.
18889 * @param {Object} config A config object containing the objects needed for the Store to access data,
18890 * and read the data into Records.
18892 Roo.data.Store = function(config){
18893 this.data = new Roo.util.MixedCollection(false);
18894 this.data.getKey = function(o){
18897 this.baseParams = {};
18899 this.paramNames = {
18906 if(config && config.data){
18907 this.inlineData = config.data;
18908 delete config.data;
18911 Roo.apply(this, config);
18913 if(this.reader){ // reader passed
18914 this.reader = Roo.factory(this.reader, Roo.data);
18915 this.reader.xmodule = this.xmodule || false;
18916 if(!this.recordType){
18917 this.recordType = this.reader.recordType;
18919 if(this.reader.onMetaChange){
18920 this.reader.onMetaChange = this.onMetaChange.createDelegate(this);
18924 if(this.recordType){
18925 this.fields = this.recordType.prototype.fields;
18927 this.modified = [];
18931 * @event datachanged
18932 * Fires when the data cache has changed, and a widget which is using this Store
18933 * as a Record cache should refresh its view.
18934 * @param {Store} this
18936 datachanged : true,
18938 * @event metachange
18939 * Fires when this store's reader provides new metadata (fields). This is currently only support for JsonReaders.
18940 * @param {Store} this
18941 * @param {Object} meta The JSON metadata
18946 * Fires when Records have been added to the Store
18947 * @param {Store} this
18948 * @param {Roo.data.Record[]} records The array of Records added
18949 * @param {Number} index The index at which the record(s) were added
18954 * Fires when a Record has been removed from the Store
18955 * @param {Store} this
18956 * @param {Roo.data.Record} record The Record that was removed
18957 * @param {Number} index The index at which the record was removed
18962 * Fires when a Record has been updated
18963 * @param {Store} this
18964 * @param {Roo.data.Record} record The Record that was updated
18965 * @param {String} operation The update operation being performed. Value may be one of:
18967 Roo.data.Record.EDIT
18968 Roo.data.Record.REJECT
18969 Roo.data.Record.COMMIT
18975 * Fires when the data cache has been cleared.
18976 * @param {Store} this
18980 * @event beforeload
18981 * Fires before a request is made for a new data object. If the beforeload handler returns false
18982 * the load action will be canceled.
18983 * @param {Store} this
18984 * @param {Object} options The loading options that were specified (see {@link #load} for details)
18989 * Fires after a new set of Records has been loaded.
18990 * @param {Store} this
18991 * @param {Roo.data.Record[]} records The Records that were loaded
18992 * @param {Object} options The loading options that were specified (see {@link #load} for details)
18996 * @event loadexception
18997 * Fires if an exception occurs in the Proxy during loading.
18998 * Called with the signature of the Proxy's "loadexception" event.
18999 * If you return Json { data: [] , success: false, .... } then this will be thrown with the following args
19002 * @param {Object} return from JsonData.reader() - success, totalRecords, records
19003 * @param {Object} load options
19004 * @param {Object} jsonData from your request (normally this contains the Exception)
19006 loadexception : true
19010 this.proxy = Roo.factory(this.proxy, Roo.data);
19011 this.proxy.xmodule = this.xmodule || false;
19012 this.relayEvents(this.proxy, ["loadexception"]);
19014 this.sortToggle = {};
19016 Roo.data.Store.superclass.constructor.call(this);
19018 if(this.inlineData){
19019 this.loadData(this.inlineData);
19020 delete this.inlineData;
19023 Roo.extend(Roo.data.Store, Roo.util.Observable, {
19025 * @cfg {boolean} isLocal flag if data is locally available (and can be always looked up
19026 * without a remote query - used by combo/forms at present.
19030 * @cfg {Roo.data.DataProxy} proxy The Proxy object which provides access to a data object.
19033 * @cfg {Array} data Inline data to be loaded when the store is initialized.
19036 * @cfg {Roo.data.Reader} reader The Reader object which processes the data object and returns
19037 * an Array of Roo.data.record objects which are cached keyed by their <em>id</em> property.
19040 * @cfg {Object} baseParams An object containing properties which are to be sent as parameters
19041 * on any HTTP request
19044 * @cfg {Object} sortInfo A config object in the format: {field: "fieldName", direction: "ASC|DESC"}
19047 * @cfg {boolean} remoteSort True if sorting is to be handled by requesting the Proxy to provide a refreshed
19048 * version of the data object in sorted order, as opposed to sorting the Record cache in place (defaults to false).
19050 remoteSort : false,
19053 * @cfg {boolean} pruneModifiedRecords True to clear all modified record information each time the store is
19054 * loaded or when a record is removed. (defaults to false).
19056 pruneModifiedRecords : false,
19059 lastOptions : null,
19062 * Add Records to the Store and fires the add event.
19063 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
19065 add : function(records){
19066 records = [].concat(records);
19067 for(var i = 0, len = records.length; i < len; i++){
19068 records[i].join(this);
19070 var index = this.data.length;
19071 this.data.addAll(records);
19072 this.fireEvent("add", this, records, index);
19076 * Remove a Record from the Store and fires the remove event.
19077 * @param {Ext.data.Record} record The Roo.data.Record object to remove from the cache.
19079 remove : function(record){
19080 var index = this.data.indexOf(record);
19081 this.data.removeAt(index);
19082 if(this.pruneModifiedRecords){
19083 this.modified.remove(record);
19085 this.fireEvent("remove", this, record, index);
19089 * Remove all Records from the Store and fires the clear event.
19091 removeAll : function(){
19093 if(this.pruneModifiedRecords){
19094 this.modified = [];
19096 this.fireEvent("clear", this);
19100 * Inserts Records to the Store at the given index and fires the add event.
19101 * @param {Number} index The start index at which to insert the passed Records.
19102 * @param {Roo.data.Record[]} records An Array of Roo.data.Record objects to add to the cache.
19104 insert : function(index, records){
19105 records = [].concat(records);
19106 for(var i = 0, len = records.length; i < len; i++){
19107 this.data.insert(index, records[i]);
19108 records[i].join(this);
19110 this.fireEvent("add", this, records, index);
19114 * Get the index within the cache of the passed Record.
19115 * @param {Roo.data.Record} record The Roo.data.Record object to to find.
19116 * @return {Number} The index of the passed Record. Returns -1 if not found.
19118 indexOf : function(record){
19119 return this.data.indexOf(record);
19123 * Get the index within the cache of the Record with the passed id.
19124 * @param {String} id The id of the Record to find.
19125 * @return {Number} The index of the Record. Returns -1 if not found.
19127 indexOfId : function(id){
19128 return this.data.indexOfKey(id);
19132 * Get the Record with the specified id.
19133 * @param {String} id The id of the Record to find.
19134 * @return {Roo.data.Record} The Record with the passed id. Returns undefined if not found.
19136 getById : function(id){
19137 return this.data.key(id);
19141 * Get the Record at the specified index.
19142 * @param {Number} index The index of the Record to find.
19143 * @return {Roo.data.Record} The Record at the passed index. Returns undefined if not found.
19145 getAt : function(index){
19146 return this.data.itemAt(index);
19150 * Returns a range of Records between specified indices.
19151 * @param {Number} startIndex (optional) The starting index (defaults to 0)
19152 * @param {Number} endIndex (optional) The ending index (defaults to the last Record in the Store)
19153 * @return {Roo.data.Record[]} An array of Records
19155 getRange : function(start, end){
19156 return this.data.getRange(start, end);
19160 storeOptions : function(o){
19161 o = Roo.apply({}, o);
19164 this.lastOptions = o;
19168 * Loads the Record cache from the configured Proxy using the configured Reader.
19170 * If using remote paging, then the first load call must specify the <em>start</em>
19171 * and <em>limit</em> properties in the options.params property to establish the initial
19172 * position within the dataset, and the number of Records to cache on each read from the Proxy.
19174 * <strong>It is important to note that for remote data sources, loading is asynchronous,
19175 * and this call will return before the new data has been loaded. Perform any post-processing
19176 * in a callback function, or in a "load" event handler.</strong>
19178 * @param {Object} options An object containing properties which control loading options:<ul>
19179 * <li>params {Object} An object containing properties to pass as HTTP parameters to a remote data source.</li>
19180 * <li>callback {Function} A function to be called after the Records have been loaded. The callback is
19181 * passed the following arguments:<ul>
19182 * <li>r : Roo.data.Record[]</li>
19183 * <li>options: Options object from the load call</li>
19184 * <li>success: Boolean success indicator</li></ul></li>
19185 * <li>scope {Object} Scope with which to call the callback (defaults to the Store object)</li>
19186 * <li>add {Boolean} indicator to append loaded records rather than replace the current cache.</li>
19189 load : function(options){
19190 options = options || {};
19191 if(this.fireEvent("beforeload", this, options) !== false){
19192 this.storeOptions(options);
19193 var p = Roo.apply(options.params || {}, this.baseParams);
19194 if(this.sortInfo && this.remoteSort){
19195 var pn = this.paramNames;
19196 p[pn["sort"]] = this.sortInfo.field;
19197 p[pn["dir"]] = this.sortInfo.direction;
19199 this.proxy.load(p, this.reader, this.loadRecords, this, options);
19204 * Reloads the Record cache from the configured Proxy using the configured Reader and
19205 * the options from the last load operation performed.
19206 * @param {Object} options (optional) An object containing properties which may override the options
19207 * used in the last load operation. See {@link #load} for details (defaults to null, in which case
19208 * the most recently used options are reused).
19210 reload : function(options){
19211 this.load(Roo.applyIf(options||{}, this.lastOptions));
19215 // Called as a callback by the Reader during a load operation.
19216 loadRecords : function(o, options, success){
19217 if(!o || success === false){
19218 if(success !== false){
19219 this.fireEvent("load", this, [], options);
19221 if(options.callback){
19222 options.callback.call(options.scope || this, [], options, false);
19226 // if data returned failure - throw an exception.
19227 if (o.success === false) {
19228 this.fireEvent("loadexception", this, o, options, this.reader.jsonData);
19231 var r = o.records, t = o.totalRecords || r.length;
19232 if(!options || options.add !== true){
19233 if(this.pruneModifiedRecords){
19234 this.modified = [];
19236 for(var i = 0, len = r.length; i < len; i++){
19240 this.data = this.snapshot;
19241 delete this.snapshot;
19244 this.data.addAll(r);
19245 this.totalLength = t;
19247 this.fireEvent("datachanged", this);
19249 this.totalLength = Math.max(t, this.data.length+r.length);
19252 this.fireEvent("load", this, r, options);
19253 if(options.callback){
19254 options.callback.call(options.scope || this, r, options, true);
19259 * Loads data from a passed data block. A Reader which understands the format of the data
19260 * must have been configured in the constructor.
19261 * @param {Object} data The data block from which to read the Records. The format of the data expected
19262 * is dependent on the type of Reader that is configured and should correspond to that Reader's readRecords parameter.
19263 * @param {Boolean} append (Optional) True to append the new Records rather than replace the existing cache.
19265 loadData : function(o, append){
19266 var r = this.reader.readRecords(o);
19267 this.loadRecords(r, {add: append}, true);
19271 * Gets the number of cached records.
19273 * <em>If using paging, this may not be the total size of the dataset. If the data object
19274 * used by the Reader contains the dataset size, then the getTotalCount() function returns
19275 * the data set size</em>
19277 getCount : function(){
19278 return this.data.length || 0;
19282 * Gets the total number of records in the dataset as returned by the server.
19284 * <em>If using paging, for this to be accurate, the data object used by the Reader must contain
19285 * the dataset size</em>
19287 getTotalCount : function(){
19288 return this.totalLength || 0;
19292 * Returns the sort state of the Store as an object with two properties:
19294 field {String} The name of the field by which the Records are sorted
19295 direction {String} The sort order, "ASC" or "DESC"
19298 getSortState : function(){
19299 return this.sortInfo;
19303 applySort : function(){
19304 if(this.sortInfo && !this.remoteSort){
19305 var s = this.sortInfo, f = s.field;
19306 var st = this.fields.get(f).sortType;
19307 var fn = function(r1, r2){
19308 var v1 = st(r1.data[f]), v2 = st(r2.data[f]);
19309 return v1 > v2 ? 1 : (v1 < v2 ? -1 : 0);
19311 this.data.sort(s.direction, fn);
19312 if(this.snapshot && this.snapshot != this.data){
19313 this.snapshot.sort(s.direction, fn);
19319 * Sets the default sort column and order to be used by the next load operation.
19320 * @param {String} fieldName The name of the field to sort by.
19321 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
19323 setDefaultSort : function(field, dir){
19324 this.sortInfo = {field: field, direction: dir ? dir.toUpperCase() : "ASC"};
19328 * Sort the Records.
19329 * If remote sorting is used, the sort is performed on the server, and the cache is
19330 * reloaded. If local sorting is used, the cache is sorted internally.
19331 * @param {String} fieldName The name of the field to sort by.
19332 * @param {String} dir (optional) The sort order, "ASC" or "DESC" (defaults to "ASC")
19334 sort : function(fieldName, dir){
19335 var f = this.fields.get(fieldName);
19337 if(this.sortInfo && this.sortInfo.field == f.name){ // toggle sort dir
19338 dir = (this.sortToggle[f.name] || "ASC").toggle("ASC", "DESC");
19343 this.sortToggle[f.name] = dir;
19344 this.sortInfo = {field: f.name, direction: dir};
19345 if(!this.remoteSort){
19347 this.fireEvent("datachanged", this);
19349 this.load(this.lastOptions);
19354 * Calls the specified function for each of the Records in the cache.
19355 * @param {Function} fn The function to call. The Record is passed as the first parameter.
19356 * Returning <em>false</em> aborts and exits the iteration.
19357 * @param {Object} scope (optional) The scope in which to call the function (defaults to the Record).
19359 each : function(fn, scope){
19360 this.data.each(fn, scope);
19364 * Gets all records modified since the last commit. Modified records are persisted across load operations
19365 * (e.g., during paging).
19366 * @return {Roo.data.Record[]} An array of Records containing outstanding modifications.
19368 getModifiedRecords : function(){
19369 return this.modified;
19373 createFilterFn : function(property, value, anyMatch){
19374 if(!value.exec){ // not a regex
19375 value = String(value);
19376 if(value.length == 0){
19379 value = new RegExp((anyMatch === true ? '' : '^') + Roo.escapeRe(value), "i");
19381 return function(r){
19382 return value.test(r.data[property]);
19387 * Sums the value of <i>property</i> for each record between start and end and returns the result.
19388 * @param {String} property A field on your records
19389 * @param {Number} start The record index to start at (defaults to 0)
19390 * @param {Number} end The last record index to include (defaults to length - 1)
19391 * @return {Number} The sum
19393 sum : function(property, start, end){
19394 var rs = this.data.items, v = 0;
19395 start = start || 0;
19396 end = (end || end === 0) ? end : rs.length-1;
19398 for(var i = start; i <= end; i++){
19399 v += (rs[i].data[property] || 0);
19405 * Filter the records by a specified property.
19406 * @param {String} field A field on your records
19407 * @param {String/RegExp} value Either a string that the field
19408 * should start with or a RegExp to test against the field
19409 * @param {Boolean} anyMatch True to match any part not just the beginning
19411 filter : function(property, value, anyMatch){
19412 var fn = this.createFilterFn(property, value, anyMatch);
19413 return fn ? this.filterBy(fn) : this.clearFilter();
19417 * Filter by a function. The specified function will be called with each
19418 * record in this data source. If the function returns true the record is included,
19419 * otherwise it is filtered.
19420 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
19421 * @param {Object} scope (optional) The scope of the function (defaults to this)
19423 filterBy : function(fn, scope){
19424 this.snapshot = this.snapshot || this.data;
19425 this.data = this.queryBy(fn, scope||this);
19426 this.fireEvent("datachanged", this);
19430 * Query the records by a specified property.
19431 * @param {String} field A field on your records
19432 * @param {String/RegExp} value Either a string that the field
19433 * should start with or a RegExp to test against the field
19434 * @param {Boolean} anyMatch True to match any part not just the beginning
19435 * @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
19437 query : function(property, value, anyMatch){
19438 var fn = this.createFilterFn(property, value, anyMatch);
19439 return fn ? this.queryBy(fn) : this.data.clone();
19443 * Query by a function. The specified function will be called with each
19444 * record in this data source. If the function returns true the record is included
19446 * @param {Function} fn The function to be called, it will receive 2 args (record, id)
19447 * @param {Object} scope (optional) The scope of the function (defaults to this)
19448 @return {MixedCollection} Returns an Roo.util.MixedCollection of the matched records
19450 queryBy : function(fn, scope){
19451 var data = this.snapshot || this.data;
19452 return data.filterBy(fn, scope||this);
19456 * Collects unique values for a particular dataIndex from this store.
19457 * @param {String} dataIndex The property to collect
19458 * @param {Boolean} allowNull (optional) Pass true to allow null, undefined or empty string values
19459 * @param {Boolean} bypassFilter (optional) Pass true to collect from all records, even ones which are filtered
19460 * @return {Array} An array of the unique values
19462 collect : function(dataIndex, allowNull, bypassFilter){
19463 var d = (bypassFilter === true && this.snapshot) ?
19464 this.snapshot.items : this.data.items;
19465 var v, sv, r = [], l = {};
19466 for(var i = 0, len = d.length; i < len; i++){
19467 v = d[i].data[dataIndex];
19469 if((allowNull || !Roo.isEmpty(v)) && !l[sv]){
19478 * Revert to a view of the Record cache with no filtering applied.
19479 * @param {Boolean} suppressEvent If true the filter is cleared silently without notifying listeners
19481 clearFilter : function(suppressEvent){
19482 if(this.snapshot && this.snapshot != this.data){
19483 this.data = this.snapshot;
19484 delete this.snapshot;
19485 if(suppressEvent !== true){
19486 this.fireEvent("datachanged", this);
19492 afterEdit : function(record){
19493 if(this.modified.indexOf(record) == -1){
19494 this.modified.push(record);
19496 this.fireEvent("update", this, record, Roo.data.Record.EDIT);
19500 afterReject : function(record){
19501 this.modified.remove(record);
19502 this.fireEvent("update", this, record, Roo.data.Record.REJECT);
19506 afterCommit : function(record){
19507 this.modified.remove(record);
19508 this.fireEvent("update", this, record, Roo.data.Record.COMMIT);
19512 * Commit all Records with outstanding changes. To handle updates for changes, subscribe to the
19513 * Store's "update" event, and perform updating when the third parameter is Roo.data.Record.COMMIT.
19515 commitChanges : function(){
19516 var m = this.modified.slice(0);
19517 this.modified = [];
19518 for(var i = 0, len = m.length; i < len; i++){
19524 * Cancel outstanding changes on all changed records.
19526 rejectChanges : function(){
19527 var m = this.modified.slice(0);
19528 this.modified = [];
19529 for(var i = 0, len = m.length; i < len; i++){
19534 onMetaChange : function(meta, rtype, o){
19535 this.recordType = rtype;
19536 this.fields = rtype.prototype.fields;
19537 delete this.snapshot;
19538 this.sortInfo = meta.sortInfo;
19539 this.modified = [];
19540 this.fireEvent('metachange', this, this.reader.meta);
19544 * Ext JS Library 1.1.1
19545 * Copyright(c) 2006-2007, Ext JS, LLC.
19547 * Originally Released Under LGPL - original licence link has changed is not relivant.
19550 * <script type="text/javascript">
19554 * @class Roo.data.SimpleStore
19555 * @extends Roo.data.Store
19556 * Small helper class to make creating Stores from Array data easier.
19557 * @cfg {Number} id The array index of the record id. Leave blank to auto generate ids.
19558 * @cfg {Array} fields An array of field definition objects, or field name strings.
19559 * @cfg {Array} data The multi-dimensional array of data
19561 * @param {Object} config
19563 Roo.data.SimpleStore = function(config){
19564 Roo.data.SimpleStore.superclass.constructor.call(this, {
19566 reader: new Roo.data.ArrayReader({
19569 Roo.data.Record.create(config.fields)
19571 proxy : new Roo.data.MemoryProxy(config.data)
19575 Roo.extend(Roo.data.SimpleStore, Roo.data.Store);/*
19577 * Ext JS Library 1.1.1
19578 * Copyright(c) 2006-2007, Ext JS, LLC.
19580 * Originally Released Under LGPL - original licence link has changed is not relivant.
19583 * <script type="text/javascript">
19588 * @extends Roo.data.Store
19589 * @class Roo.data.JsonStore
19590 * Small helper class to make creating Stores for JSON data easier. <br/>
19592 var store = new Roo.data.JsonStore({
19593 url: 'get-images.php',
19595 fields: ['name', 'url', {name:'size', type: 'float'}, {name:'lastmod', type:'date'}]
19598 * <b>Note: Although they are not listed, this class inherits all of the config options of Store,
19599 * JsonReader and HttpProxy (unless inline data is provided).</b>
19600 * @cfg {Array} fields An array of field definition objects, or field name strings.
19602 * @param {Object} config
19604 Roo.data.JsonStore = function(c){
19605 Roo.data.JsonStore.superclass.constructor.call(this, Roo.apply(c, {
19606 proxy: !c.data ? new Roo.data.HttpProxy({url: c.url}) : undefined,
19607 reader: new Roo.data.JsonReader(c, c.fields)
19610 Roo.extend(Roo.data.JsonStore, Roo.data.Store);/*
19612 * Ext JS Library 1.1.1
19613 * Copyright(c) 2006-2007, Ext JS, LLC.
19615 * Originally Released Under LGPL - original licence link has changed is not relivant.
19618 * <script type="text/javascript">
19622 Roo.data.Field = function(config){
19623 if(typeof config == "string"){
19624 config = {name: config};
19626 Roo.apply(this, config);
19629 this.type = "auto";
19632 var st = Roo.data.SortTypes;
19633 // named sortTypes are supported, here we look them up
19634 if(typeof this.sortType == "string"){
19635 this.sortType = st[this.sortType];
19638 // set default sortType for strings and dates
19639 if(!this.sortType){
19642 this.sortType = st.asUCString;
19645 this.sortType = st.asDate;
19648 this.sortType = st.none;
19653 var stripRe = /[\$,%]/g;
19655 // prebuilt conversion function for this field, instead of
19656 // switching every time we're reading a value
19658 var cv, dateFormat = this.dateFormat;
19663 cv = function(v){ return v; };
19666 cv = function(v){ return (v === undefined || v === null) ? '' : String(v); };
19670 return v !== undefined && v !== null && v !== '' ?
19671 parseInt(String(v).replace(stripRe, ""), 10) : '';
19676 return v !== undefined && v !== null && v !== '' ?
19677 parseFloat(String(v).replace(stripRe, ""), 10) : '';
19682 cv = function(v){ return v === true || v === "true" || v == 1; };
19689 if(v instanceof Date){
19693 if(dateFormat == "timestamp"){
19694 return new Date(v*1000);
19696 return Date.parseDate(v, dateFormat);
19698 var parsed = Date.parse(v);
19699 return parsed ? new Date(parsed) : null;
19708 Roo.data.Field.prototype = {
19716 * Ext JS Library 1.1.1
19717 * Copyright(c) 2006-2007, Ext JS, LLC.
19719 * Originally Released Under LGPL - original licence link has changed is not relivant.
19722 * <script type="text/javascript">
19725 // Base class for reading structured data from a data source. This class is intended to be
19726 // extended (see ArrayReader, JsonReader and XmlReader) and should not be created directly.
19729 * @class Roo.data.DataReader
19730 * Base class for reading structured data from a data source. This class is intended to be
19731 * extended (see {Roo.data.ArrayReader}, {Roo.data.JsonReader} and {Roo.data.XmlReader}) and should not be created directly.
19734 Roo.data.DataReader = function(meta, recordType){
19738 this.recordType = recordType instanceof Array ?
19739 Roo.data.Record.create(recordType) : recordType;
19742 Roo.data.DataReader.prototype = {
19744 * Create an empty record
19745 * @param {Object} data (optional) - overlay some values
19746 * @return {Roo.data.Record} record created.
19748 newRow : function(d) {
19750 this.recordType.prototype.fields.each(function(c) {
19752 case 'int' : da[c.name] = 0; break;
19753 case 'date' : da[c.name] = new Date(); break;
19754 case 'float' : da[c.name] = 0.0; break;
19755 case 'boolean' : da[c.name] = false; break;
19756 default : da[c.name] = ""; break;
19760 return new this.recordType(Roo.apply(da, d));
19765 * Ext JS Library 1.1.1
19766 * Copyright(c) 2006-2007, Ext JS, LLC.
19768 * Originally Released Under LGPL - original licence link has changed is not relivant.
19771 * <script type="text/javascript">
19775 * @class Roo.data.DataProxy
19776 * @extends Roo.data.Observable
19777 * This class is an abstract base class for implementations which provide retrieval of
19778 * unformatted data objects.<br>
19780 * DataProxy implementations are usually used in conjunction with an implementation of Roo.data.DataReader
19781 * (of the appropriate type which knows how to parse the data object) to provide a block of
19782 * {@link Roo.data.Records} to an {@link Roo.data.Store}.<br>
19784 * Custom implementations must implement the load method as described in
19785 * {@link Roo.data.HttpProxy#load}.
19787 Roo.data.DataProxy = function(){
19790 * @event beforeload
19791 * Fires before a network request is made to retrieve a data object.
19792 * @param {Object} This DataProxy object.
19793 * @param {Object} params The params parameter to the load function.
19798 * Fires before the load method's callback is called.
19799 * @param {Object} This DataProxy object.
19800 * @param {Object} o The data object.
19801 * @param {Object} arg The callback argument object passed to the load function.
19805 * @event loadexception
19806 * Fires if an Exception occurs during data retrieval.
19807 * @param {Object} This DataProxy object.
19808 * @param {Object} o The data object.
19809 * @param {Object} arg The callback argument object passed to the load function.
19810 * @param {Object} e The Exception.
19812 loadexception : true
19814 Roo.data.DataProxy.superclass.constructor.call(this);
19817 Roo.extend(Roo.data.DataProxy, Roo.util.Observable);
19820 * @cfg {void} listeners (Not available) Constructor blocks listeners from being set
19824 * Ext JS Library 1.1.1
19825 * Copyright(c) 2006-2007, Ext JS, LLC.
19827 * Originally Released Under LGPL - original licence link has changed is not relivant.
19830 * <script type="text/javascript">
19833 * @class Roo.data.MemoryProxy
19834 * An implementation of Roo.data.DataProxy that simply passes the data specified in its constructor
19835 * to the Reader when its load method is called.
19837 * @param {Object} data The data object which the Reader uses to construct a block of Roo.data.Records.
19839 Roo.data.MemoryProxy = function(data){
19843 Roo.data.MemoryProxy.superclass.constructor.call(this);
19847 Roo.extend(Roo.data.MemoryProxy, Roo.data.DataProxy, {
19849 * Load data from the requested source (in this case an in-memory
19850 * data object passed to the constructor), read the data object into
19851 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
19852 * process that block using the passed callback.
19853 * @param {Object} params This parameter is not used by the MemoryProxy class.
19854 * @param {Roo.data.DataReader} reader The Reader object which converts the data
19855 * object into a block of Roo.data.Records.
19856 * @param {Function} callback The function into which to pass the block of Roo.data.records.
19857 * The function must be passed <ul>
19858 * <li>The Record block object</li>
19859 * <li>The "arg" argument from the load function</li>
19860 * <li>A boolean success indicator</li>
19862 * @param {Object} scope The scope in which to call the callback
19863 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
19865 load : function(params, reader, callback, scope, arg){
19866 params = params || {};
19869 result = reader.readRecords(this.data);
19871 this.fireEvent("loadexception", this, arg, null, e);
19872 callback.call(scope, null, arg, false);
19875 callback.call(scope, result, arg, true);
19879 update : function(params, records){
19884 * Ext JS Library 1.1.1
19885 * Copyright(c) 2006-2007, Ext JS, LLC.
19887 * Originally Released Under LGPL - original licence link has changed is not relivant.
19890 * <script type="text/javascript">
19893 * @class Roo.data.HttpProxy
19894 * @extends Roo.data.DataProxy
19895 * An implementation of {@link Roo.data.DataProxy} that reads a data object from an {@link Roo.data.Connection} object
19896 * configured to reference a certain URL.<br><br>
19898 * <em>Note that this class cannot be used to retrieve data from a domain other than the domain
19899 * from which the running page was served.<br><br>
19901 * For cross-domain access to remote data, use an {@link Roo.data.ScriptTagProxy}.</em><br><br>
19903 * Be aware that to enable the browser to parse an XML document, the server must set
19904 * the Content-Type header in the HTTP response to "text/xml".
19906 * @param {Object} conn Connection config options to add to each request (e.g. {url: 'foo.php'} or
19907 * an {@link Roo.data.Connection} object. If a Connection config is passed, the singleton {@link Roo.Ajax} object
19908 * will be used to make the request.
19910 Roo.data.HttpProxy = function(conn){
19911 Roo.data.HttpProxy.superclass.constructor.call(this);
19912 // is conn a conn config or a real conn?
19914 this.useAjax = !conn || !conn.events;
19918 Roo.extend(Roo.data.HttpProxy, Roo.data.DataProxy, {
19919 // thse are take from connection...
19922 * @cfg {String} url (Optional) The default URL to be used for requests to the server. (defaults to undefined)
19925 * @cfg {Object} extraParams (Optional) An object containing properties which are used as
19926 * extra parameters to each request made by this object. (defaults to undefined)
19929 * @cfg {Object} defaultHeaders (Optional) An object containing request headers which are added
19930 * to each request made by this object. (defaults to undefined)
19933 * @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)
19936 * @cfg {Number} timeout (Optional) The timeout in milliseconds to be used for requests. (defaults to 30000)
19939 * @cfg {Boolean} autoAbort (Optional) Whether this request should abort any pending requests. (defaults to false)
19945 * @cfg {Boolean} disableCaching (Optional) True to add a unique cache-buster param to GET requests. (defaults to true)
19949 * Return the {@link Roo.data.Connection} object being used by this Proxy.
19950 * @return {Connection} The Connection object. This object may be used to subscribe to events on
19951 * a finer-grained basis than the DataProxy events.
19953 getConnection : function(){
19954 return this.useAjax ? Roo.Ajax : this.conn;
19958 * Load data from the configured {@link Roo.data.Connection}, read the data object into
19959 * a block of Roo.data.Records using the passed {@link Roo.data.DataReader} implementation, and
19960 * process that block using the passed callback.
19961 * @param {Object} params An object containing properties which are to be used as HTTP parameters
19962 * for the request to the remote server.
19963 * @param {Roo.data.DataReader} reader The Reader object which converts the data
19964 * object into a block of Roo.data.Records.
19965 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
19966 * The function must be passed <ul>
19967 * <li>The Record block object</li>
19968 * <li>The "arg" argument from the load function</li>
19969 * <li>A boolean success indicator</li>
19971 * @param {Object} scope The scope in which to call the callback
19972 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
19974 load : function(params, reader, callback, scope, arg){
19975 if(this.fireEvent("beforeload", this, params) !== false){
19977 params : params || {},
19979 callback : callback,
19984 callback : this.loadResponse,
19988 Roo.applyIf(o, this.conn);
19989 if(this.activeRequest){
19990 Roo.Ajax.abort(this.activeRequest);
19992 this.activeRequest = Roo.Ajax.request(o);
19994 this.conn.request(o);
19997 callback.call(scope||this, null, arg, false);
20002 loadResponse : function(o, success, response){
20003 delete this.activeRequest;
20005 this.fireEvent("loadexception", this, o, response);
20006 o.request.callback.call(o.request.scope, null, o.request.arg, false);
20011 result = o.reader.read(response);
20013 this.fireEvent("loadexception", this, o, response, e);
20014 o.request.callback.call(o.request.scope, null, o.request.arg, false);
20018 this.fireEvent("load", this, o, o.request.arg);
20019 o.request.callback.call(o.request.scope, result, o.request.arg, true);
20023 update : function(dataSet){
20028 updateResponse : function(dataSet){
20033 * Ext JS Library 1.1.1
20034 * Copyright(c) 2006-2007, Ext JS, LLC.
20036 * Originally Released Under LGPL - original licence link has changed is not relivant.
20039 * <script type="text/javascript">
20043 * @class Roo.data.ScriptTagProxy
20044 * An implementation of Roo.data.DataProxy that reads a data object from a URL which may be in a domain
20045 * other than the originating domain of the running page.<br><br>
20047 * <em>Note that if you are retrieving data from a page that is in a domain that is NOT the same as the originating domain
20048 * of the running page, you must use this class, rather than DataProxy.</em><br><br>
20050 * The content passed back from a server resource requested by a ScriptTagProxy is executable JavaScript
20051 * source code that is used as the source inside a <script> tag.<br><br>
20053 * In order for the browser to process the returned data, the server must wrap the data object
20054 * with a call to a callback function, the name of which is passed as a parameter by the ScriptTagProxy.
20055 * Below is a Java example for a servlet which returns data for either a ScriptTagProxy, or an HttpProxy
20056 * depending on whether the callback name was passed:
20059 boolean scriptTag = false;
20060 String cb = request.getParameter("callback");
20063 response.setContentType("text/javascript");
20065 response.setContentType("application/x-json");
20067 Writer out = response.getWriter();
20069 out.write(cb + "(");
20071 out.print(dataBlock.toJsonString());
20078 * @param {Object} config A configuration object.
20080 Roo.data.ScriptTagProxy = function(config){
20081 Roo.data.ScriptTagProxy.superclass.constructor.call(this);
20082 Roo.apply(this, config);
20083 this.head = document.getElementsByTagName("head")[0];
20086 Roo.data.ScriptTagProxy.TRANS_ID = 1000;
20088 Roo.extend(Roo.data.ScriptTagProxy, Roo.data.DataProxy, {
20090 * @cfg {String} url The URL from which to request the data object.
20093 * @cfg {Number} timeout (Optional) The number of milliseconds to wait for a response. Defaults to 30 seconds.
20097 * @cfg {String} callbackParam (Optional) The name of the parameter to pass to the server which tells
20098 * the server the name of the callback function set up by the load call to process the returned data object.
20099 * Defaults to "callback".<p>The server-side processing must read this parameter value, and generate
20100 * javascript output which calls this named function passing the data object as its only parameter.
20102 callbackParam : "callback",
20104 * @cfg {Boolean} nocache (Optional) Defaults to true. Disable cacheing by adding a unique parameter
20105 * name to the request.
20110 * Load data from the configured URL, read the data object into
20111 * a block of Roo.data.Records using the passed Roo.data.DataReader implementation, and
20112 * process that block using the passed callback.
20113 * @param {Object} params An object containing properties which are to be used as HTTP parameters
20114 * for the request to the remote server.
20115 * @param {Roo.data.DataReader} reader The Reader object which converts the data
20116 * object into a block of Roo.data.Records.
20117 * @param {Function} callback The function into which to pass the block of Roo.data.Records.
20118 * The function must be passed <ul>
20119 * <li>The Record block object</li>
20120 * <li>The "arg" argument from the load function</li>
20121 * <li>A boolean success indicator</li>
20123 * @param {Object} scope The scope in which to call the callback
20124 * @param {Object} arg An optional argument which is passed to the callback as its second parameter.
20126 load : function(params, reader, callback, scope, arg){
20127 if(this.fireEvent("beforeload", this, params) !== false){
20129 var p = Roo.urlEncode(Roo.apply(params, this.extraParams));
20131 var url = this.url;
20132 url += (url.indexOf("?") != -1 ? "&" : "?") + p;
20134 url += "&_dc=" + (new Date().getTime());
20136 var transId = ++Roo.data.ScriptTagProxy.TRANS_ID;
20139 cb : "stcCallback"+transId,
20140 scriptId : "stcScript"+transId,
20144 callback : callback,
20150 window[trans.cb] = function(o){
20151 conn.handleResponse(o, trans);
20154 url += String.format("&{0}={1}", this.callbackParam, trans.cb);
20156 if(this.autoAbort !== false){
20160 trans.timeoutId = this.handleFailure.defer(this.timeout, this, [trans]);
20162 var script = document.createElement("script");
20163 script.setAttribute("src", url);
20164 script.setAttribute("type", "text/javascript");
20165 script.setAttribute("id", trans.scriptId);
20166 this.head.appendChild(script);
20168 this.trans = trans;
20170 callback.call(scope||this, null, arg, false);
20175 isLoading : function(){
20176 return this.trans ? true : false;
20180 * Abort the current server request.
20182 abort : function(){
20183 if(this.isLoading()){
20184 this.destroyTrans(this.trans);
20189 destroyTrans : function(trans, isLoaded){
20190 this.head.removeChild(document.getElementById(trans.scriptId));
20191 clearTimeout(trans.timeoutId);
20193 window[trans.cb] = undefined;
20195 delete window[trans.cb];
20198 // if hasn't been loaded, wait for load to remove it to prevent script error
20199 window[trans.cb] = function(){
20200 window[trans.cb] = undefined;
20202 delete window[trans.cb];
20209 handleResponse : function(o, trans){
20210 this.trans = false;
20211 this.destroyTrans(trans, true);
20214 result = trans.reader.readRecords(o);
20216 this.fireEvent("loadexception", this, o, trans.arg, e);
20217 trans.callback.call(trans.scope||window, null, trans.arg, false);
20220 this.fireEvent("load", this, o, trans.arg);
20221 trans.callback.call(trans.scope||window, result, trans.arg, true);
20225 handleFailure : function(trans){
20226 this.trans = false;
20227 this.destroyTrans(trans, false);
20228 this.fireEvent("loadexception", this, null, trans.arg);
20229 trans.callback.call(trans.scope||window, null, trans.arg, false);
20233 * Ext JS Library 1.1.1
20234 * Copyright(c) 2006-2007, Ext JS, LLC.
20236 * Originally Released Under LGPL - original licence link has changed is not relivant.
20239 * <script type="text/javascript">
20243 * @class Roo.data.JsonReader
20244 * @extends Roo.data.DataReader
20245 * Data reader class to create an Array of Roo.data.Record objects from a JSON response
20246 * based on mappings in a provided Roo.data.Record constructor.
20250 var RecordDef = Roo.data.Record.create([
20251 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
20252 {name: 'occupation'} // This field will use "occupation" as the mapping.
20254 var myReader = new Roo.data.JsonReader({
20255 totalProperty: "results", // The property which contains the total dataset size (optional)
20256 root: "rows", // The property which contains an Array of row objects
20257 id: "id" // The property within each row object that provides an ID for the record (optional)
20261 * This would consume a JSON file like this:
20263 { 'results': 2, 'rows': [
20264 { 'id': 1, 'name': 'Bill', occupation: 'Gardener' },
20265 { 'id': 2, 'name': 'Ben', occupation: 'Horticulturalist' } ]
20268 * @cfg {String} totalProperty Name of the property from which to retrieve the total number of records
20269 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
20270 * paged from the remote server.
20271 * @cfg {String} successProperty Name of the property from which to retrieve the success attribute used by forms.
20272 * @cfg {String} root name of the property which contains the Array of row objects.
20273 * @cfg {String} id Name of the property within a row object that contains a record identifier value.
20275 * Create a new JsonReader
20276 * @param {Object} meta Metadata configuration options
20277 * @param {Object} recordType Either an Array of field definition objects,
20278 * or an {@link Roo.data.Record} object created using {@link Roo.data.Record#create}.
20280 Roo.data.JsonReader = function(meta, recordType){
20283 // set some defaults:
20284 Roo.applyIf(meta, {
20285 totalProperty: 'total',
20286 successProperty : 'success',
20291 Roo.data.JsonReader.superclass.constructor.call(this, meta, recordType||meta.fields);
20293 Roo.extend(Roo.data.JsonReader, Roo.data.DataReader, {
20295 * This method is only used by a DataProxy which has retrieved data from a remote server.
20296 * @param {Object} response The XHR object which contains the JSON data in its responseText.
20297 * @return {Object} data A data block which is used by an Roo.data.Store object as
20298 * a cache of Roo.data.Records.
20300 read : function(response){
20301 var json = response.responseText;
20303 var o = eval("("+json+")");
20305 throw {message: "JsonReader.read: Json object not found"};
20310 this.meta = o.metaData;
20311 this.recordType = Roo.data.Record.create(o.metaData.fields);
20312 this.onMetaChange(this.meta, this.recordType, o);
20314 return this.readRecords(o);
20317 // private function a store will implement
20318 onMetaChange : function(meta, recordType, o){
20325 simpleAccess: function(obj, subsc) {
20332 getJsonAccessor: function(){
20334 return function(expr) {
20336 return(re.test(expr))
20337 ? new Function("obj", "return obj." + expr)
20342 return Roo.emptyFn;
20347 * Create a data block containing Roo.data.Records from an XML document.
20348 * @param {Object} o An object which contains an Array of row objects in the property specified
20349 * in the config as 'root, and optionally a property, specified in the config as 'totalProperty'
20350 * which contains the total size of the dataset.
20351 * @return {Object} data A data block which is used by an Roo.data.Store object as
20352 * a cache of Roo.data.Records.
20354 readRecords : function(o){
20356 * After any data loads, the raw JSON data is available for further custom processing.
20360 var s = this.meta, Record = this.recordType,
20361 f = Record.prototype.fields, fi = f.items, fl = f.length;
20363 // Generate extraction functions for the totalProperty, the root, the id, and for each field
20365 if(s.totalProperty) {
20366 this.getTotal = this.getJsonAccessor(s.totalProperty);
20368 if(s.successProperty) {
20369 this.getSuccess = this.getJsonAccessor(s.successProperty);
20371 this.getRoot = s.root ? this.getJsonAccessor(s.root) : function(p){return p;};
20373 var g = this.getJsonAccessor(s.id);
20374 this.getId = function(rec) {
20376 return (r === undefined || r === "") ? null : r;
20379 this.getId = function(){return null;};
20382 for(var i = 0; i < fl; i++){
20384 var map = (f.mapping !== undefined && f.mapping !== null) ? f.mapping : f.name;
20385 this.ef[i] = this.getJsonAccessor(map);
20389 var root = this.getRoot(o), c = root.length, totalRecords = c, success = true;
20390 if(s.totalProperty){
20391 var v = parseInt(this.getTotal(o), 10);
20396 if(s.successProperty){
20397 var v = this.getSuccess(o);
20398 if(v === false || v === 'false'){
20403 for(var i = 0; i < c; i++){
20406 var id = this.getId(n);
20407 for(var j = 0; j < fl; j++){
20409 var v = this.ef[j](n);
20410 values[f.name] = f.convert((v !== undefined) ? v : f.defaultValue);
20412 var record = new Record(values, id);
20414 records[i] = record;
20419 totalRecords : totalRecords
20424 * Ext JS Library 1.1.1
20425 * Copyright(c) 2006-2007, Ext JS, LLC.
20427 * Originally Released Under LGPL - original licence link has changed is not relivant.
20430 * <script type="text/javascript">
20434 * @class Roo.data.XmlReader
20435 * @extends Roo.data.DataReader
20436 * Data reader class to create an Array of {@link Roo.data.Record} objects from an XML document
20437 * based on mappings in a provided Roo.data.Record constructor.<br><br>
20439 * <em>Note that in order for the browser to parse a returned XML document, the Content-Type
20440 * header in the HTTP response must be set to "text/xml".</em>
20444 var RecordDef = Roo.data.Record.create([
20445 {name: 'name', mapping: 'name'}, // "mapping" property not needed if it's the same as "name"
20446 {name: 'occupation'} // This field will use "occupation" as the mapping.
20448 var myReader = new Roo.data.XmlReader({
20449 totalRecords: "results", // The element which contains the total dataset size (optional)
20450 record: "row", // The repeated element which contains row information
20451 id: "id" // The element within the row that provides an ID for the record (optional)
20455 * This would consume an XML file like this:
20459 <results>2</results>
20462 <name>Bill</name>
20463 <occupation>Gardener</occupation>
20467 <name>Ben</name>
20468 <occupation>Horticulturalist</occupation>
20472 * @cfg {String} totalRecords The DomQuery path from which to retrieve the total number of records
20473 * in the dataset. This is only needed if the whole dataset is not passed in one go, but is being
20474 * paged from the remote server.
20475 * @cfg {String} record The DomQuery path to the repeated element which contains record information.
20476 * @cfg {String} success The DomQuery path to the success attribute used by forms.
20477 * @cfg {String} id The DomQuery path relative from the record element to the element that contains
20478 * a record identifier value.
20480 * Create a new XmlReader
20481 * @param {Object} meta Metadata configuration options
20482 * @param {Mixed} recordType The definition of the data record type to produce. This can be either a valid
20483 * Record subclass created with {@link Roo.data.Record#create}, or an array of objects with which to call
20484 * Roo.data.Record.create. See the {@link Roo.data.Record} class for more details.
20486 Roo.data.XmlReader = function(meta, recordType){
20488 Roo.data.XmlReader.superclass.constructor.call(this, meta, recordType||meta.fields);
20490 Roo.extend(Roo.data.XmlReader, Roo.data.DataReader, {
20492 * This method is only used by a DataProxy which has retrieved data from a remote server.
20493 * @param {Object} response The XHR object which contains the parsed XML document. The response is expected
20494 * to contain a method called 'responseXML' that returns an XML document object.
20495 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
20496 * a cache of Roo.data.Records.
20498 read : function(response){
20499 var doc = response.responseXML;
20501 throw {message: "XmlReader.read: XML Document not available"};
20503 return this.readRecords(doc);
20507 * Create a data block containing Roo.data.Records from an XML document.
20508 * @param {Object} doc A parsed XML document.
20509 * @return {Object} records A data block which is used by an {@link Roo.data.Store} as
20510 * a cache of Roo.data.Records.
20512 readRecords : function(doc){
20514 * After any data loads/reads, the raw XML Document is available for further custom processing.
20515 * @type XMLDocument
20517 this.xmlData = doc;
20518 var root = doc.documentElement || doc;
20519 var q = Roo.DomQuery;
20520 var recordType = this.recordType, fields = recordType.prototype.fields;
20521 var sid = this.meta.id;
20522 var totalRecords = 0, success = true;
20523 if(this.meta.totalRecords){
20524 totalRecords = q.selectNumber(this.meta.totalRecords, root, 0);
20527 if(this.meta.success){
20528 var sv = q.selectValue(this.meta.success, root, true);
20529 success = sv !== false && sv !== 'false';
20532 var ns = q.select(this.meta.record, root);
20533 for(var i = 0, len = ns.length; i < len; i++) {
20536 var id = sid ? q.selectValue(sid, n) : undefined;
20537 for(var j = 0, jlen = fields.length; j < jlen; j++){
20538 var f = fields.items[j];
20539 var v = q.selectValue(f.mapping || f.name, n, f.defaultValue);
20541 values[f.name] = v;
20543 var record = new recordType(values, id);
20545 records[records.length] = record;
20551 totalRecords : totalRecords || records.length
20556 * Ext JS Library 1.1.1
20557 * Copyright(c) 2006-2007, Ext JS, LLC.
20559 * Originally Released Under LGPL - original licence link has changed is not relivant.
20562 * <script type="text/javascript">
20566 * @class Roo.data.ArrayReader
20567 * @extends Roo.data.DataReader
20568 * Data reader class to create an Array of Roo.data.Record objects from an Array.
20569 * Each element of that Array represents a row of data fields. The
20570 * fields are pulled into a Record object using as a subscript, the <em>mapping</em> property
20571 * of the field definition if it exists, or the field's ordinal position in the definition.<br>
20575 var RecordDef = Roo.data.Record.create([
20576 {name: 'name', mapping: 1}, // "mapping" only needed if an "id" field is present which
20577 {name: 'occupation', mapping: 2} // precludes using the ordinal position as the index.
20579 var myReader = new Roo.data.ArrayReader({
20580 id: 0 // The subscript within row Array that provides an ID for the Record (optional)
20584 * This would consume an Array like this:
20586 [ [1, 'Bill', 'Gardener'], [2, 'Ben', 'Horticulturalist'] ]
20588 * @cfg {String} id (optional) The subscript within row Array that provides an ID for the Record
20590 * Create a new JsonReader
20591 * @param {Object} meta Metadata configuration options.
20592 * @param {Object} recordType Either an Array of field definition objects
20593 * as specified to {@link Roo.data.Record#create},
20594 * or an {@link Roo.data.Record} object
20595 * created using {@link Roo.data.Record#create}.
20597 Roo.data.ArrayReader = function(meta, recordType){
20598 Roo.data.ArrayReader.superclass.constructor.call(this, meta, recordType);
20601 Roo.extend(Roo.data.ArrayReader, Roo.data.JsonReader, {
20603 * Create a data block containing Roo.data.Records from an XML document.
20604 * @param {Object} o An Array of row objects which represents the dataset.
20605 * @return {Object} data A data block which is used by an Roo.data.Store object as
20606 * a cache of Roo.data.Records.
20608 readRecords : function(o){
20609 var sid = this.meta ? this.meta.id : null;
20610 var recordType = this.recordType, fields = recordType.prototype.fields;
20613 for(var i = 0; i < root.length; i++){
20616 var id = ((sid || sid === 0) && n[sid] !== undefined && n[sid] !== "" ? n[sid] : null);
20617 for(var j = 0, jlen = fields.length; j < jlen; j++){
20618 var f = fields.items[j];
20619 var k = f.mapping !== undefined && f.mapping !== null ? f.mapping : j;
20620 var v = n[k] !== undefined ? n[k] : f.defaultValue;
20622 values[f.name] = v;
20624 var record = new recordType(values, id);
20626 records[records.length] = record;
20630 totalRecords : records.length
20635 * Ext JS Library 1.1.1
20636 * Copyright(c) 2006-2007, Ext JS, LLC.
20638 * Originally Released Under LGPL - original licence link has changed is not relivant.
20641 * <script type="text/javascript">
20646 * @class Roo.data.Tree
20647 * @extends Roo.util.Observable
20648 * Represents a tree data structure and bubbles all the events for its nodes. The nodes
20649 * in the tree have most standard DOM functionality.
20651 * @param {Node} root (optional) The root node
20653 Roo.data.Tree = function(root){
20654 this.nodeHash = {};
20656 * The root node for this tree
20661 this.setRootNode(root);
20666 * Fires when a new child node is appended to a node in this tree.
20667 * @param {Tree} tree The owner tree
20668 * @param {Node} parent The parent node
20669 * @param {Node} node The newly appended node
20670 * @param {Number} index The index of the newly appended node
20675 * Fires when a child node is removed from a node in this tree.
20676 * @param {Tree} tree The owner tree
20677 * @param {Node} parent The parent node
20678 * @param {Node} node The child node removed
20683 * Fires when a node is moved to a new location in the tree
20684 * @param {Tree} tree The owner tree
20685 * @param {Node} node The node moved
20686 * @param {Node} oldParent The old parent of this node
20687 * @param {Node} newParent The new parent of this node
20688 * @param {Number} index The index it was moved to
20693 * Fires when a new child node is inserted in a node in this tree.
20694 * @param {Tree} tree The owner tree
20695 * @param {Node} parent The parent node
20696 * @param {Node} node The child node inserted
20697 * @param {Node} refNode The child node the node was inserted before
20701 * @event beforeappend
20702 * Fires before a new child is appended to a node in this tree, return false to cancel the append.
20703 * @param {Tree} tree The owner tree
20704 * @param {Node} parent The parent node
20705 * @param {Node} node The child node to be appended
20707 "beforeappend" : true,
20709 * @event beforeremove
20710 * Fires before a child is removed from a node in this tree, return false to cancel the remove.
20711 * @param {Tree} tree The owner tree
20712 * @param {Node} parent The parent node
20713 * @param {Node} node The child node to be removed
20715 "beforeremove" : true,
20717 * @event beforemove
20718 * Fires before a node is moved to a new location in the tree. Return false to cancel the move.
20719 * @param {Tree} tree The owner tree
20720 * @param {Node} node The node being moved
20721 * @param {Node} oldParent The parent of the node
20722 * @param {Node} newParent The new parent the node is moving to
20723 * @param {Number} index The index it is being moved to
20725 "beforemove" : true,
20727 * @event beforeinsert
20728 * Fires before a new child is inserted in a node in this tree, return false to cancel the insert.
20729 * @param {Tree} tree The owner tree
20730 * @param {Node} parent The parent node
20731 * @param {Node} node The child node to be inserted
20732 * @param {Node} refNode The child node the node is being inserted before
20734 "beforeinsert" : true
20737 Roo.data.Tree.superclass.constructor.call(this);
20740 Roo.extend(Roo.data.Tree, Roo.util.Observable, {
20741 pathSeparator: "/",
20743 proxyNodeEvent : function(){
20744 return this.fireEvent.apply(this, arguments);
20748 * Returns the root node for this tree.
20751 getRootNode : function(){
20756 * Sets the root node for this tree.
20757 * @param {Node} node
20760 setRootNode : function(node){
20762 node.ownerTree = this;
20763 node.isRoot = true;
20764 this.registerNode(node);
20769 * Gets a node in this tree by its id.
20770 * @param {String} id
20773 getNodeById : function(id){
20774 return this.nodeHash[id];
20777 registerNode : function(node){
20778 this.nodeHash[node.id] = node;
20781 unregisterNode : function(node){
20782 delete this.nodeHash[node.id];
20785 toString : function(){
20786 return "[Tree"+(this.id?" "+this.id:"")+"]";
20791 * @class Roo.data.Node
20792 * @extends Roo.util.Observable
20793 * @cfg {Boolean} leaf true if this node is a leaf and does not have children
20794 * @cfg {String} id The id for this node. If one is not specified, one is generated.
20796 * @param {Object} attributes The attributes/config for the node
20798 Roo.data.Node = function(attributes){
20800 * The attributes supplied for the node. You can use this property to access any custom attributes you supplied.
20803 this.attributes = attributes || {};
20804 this.leaf = this.attributes.leaf;
20806 * The node id. @type String
20808 this.id = this.attributes.id;
20810 this.id = Roo.id(null, "ynode-");
20811 this.attributes.id = this.id;
20814 * All child nodes of this node. @type Array
20816 this.childNodes = [];
20817 if(!this.childNodes.indexOf){ // indexOf is a must
20818 this.childNodes.indexOf = function(o){
20819 for(var i = 0, len = this.length; i < len; i++){
20820 if(this[i] == o) return i;
20826 * The parent node for this node. @type Node
20828 this.parentNode = null;
20830 * The first direct child node of this node, or null if this node has no child nodes. @type Node
20832 this.firstChild = null;
20834 * The last direct child node of this node, or null if this node has no child nodes. @type Node
20836 this.lastChild = null;
20838 * The node immediately preceding this node in the tree, or null if there is no sibling node. @type Node
20840 this.previousSibling = null;
20842 * The node immediately following this node in the tree, or null if there is no sibling node. @type Node
20844 this.nextSibling = null;
20849 * Fires when a new child node is appended
20850 * @param {Tree} tree The owner tree
20851 * @param {Node} this This node
20852 * @param {Node} node The newly appended node
20853 * @param {Number} index The index of the newly appended node
20858 * Fires when a child node is removed
20859 * @param {Tree} tree The owner tree
20860 * @param {Node} this This node
20861 * @param {Node} node The removed node
20866 * Fires when this node is moved to a new location in the tree
20867 * @param {Tree} tree The owner tree
20868 * @param {Node} this This node
20869 * @param {Node} oldParent The old parent of this node
20870 * @param {Node} newParent The new parent of this node
20871 * @param {Number} index The index it was moved to
20876 * Fires when a new child node is inserted.
20877 * @param {Tree} tree The owner tree
20878 * @param {Node} this This node
20879 * @param {Node} node The child node inserted
20880 * @param {Node} refNode The child node the node was inserted before
20884 * @event beforeappend
20885 * Fires before a new child is appended, return false to cancel the append.
20886 * @param {Tree} tree The owner tree
20887 * @param {Node} this This node
20888 * @param {Node} node The child node to be appended
20890 "beforeappend" : true,
20892 * @event beforeremove
20893 * Fires before a child is removed, return false to cancel the remove.
20894 * @param {Tree} tree The owner tree
20895 * @param {Node} this This node
20896 * @param {Node} node The child node to be removed
20898 "beforeremove" : true,
20900 * @event beforemove
20901 * Fires before this node is moved to a new location in the tree. Return false to cancel the move.
20902 * @param {Tree} tree The owner tree
20903 * @param {Node} this This node
20904 * @param {Node} oldParent The parent of this node
20905 * @param {Node} newParent The new parent this node is moving to
20906 * @param {Number} index The index it is being moved to
20908 "beforemove" : true,
20910 * @event beforeinsert
20911 * Fires before a new child is inserted, return false to cancel the insert.
20912 * @param {Tree} tree The owner tree
20913 * @param {Node} this This node
20914 * @param {Node} node The child node to be inserted
20915 * @param {Node} refNode The child node the node is being inserted before
20917 "beforeinsert" : true
20919 this.listeners = this.attributes.listeners;
20920 Roo.data.Node.superclass.constructor.call(this);
20923 Roo.extend(Roo.data.Node, Roo.util.Observable, {
20924 fireEvent : function(evtName){
20925 // first do standard event for this node
20926 if(Roo.data.Node.superclass.fireEvent.apply(this, arguments) === false){
20929 // then bubble it up to the tree if the event wasn't cancelled
20930 var ot = this.getOwnerTree();
20932 if(ot.proxyNodeEvent.apply(ot, arguments) === false){
20940 * Returns true if this node is a leaf
20941 * @return {Boolean}
20943 isLeaf : function(){
20944 return this.leaf === true;
20948 setFirstChild : function(node){
20949 this.firstChild = node;
20953 setLastChild : function(node){
20954 this.lastChild = node;
20959 * Returns true if this node is the last child of its parent
20960 * @return {Boolean}
20962 isLast : function(){
20963 return (!this.parentNode ? true : this.parentNode.lastChild == this);
20967 * Returns true if this node is the first child of its parent
20968 * @return {Boolean}
20970 isFirst : function(){
20971 return (!this.parentNode ? true : this.parentNode.firstChild == this);
20974 hasChildNodes : function(){
20975 return !this.isLeaf() && this.childNodes.length > 0;
20979 * Insert node(s) as the last child node of this node.
20980 * @param {Node/Array} node The node or Array of nodes to append
20981 * @return {Node} The appended node if single append, or null if an array was passed
20983 appendChild : function(node){
20985 if(node instanceof Array){
20987 }else if(arguments.length > 1){
20990 // if passed an array or multiple args do them one by one
20992 for(var i = 0, len = multi.length; i < len; i++) {
20993 this.appendChild(multi[i]);
20996 if(this.fireEvent("beforeappend", this.ownerTree, this, node) === false){
20999 var index = this.childNodes.length;
21000 var oldParent = node.parentNode;
21001 // it's a move, make sure we move it cleanly
21003 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index) === false){
21006 oldParent.removeChild(node);
21008 index = this.childNodes.length;
21010 this.setFirstChild(node);
21012 this.childNodes.push(node);
21013 node.parentNode = this;
21014 var ps = this.childNodes[index-1];
21016 node.previousSibling = ps;
21017 ps.nextSibling = node;
21019 node.previousSibling = null;
21021 node.nextSibling = null;
21022 this.setLastChild(node);
21023 node.setOwnerTree(this.getOwnerTree());
21024 this.fireEvent("append", this.ownerTree, this, node, index);
21026 node.fireEvent("move", this.ownerTree, node, oldParent, this, index);
21033 * Removes a child node from this node.
21034 * @param {Node} node The node to remove
21035 * @return {Node} The removed node
21037 removeChild : function(node){
21038 var index = this.childNodes.indexOf(node);
21042 if(this.fireEvent("beforeremove", this.ownerTree, this, node) === false){
21046 // remove it from childNodes collection
21047 this.childNodes.splice(index, 1);
21050 if(node.previousSibling){
21051 node.previousSibling.nextSibling = node.nextSibling;
21053 if(node.nextSibling){
21054 node.nextSibling.previousSibling = node.previousSibling;
21057 // update child refs
21058 if(this.firstChild == node){
21059 this.setFirstChild(node.nextSibling);
21061 if(this.lastChild == node){
21062 this.setLastChild(node.previousSibling);
21065 node.setOwnerTree(null);
21066 // clear any references from the node
21067 node.parentNode = null;
21068 node.previousSibling = null;
21069 node.nextSibling = null;
21070 this.fireEvent("remove", this.ownerTree, this, node);
21075 * Inserts the first node before the second node in this nodes childNodes collection.
21076 * @param {Node} node The node to insert
21077 * @param {Node} refNode The node to insert before (if null the node is appended)
21078 * @return {Node} The inserted node
21080 insertBefore : function(node, refNode){
21081 if(!refNode){ // like standard Dom, refNode can be null for append
21082 return this.appendChild(node);
21085 if(node == refNode){
21089 if(this.fireEvent("beforeinsert", this.ownerTree, this, node, refNode) === false){
21092 var index = this.childNodes.indexOf(refNode);
21093 var oldParent = node.parentNode;
21094 var refIndex = index;
21096 // when moving internally, indexes will change after remove
21097 if(oldParent == this && this.childNodes.indexOf(node) < index){
21101 // it's a move, make sure we move it cleanly
21103 if(node.fireEvent("beforemove", node.getOwnerTree(), node, oldParent, this, index, refNode) === false){
21106 oldParent.removeChild(node);
21109 this.setFirstChild(node);
21111 this.childNodes.splice(refIndex, 0, node);
21112 node.parentNode = this;
21113 var ps = this.childNodes[refIndex-1];
21115 node.previousSibling = ps;
21116 ps.nextSibling = node;
21118 node.previousSibling = null;
21120 node.nextSibling = refNode;
21121 refNode.previousSibling = node;
21122 node.setOwnerTree(this.getOwnerTree());
21123 this.fireEvent("insert", this.ownerTree, this, node, refNode);
21125 node.fireEvent("move", this.ownerTree, node, oldParent, this, refIndex, refNode);
21131 * Returns the child node at the specified index.
21132 * @param {Number} index
21135 item : function(index){
21136 return this.childNodes[index];
21140 * Replaces one child node in this node with another.
21141 * @param {Node} newChild The replacement node
21142 * @param {Node} oldChild The node to replace
21143 * @return {Node} The replaced node
21145 replaceChild : function(newChild, oldChild){
21146 this.insertBefore(newChild, oldChild);
21147 this.removeChild(oldChild);
21152 * Returns the index of a child node
21153 * @param {Node} node
21154 * @return {Number} The index of the node or -1 if it was not found
21156 indexOf : function(child){
21157 return this.childNodes.indexOf(child);
21161 * Returns the tree this node is in.
21164 getOwnerTree : function(){
21165 // if it doesn't have one, look for one
21166 if(!this.ownerTree){
21170 this.ownerTree = p.ownerTree;
21176 return this.ownerTree;
21180 * Returns depth of this node (the root node has a depth of 0)
21183 getDepth : function(){
21186 while(p.parentNode){
21194 setOwnerTree : function(tree){
21195 // if it's move, we need to update everyone
21196 if(tree != this.ownerTree){
21197 if(this.ownerTree){
21198 this.ownerTree.unregisterNode(this);
21200 this.ownerTree = tree;
21201 var cs = this.childNodes;
21202 for(var i = 0, len = cs.length; i < len; i++) {
21203 cs[i].setOwnerTree(tree);
21206 tree.registerNode(this);
21212 * Returns the path for this node. The path can be used to expand or select this node programmatically.
21213 * @param {String} attr (optional) The attr to use for the path (defaults to the node's id)
21214 * @return {String} The path
21216 getPath : function(attr){
21217 attr = attr || "id";
21218 var p = this.parentNode;
21219 var b = [this.attributes[attr]];
21221 b.unshift(p.attributes[attr]);
21224 var sep = this.getOwnerTree().pathSeparator;
21225 return sep + b.join(sep);
21229 * Bubbles up the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
21230 * function call will be the scope provided or the current node. The arguments to the function
21231 * will be the args provided or the current node. If the function returns false at any point,
21232 * the bubble is stopped.
21233 * @param {Function} fn The function to call
21234 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21235 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21237 bubble : function(fn, scope, args){
21240 if(fn.call(scope || p, args || p) === false){
21248 * Cascades down the tree from this node, calling the specified function with each node. The scope (<i>this</i>) of
21249 * function call will be the scope provided or the current node. The arguments to the function
21250 * will be the args provided or the current node. If the function returns false at any point,
21251 * the cascade is stopped on that branch.
21252 * @param {Function} fn The function to call
21253 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21254 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21256 cascade : function(fn, scope, args){
21257 if(fn.call(scope || this, args || this) !== false){
21258 var cs = this.childNodes;
21259 for(var i = 0, len = cs.length; i < len; i++) {
21260 cs[i].cascade(fn, scope, args);
21266 * Interates the child nodes of this node, calling the specified function with each node. The scope (<i>this</i>) of
21267 * function call will be the scope provided or the current node. The arguments to the function
21268 * will be the args provided or the current node. If the function returns false at any point,
21269 * the iteration stops.
21270 * @param {Function} fn The function to call
21271 * @param {Object} scope (optional) The scope of the function (defaults to current node)
21272 * @param {Array} args (optional) The args to call the function with (default to passing the current node)
21274 eachChild : function(fn, scope, args){
21275 var cs = this.childNodes;
21276 for(var i = 0, len = cs.length; i < len; i++) {
21277 if(fn.call(scope || this, args || cs[i]) === false){
21284 * Finds the first child that has the attribute with the specified value.
21285 * @param {String} attribute The attribute name
21286 * @param {Mixed} value The value to search for
21287 * @return {Node} The found child or null if none was found
21289 findChild : function(attribute, value){
21290 var cs = this.childNodes;
21291 for(var i = 0, len = cs.length; i < len; i++) {
21292 if(cs[i].attributes[attribute] == value){
21300 * Finds the first child by a custom function. The child matches if the function passed
21302 * @param {Function} fn
21303 * @param {Object} scope (optional)
21304 * @return {Node} The found child or null if none was found
21306 findChildBy : function(fn, scope){
21307 var cs = this.childNodes;
21308 for(var i = 0, len = cs.length; i < len; i++) {
21309 if(fn.call(scope||cs[i], cs[i]) === true){
21317 * Sorts this nodes children using the supplied sort function
21318 * @param {Function} fn
21319 * @param {Object} scope (optional)
21321 sort : function(fn, scope){
21322 var cs = this.childNodes;
21323 var len = cs.length;
21325 var sortFn = scope ? function(){fn.apply(scope, arguments);} : fn;
21327 for(var i = 0; i < len; i++){
21329 n.previousSibling = cs[i-1];
21330 n.nextSibling = cs[i+1];
21332 this.setFirstChild(n);
21335 this.setLastChild(n);
21342 * Returns true if this node is an ancestor (at any point) of the passed node.
21343 * @param {Node} node
21344 * @return {Boolean}
21346 contains : function(node){
21347 return node.isAncestor(this);
21351 * Returns true if the passed node is an ancestor (at any point) of this node.
21352 * @param {Node} node
21353 * @return {Boolean}
21355 isAncestor : function(node){
21356 var p = this.parentNode;
21366 toString : function(){
21367 return "[Node"+(this.id?" "+this.id:"")+"]";
21371 * Ext JS Library 1.1.1
21372 * Copyright(c) 2006-2007, Ext JS, LLC.
21374 * Originally Released Under LGPL - original licence link has changed is not relivant.
21377 * <script type="text/javascript">
21382 * @class Roo.ComponentMgr
21383 * Provides a common registry of all components on a page so that they can be easily accessed by component id (see {@link Roo.getCmp}).
21386 Roo.ComponentMgr = function(){
21387 var all = new Roo.util.MixedCollection();
21391 * Registers a component.
21392 * @param {Roo.Component} c The component
21394 register : function(c){
21399 * Unregisters a component.
21400 * @param {Roo.Component} c The component
21402 unregister : function(c){
21407 * Returns a component by id
21408 * @param {String} id The component id
21410 get : function(id){
21411 return all.get(id);
21415 * Registers a function that will be called when a specified component is added to ComponentMgr
21416 * @param {String} id The component id
21417 * @param {Funtction} fn The callback function
21418 * @param {Object} scope The scope of the callback
21420 onAvailable : function(id, fn, scope){
21421 all.on("add", function(index, o){
21423 fn.call(scope || o, o);
21424 all.un("add", fn, scope);
21431 * Ext JS Library 1.1.1
21432 * Copyright(c) 2006-2007, Ext JS, LLC.
21434 * Originally Released Under LGPL - original licence link has changed is not relivant.
21437 * <script type="text/javascript">
21441 * @class Roo.Component
21442 * @extends Roo.util.Observable
21443 * Base class for all major Roo components. All subclasses of Component can automatically participate in the standard
21444 * Roo component lifecycle of creation, rendering and destruction. They also have automatic support for basic hide/show
21445 * and enable/disable behavior. Component allows any subclass to be lazy-rendered into any {@link Roo.Container} and
21446 * to be automatically registered with the {@link Roo.ComponentMgr} so that it can be referenced at any time via {@link Roo.getCmp}.
21447 * All visual components (widgets) that require rendering into a layout should subclass Component.
21449 * @param {Roo.Element/String/Object} config The configuration options. If an element is passed, it is set as the internal
21450 * element and its id used as the component id. If a string is passed, it is assumed to be the id of an existing element
21451 * and is used as the component id. Otherwise, it is assumed to be a standard config object and is applied to the component.
21453 Roo.Component = function(config){
21454 config = config || {};
21455 if(config.tagName || config.dom || typeof config == "string"){ // element object
21456 config = {el: config, id: config.id || config};
21458 this.initialConfig = config;
21460 Roo.apply(this, config);
21464 * Fires after the component is disabled.
21465 * @param {Roo.Component} this
21470 * Fires after the component is enabled.
21471 * @param {Roo.Component} this
21475 * @event beforeshow
21476 * Fires before the component is shown. Return false to stop the show.
21477 * @param {Roo.Component} this
21482 * Fires after the component is shown.
21483 * @param {Roo.Component} this
21487 * @event beforehide
21488 * Fires before the component is hidden. Return false to stop the hide.
21489 * @param {Roo.Component} this
21494 * Fires after the component is hidden.
21495 * @param {Roo.Component} this
21499 * @event beforerender
21500 * Fires before the component is rendered. Return false to stop the render.
21501 * @param {Roo.Component} this
21503 beforerender : true,
21506 * Fires after the component is rendered.
21507 * @param {Roo.Component} this
21511 * @event beforedestroy
21512 * Fires before the component is destroyed. Return false to stop the destroy.
21513 * @param {Roo.Component} this
21515 beforedestroy : true,
21518 * Fires after the component is destroyed.
21519 * @param {Roo.Component} this
21524 this.id = "ext-comp-" + (++Roo.Component.AUTO_ID);
21526 Roo.ComponentMgr.register(this);
21527 Roo.Component.superclass.constructor.call(this);
21528 this.initComponent();
21529 if(this.renderTo){ // not supported by all components yet. use at your own risk!
21530 this.render(this.renderTo);
21531 delete this.renderTo;
21536 Roo.Component.AUTO_ID = 1000;
21538 Roo.extend(Roo.Component, Roo.util.Observable, {
21540 * @property {Boolean} hidden
21541 * true if this component is hidden. Read-only.
21545 * true if this component is disabled. Read-only.
21549 * true if this component has been rendered. Read-only.
21553 /** @cfg {String} disableClass
21554 * CSS class added to the component when it is disabled (defaults to "x-item-disabled").
21556 disabledClass : "x-item-disabled",
21557 /** @cfg {Boolean} allowDomMove
21558 * Whether the component can move the Dom node when rendering (defaults to true).
21560 allowDomMove : true,
21561 /** @cfg {String} hideMode
21562 * How this component should hidden. Supported values are
21563 * "visibility" (css visibility), "offsets" (negative offset position) and
21564 * "display" (css display) - defaults to "display".
21566 hideMode: 'display',
21569 ctype : "Roo.Component",
21571 /** @cfg {String} actionMode
21572 * which property holds the element that used for hide() / show() / disable() / enable()
21578 getActionEl : function(){
21579 return this[this.actionMode];
21582 initComponent : Roo.emptyFn,
21584 * If this is a lazy rendering component, render it to its container element.
21585 * @param {String/HTMLElement/Element} container (optional) The element this component should be rendered into. If it is being applied to existing markup, this should be left off.
21587 render : function(container, position){
21588 if(!this.rendered && this.fireEvent("beforerender", this) !== false){
21589 if(!container && this.el){
21590 this.el = Roo.get(this.el);
21591 container = this.el.dom.parentNode;
21592 this.allowDomMove = false;
21594 this.container = Roo.get(container);
21595 this.rendered = true;
21596 if(position !== undefined){
21597 if(typeof position == 'number'){
21598 position = this.container.dom.childNodes[position];
21600 position = Roo.getDom(position);
21603 this.onRender(this.container, position || null);
21605 this.el.addClass(this.cls);
21609 this.el.applyStyles(this.style);
21612 this.fireEvent("render", this);
21613 this.afterRender(this.container);
21625 // default function is not really useful
21626 onRender : function(ct, position){
21628 this.el = Roo.get(this.el);
21629 if(this.allowDomMove !== false){
21630 ct.dom.insertBefore(this.el.dom, position);
21636 getAutoCreate : function(){
21637 var cfg = typeof this.autoCreate == "object" ?
21638 this.autoCreate : Roo.apply({}, this.defaultAutoCreate);
21639 if(this.id && !cfg.id){
21646 afterRender : Roo.emptyFn,
21649 * Destroys this component by purging any event listeners, removing the component's element from the DOM,
21650 * removing the component from its {@link Roo.Container} (if applicable) and unregistering it from {@link Roo.ComponentMgr}.
21652 destroy : function(){
21653 if(this.fireEvent("beforedestroy", this) !== false){
21654 this.purgeListeners();
21655 this.beforeDestroy();
21657 this.el.removeAllListeners();
21659 if(this.actionMode == "container"){
21660 this.container.remove();
21664 Roo.ComponentMgr.unregister(this);
21665 this.fireEvent("destroy", this);
21670 beforeDestroy : function(){
21675 onDestroy : function(){
21680 * Returns the underlying {@link Roo.Element}.
21681 * @return {Roo.Element} The element
21683 getEl : function(){
21688 * Returns the id of this component.
21691 getId : function(){
21696 * Try to focus this component.
21697 * @param {Boolean} selectText True to also select the text in this component (if applicable)
21698 * @return {Roo.Component} this
21700 focus : function(selectText){
21703 if(selectText === true){
21704 this.el.dom.select();
21719 * Disable this component.
21720 * @return {Roo.Component} this
21722 disable : function(){
21726 this.disabled = true;
21727 this.fireEvent("disable", this);
21732 onDisable : function(){
21733 this.getActionEl().addClass(this.disabledClass);
21734 this.el.dom.disabled = true;
21738 * Enable this component.
21739 * @return {Roo.Component} this
21741 enable : function(){
21745 this.disabled = false;
21746 this.fireEvent("enable", this);
21751 onEnable : function(){
21752 this.getActionEl().removeClass(this.disabledClass);
21753 this.el.dom.disabled = false;
21757 * Convenience function for setting disabled/enabled by boolean.
21758 * @param {Boolean} disabled
21760 setDisabled : function(disabled){
21761 this[disabled ? "disable" : "enable"]();
21765 * Show this component.
21766 * @return {Roo.Component} this
21769 if(this.fireEvent("beforeshow", this) !== false){
21770 this.hidden = false;
21774 this.fireEvent("show", this);
21780 onShow : function(){
21781 var ae = this.getActionEl();
21782 if(this.hideMode == 'visibility'){
21783 ae.dom.style.visibility = "visible";
21784 }else if(this.hideMode == 'offsets'){
21785 ae.removeClass('x-hidden');
21787 ae.dom.style.display = "";
21792 * Hide this component.
21793 * @return {Roo.Component} this
21796 if(this.fireEvent("beforehide", this) !== false){
21797 this.hidden = true;
21801 this.fireEvent("hide", this);
21807 onHide : function(){
21808 var ae = this.getActionEl();
21809 if(this.hideMode == 'visibility'){
21810 ae.dom.style.visibility = "hidden";
21811 }else if(this.hideMode == 'offsets'){
21812 ae.addClass('x-hidden');
21814 ae.dom.style.display = "none";
21819 * Convenience function to hide or show this component by boolean.
21820 * @param {Boolean} visible True to show, false to hide
21821 * @return {Roo.Component} this
21823 setVisible: function(visible){
21833 * Returns true if this component is visible.
21835 isVisible : function(){
21836 return this.getActionEl().isVisible();
21839 cloneConfig : function(overrides){
21840 overrides = overrides || {};
21841 var id = overrides.id || Roo.id();
21842 var cfg = Roo.applyIf(overrides, this.initialConfig);
21843 cfg.id = id; // prevent dup id
21844 return new this.constructor(cfg);
21848 * Ext JS Library 1.1.1
21849 * Copyright(c) 2006-2007, Ext JS, LLC.
21851 * Originally Released Under LGPL - original licence link has changed is not relivant.
21854 * <script type="text/javascript">
21859 * @extends Roo.Element
21860 * An extended {@link Roo.Element} object that supports a shadow and shim, constrain to viewport and
21861 * automatic maintaining of shadow/shim positions.
21862 * @cfg {Boolean} shim False to disable the iframe shim in browsers which need one (defaults to true)
21863 * @cfg {String/Boolean} shadow True to create a shadow element with default class "x-layer-shadow", or
21864 * you can pass a string with a CSS class name. False turns off the shadow.
21865 * @cfg {Object} dh DomHelper object config to create element with (defaults to {tag: "div", cls: "x-layer"}).
21866 * @cfg {Boolean} constrain False to disable constrain to viewport (defaults to true)
21867 * @cfg {String} cls CSS class to add to the element
21868 * @cfg {Number} zindex Starting z-index (defaults to 11000)
21869 * @cfg {Number} shadowOffset Number of pixels to offset the shadow (defaults to 3)
21871 * @param {Object} config An object with config options.
21872 * @param {String/HTMLElement} existingEl (optional) Uses an existing DOM element. If the element is not found it creates it.
21875 Roo.Layer = function(config, existingEl){
21876 config = config || {};
21877 var dh = Roo.DomHelper;
21878 var cp = config.parentEl, pel = cp ? Roo.getDom(cp) : document.body;
21880 this.dom = Roo.getDom(existingEl);
21883 var o = config.dh || {tag: "div", cls: "x-layer"};
21884 this.dom = dh.append(pel, o);
21887 this.addClass(config.cls);
21889 this.constrain = config.constrain !== false;
21890 this.visibilityMode = Roo.Element.VISIBILITY;
21892 this.id = this.dom.id = config.id;
21894 this.id = Roo.id(this.dom);
21896 this.zindex = config.zindex || this.getZIndex();
21897 this.position("absolute", this.zindex);
21899 this.shadowOffset = config.shadowOffset || 4;
21900 this.shadow = new Roo.Shadow({
21901 offset : this.shadowOffset,
21902 mode : config.shadow
21905 this.shadowOffset = 0;
21907 this.useShim = config.shim !== false && Roo.useShims;
21908 this.useDisplay = config.useDisplay;
21912 var supr = Roo.Element.prototype;
21914 // shims are shared among layer to keep from having 100 iframes
21917 Roo.extend(Roo.Layer, Roo.Element, {
21919 getZIndex : function(){
21920 return this.zindex || parseInt(this.getStyle("z-index"), 10) || 11000;
21923 getShim : function(){
21930 var shim = shims.shift();
21932 shim = this.createShim();
21933 shim.enableDisplayMode('block');
21934 shim.dom.style.display = 'none';
21935 shim.dom.style.visibility = 'visible';
21937 var pn = this.dom.parentNode;
21938 if(shim.dom.parentNode != pn){
21939 pn.insertBefore(shim.dom, this.dom);
21941 shim.setStyle('z-index', this.getZIndex()-2);
21946 hideShim : function(){
21948 this.shim.setDisplayed(false);
21949 shims.push(this.shim);
21954 disableShadow : function(){
21956 this.shadowDisabled = true;
21957 this.shadow.hide();
21958 this.lastShadowOffset = this.shadowOffset;
21959 this.shadowOffset = 0;
21963 enableShadow : function(show){
21965 this.shadowDisabled = false;
21966 this.shadowOffset = this.lastShadowOffset;
21967 delete this.lastShadowOffset;
21975 // this code can execute repeatedly in milliseconds (i.e. during a drag) so
21976 // code size was sacrificed for effeciency (e.g. no getBox/setBox, no XY calls)
21977 sync : function(doShow){
21978 var sw = this.shadow;
21979 if(!this.updating && this.isVisible() && (sw || this.useShim)){
21980 var sh = this.getShim();
21982 var w = this.getWidth(),
21983 h = this.getHeight();
21985 var l = this.getLeft(true),
21986 t = this.getTop(true);
21988 if(sw && !this.shadowDisabled){
21989 if(doShow && !sw.isVisible()){
21992 sw.realign(l, t, w, h);
21998 // fit the shim behind the shadow, so it is shimmed too
21999 var a = sw.adjusts, s = sh.dom.style;
22000 s.left = (Math.min(l, l+a.l))+"px";
22001 s.top = (Math.min(t, t+a.t))+"px";
22002 s.width = (w+a.w)+"px";
22003 s.height = (h+a.h)+"px";
22010 sh.setLeftTop(l, t);
22017 destroy : function(){
22020 this.shadow.hide();
22022 this.removeAllListeners();
22023 var pn = this.dom.parentNode;
22025 pn.removeChild(this.dom);
22027 Roo.Element.uncache(this.id);
22030 remove : function(){
22035 beginUpdate : function(){
22036 this.updating = true;
22040 endUpdate : function(){
22041 this.updating = false;
22046 hideUnders : function(negOffset){
22048 this.shadow.hide();
22054 constrainXY : function(){
22055 if(this.constrain){
22056 var vw = Roo.lib.Dom.getViewWidth(),
22057 vh = Roo.lib.Dom.getViewHeight();
22058 var s = Roo.get(document).getScroll();
22060 var xy = this.getXY();
22061 var x = xy[0], y = xy[1];
22062 var w = this.dom.offsetWidth+this.shadowOffset, h = this.dom.offsetHeight+this.shadowOffset;
22063 // only move it if it needs it
22065 // first validate right/bottom
22066 if((x + w) > vw+s.left){
22067 x = vw - w - this.shadowOffset;
22070 if((y + h) > vh+s.top){
22071 y = vh - h - this.shadowOffset;
22074 // then make sure top/left isn't negative
22085 var ay = this.avoidY;
22086 if(y <= ay && (y+h) >= ay){
22092 supr.setXY.call(this, xy);
22098 isVisible : function(){
22099 return this.visible;
22103 showAction : function(){
22104 this.visible = true; // track visibility to prevent getStyle calls
22105 if(this.useDisplay === true){
22106 this.setDisplayed("");
22107 }else if(this.lastXY){
22108 supr.setXY.call(this, this.lastXY);
22109 }else if(this.lastLT){
22110 supr.setLeftTop.call(this, this.lastLT[0], this.lastLT[1]);
22115 hideAction : function(){
22116 this.visible = false;
22117 if(this.useDisplay === true){
22118 this.setDisplayed(false);
22120 this.setLeftTop(-10000,-10000);
22124 // overridden Element method
22125 setVisible : function(v, a, d, c, e){
22130 var cb = function(){
22135 }.createDelegate(this);
22136 supr.setVisible.call(this, true, true, d, cb, e);
22139 this.hideUnders(true);
22148 }.createDelegate(this);
22150 supr.setVisible.call(this, v, a, d, cb, e);
22159 storeXY : function(xy){
22160 delete this.lastLT;
22164 storeLeftTop : function(left, top){
22165 delete this.lastXY;
22166 this.lastLT = [left, top];
22170 beforeFx : function(){
22171 this.beforeAction();
22172 return Roo.Layer.superclass.beforeFx.apply(this, arguments);
22176 afterFx : function(){
22177 Roo.Layer.superclass.afterFx.apply(this, arguments);
22178 this.sync(this.isVisible());
22182 beforeAction : function(){
22183 if(!this.updating && this.shadow){
22184 this.shadow.hide();
22188 // overridden Element method
22189 setLeft : function(left){
22190 this.storeLeftTop(left, this.getTop(true));
22191 supr.setLeft.apply(this, arguments);
22195 setTop : function(top){
22196 this.storeLeftTop(this.getLeft(true), top);
22197 supr.setTop.apply(this, arguments);
22201 setLeftTop : function(left, top){
22202 this.storeLeftTop(left, top);
22203 supr.setLeftTop.apply(this, arguments);
22207 setXY : function(xy, a, d, c, e){
22209 this.beforeAction();
22211 var cb = this.createCB(c);
22212 supr.setXY.call(this, xy, a, d, cb, e);
22219 createCB : function(c){
22230 // overridden Element method
22231 setX : function(x, a, d, c, e){
22232 this.setXY([x, this.getY()], a, d, c, e);
22235 // overridden Element method
22236 setY : function(y, a, d, c, e){
22237 this.setXY([this.getX(), y], a, d, c, e);
22240 // overridden Element method
22241 setSize : function(w, h, a, d, c, e){
22242 this.beforeAction();
22243 var cb = this.createCB(c);
22244 supr.setSize.call(this, w, h, a, d, cb, e);
22250 // overridden Element method
22251 setWidth : function(w, a, d, c, e){
22252 this.beforeAction();
22253 var cb = this.createCB(c);
22254 supr.setWidth.call(this, w, a, d, cb, e);
22260 // overridden Element method
22261 setHeight : function(h, a, d, c, e){
22262 this.beforeAction();
22263 var cb = this.createCB(c);
22264 supr.setHeight.call(this, h, a, d, cb, e);
22270 // overridden Element method
22271 setBounds : function(x, y, w, h, a, d, c, e){
22272 this.beforeAction();
22273 var cb = this.createCB(c);
22275 this.storeXY([x, y]);
22276 supr.setXY.call(this, [x, y]);
22277 supr.setSize.call(this, w, h, a, d, cb, e);
22280 supr.setBounds.call(this, x, y, w, h, a, d, cb, e);
22286 * Sets the z-index of this layer and adjusts any shadow and shim z-indexes. The layer z-index is automatically
22287 * incremented by two more than the value passed in so that it always shows above any shadow or shim (the shadow
22288 * element, if any, will be assigned z-index + 1, and the shim element, if any, will be assigned the unmodified z-index).
22289 * @param {Number} zindex The new z-index to set
22290 * @return {this} The Layer
22292 setZIndex : function(zindex){
22293 this.zindex = zindex;
22294 this.setStyle("z-index", zindex + 2);
22296 this.shadow.setZIndex(zindex + 1);
22299 this.shim.setStyle("z-index", zindex);
22305 * Ext JS Library 1.1.1
22306 * Copyright(c) 2006-2007, Ext JS, LLC.
22308 * Originally Released Under LGPL - original licence link has changed is not relivant.
22311 * <script type="text/javascript">
22316 * @class Roo.Shadow
22317 * Simple class that can provide a shadow effect for any element. Note that the element MUST be absolutely positioned,
22318 * and the shadow does not provide any shimming. This should be used only in simple cases -- for more advanced
22319 * functionality that can also provide the same shadow effect, see the {@link Roo.Layer} class.
22321 * Create a new Shadow
22322 * @param {Object} config The config object
22324 Roo.Shadow = function(config){
22325 Roo.apply(this, config);
22326 if(typeof this.mode != "string"){
22327 this.mode = this.defaultMode;
22329 var o = this.offset, a = {h: 0};
22330 var rad = Math.floor(this.offset/2);
22331 switch(this.mode.toLowerCase()){ // all this hideous nonsense calculates the various offsets for shadows
22337 a.l -= this.offset + rad;
22338 a.t -= this.offset + rad;
22349 a.l -= (this.offset - rad);
22350 a.t -= this.offset + rad;
22352 a.w -= (this.offset - rad)*2;
22363 a.l -= (this.offset - rad);
22364 a.t -= (this.offset - rad);
22366 a.w -= (this.offset + rad + 1);
22367 a.h -= (this.offset + rad);
22376 Roo.Shadow.prototype = {
22378 * @cfg {String} mode
22379 * The shadow display mode. Supports the following options:<br />
22380 * sides: Shadow displays on both sides and bottom only<br />
22381 * frame: Shadow displays equally on all four sides<br />
22382 * drop: Traditional bottom-right drop shadow (default)
22385 * @cfg {String} offset
22386 * The number of pixels to offset the shadow from the element (defaults to 4)
22391 defaultMode: "drop",
22394 * Displays the shadow under the target element
22395 * @param {String/HTMLElement/Element} targetEl The id or element under which the shadow should display
22397 show : function(target){
22398 target = Roo.get(target);
22400 this.el = Roo.Shadow.Pool.pull();
22401 if(this.el.dom.nextSibling != target.dom){
22402 this.el.insertBefore(target);
22405 this.el.setStyle("z-index", this.zIndex || parseInt(target.getStyle("z-index"), 10)-1);
22407 this.el.dom.style.filter="progid:DXImageTransform.Microsoft.alpha(opacity=50) progid:DXImageTransform.Microsoft.Blur(pixelradius="+(this.offset)+")";
22410 target.getLeft(true),
22411 target.getTop(true),
22415 this.el.dom.style.display = "block";
22419 * Returns true if the shadow is visible, else false
22421 isVisible : function(){
22422 return this.el ? true : false;
22426 * Direct alignment when values are already available. Show must be called at least once before
22427 * calling this method to ensure it is initialized.
22428 * @param {Number} left The target element left position
22429 * @param {Number} top The target element top position
22430 * @param {Number} width The target element width
22431 * @param {Number} height The target element height
22433 realign : function(l, t, w, h){
22437 var a = this.adjusts, d = this.el.dom, s = d.style;
22439 s.left = (l+a.l)+"px";
22440 s.top = (t+a.t)+"px";
22441 var sw = (w+a.w), sh = (h+a.h), sws = sw +"px", shs = sh + "px";
22442 if(s.width != sws || s.height != shs){
22446 var cn = d.childNodes;
22447 var sww = Math.max(0, (sw-12))+"px";
22448 cn[0].childNodes[1].style.width = sww;
22449 cn[1].childNodes[1].style.width = sww;
22450 cn[2].childNodes[1].style.width = sww;
22451 cn[1].style.height = Math.max(0, (sh-12))+"px";
22457 * Hides this shadow
22461 this.el.dom.style.display = "none";
22462 Roo.Shadow.Pool.push(this.el);
22468 * Adjust the z-index of this shadow
22469 * @param {Number} zindex The new z-index
22471 setZIndex : function(z){
22474 this.el.setStyle("z-index", z);
22479 // Private utility class that manages the internal Shadow cache
22480 Roo.Shadow.Pool = function(){
22482 var markup = Roo.isIE ?
22483 '<div class="x-ie-shadow"></div>' :
22484 '<div class="x-shadow"><div class="xst"><div class="xstl"></div><div class="xstc"></div><div class="xstr"></div></div><div class="xsc"><div class="xsml"></div><div class="xsmc"></div><div class="xsmr"></div></div><div class="xsb"><div class="xsbl"></div><div class="xsbc"></div><div class="xsbr"></div></div></div>';
22487 var sh = p.shift();
22489 sh = Roo.get(Roo.DomHelper.insertHtml("beforeBegin", document.body.firstChild, markup));
22490 sh.autoBoxAdjust = false;
22495 push : function(sh){
22501 * Ext JS Library 1.1.1
22502 * Copyright(c) 2006-2007, Ext JS, LLC.
22504 * Originally Released Under LGPL - original licence link has changed is not relivant.
22507 * <script type="text/javascript">
22511 * @class Roo.BoxComponent
22512 * @extends Roo.Component
22513 * Base class for any visual {@link Roo.Component} that uses a box container. BoxComponent provides automatic box
22514 * model adjustments for sizing and positioning and will work correctly withnin the Component rendering model. All
22515 * container classes should subclass BoxComponent so that they will work consistently when nested within other Ext
22516 * layout containers.
22518 * @param {Roo.Element/String/Object} config The configuration options.
22520 Roo.BoxComponent = function(config){
22521 Roo.Component.call(this, config);
22525 * Fires after the component is resized.
22526 * @param {Roo.Component} this
22527 * @param {Number} adjWidth The box-adjusted width that was set
22528 * @param {Number} adjHeight The box-adjusted height that was set
22529 * @param {Number} rawWidth The width that was originally specified
22530 * @param {Number} rawHeight The height that was originally specified
22535 * Fires after the component is moved.
22536 * @param {Roo.Component} this
22537 * @param {Number} x The new x position
22538 * @param {Number} y The new y position
22544 Roo.extend(Roo.BoxComponent, Roo.Component, {
22545 // private, set in afterRender to signify that the component has been rendered
22547 // private, used to defer height settings to subclasses
22548 deferHeight: false,
22549 /** @cfg {Number} width
22550 * width (optional) size of component
22552 /** @cfg {Number} height
22553 * height (optional) size of component
22557 * Sets the width and height of the component. This method fires the resize event. This method can accept
22558 * either width and height as separate numeric arguments, or you can pass a size object like {width:10, height:20}.
22559 * @param {Number/Object} width The new width to set, or a size object in the format {width, height}
22560 * @param {Number} height The new height to set (not required if a size object is passed as the first arg)
22561 * @return {Roo.BoxComponent} this
22563 setSize : function(w, h){
22564 // support for standard size objects
22565 if(typeof w == 'object'){
22570 if(!this.boxReady){
22576 // prevent recalcs when not needed
22577 if(this.lastSize && this.lastSize.width == w && this.lastSize.height == h){
22580 this.lastSize = {width: w, height: h};
22582 var adj = this.adjustSize(w, h);
22583 var aw = adj.width, ah = adj.height;
22584 if(aw !== undefined || ah !== undefined){ // this code is nasty but performs better with floaters
22585 var rz = this.getResizeEl();
22586 if(!this.deferHeight && aw !== undefined && ah !== undefined){
22587 rz.setSize(aw, ah);
22588 }else if(!this.deferHeight && ah !== undefined){
22590 }else if(aw !== undefined){
22593 this.onResize(aw, ah, w, h);
22594 this.fireEvent('resize', this, aw, ah, w, h);
22600 * Gets the current size of the component's underlying element.
22601 * @return {Object} An object containing the element's size {width: (element width), height: (element height)}
22603 getSize : function(){
22604 return this.el.getSize();
22608 * Gets the current XY position of the component's underlying element.
22609 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
22610 * @return {Array} The XY position of the element (e.g., [100, 200])
22612 getPosition : function(local){
22613 if(local === true){
22614 return [this.el.getLeft(true), this.el.getTop(true)];
22616 return this.xy || this.el.getXY();
22620 * Gets the current box measurements of the component's underlying element.
22621 * @param {Boolean} local (optional) If true the element's left and top are returned instead of page XY (defaults to false)
22622 * @returns {Object} box An object in the format {x, y, width, height}
22624 getBox : function(local){
22625 var s = this.el.getSize();
22627 s.x = this.el.getLeft(true);
22628 s.y = this.el.getTop(true);
22630 var xy = this.xy || this.el.getXY();
22638 * Sets the current box measurements of the component's underlying element.
22639 * @param {Object} box An object in the format {x, y, width, height}
22640 * @returns {Roo.BoxComponent} this
22642 updateBox : function(box){
22643 this.setSize(box.width, box.height);
22644 this.setPagePosition(box.x, box.y);
22649 getResizeEl : function(){
22650 return this.resizeEl || this.el;
22654 getPositionEl : function(){
22655 return this.positionEl || this.el;
22659 * Sets the left and top of the component. To set the page XY position instead, use {@link #setPagePosition}.
22660 * This method fires the move event.
22661 * @param {Number} left The new left
22662 * @param {Number} top The new top
22663 * @returns {Roo.BoxComponent} this
22665 setPosition : function(x, y){
22668 if(!this.boxReady){
22671 var adj = this.adjustPosition(x, y);
22672 var ax = adj.x, ay = adj.y;
22674 var el = this.getPositionEl();
22675 if(ax !== undefined || ay !== undefined){
22676 if(ax !== undefined && ay !== undefined){
22677 el.setLeftTop(ax, ay);
22678 }else if(ax !== undefined){
22680 }else if(ay !== undefined){
22683 this.onPosition(ax, ay);
22684 this.fireEvent('move', this, ax, ay);
22690 * Sets the page XY position of the component. To set the left and top instead, use {@link #setPosition}.
22691 * This method fires the move event.
22692 * @param {Number} x The new x position
22693 * @param {Number} y The new y position
22694 * @returns {Roo.BoxComponent} this
22696 setPagePosition : function(x, y){
22699 if(!this.boxReady){
22702 if(x === undefined || y === undefined){ // cannot translate undefined points
22705 var p = this.el.translatePoints(x, y);
22706 this.setPosition(p.left, p.top);
22711 onRender : function(ct, position){
22712 Roo.BoxComponent.superclass.onRender.call(this, ct, position);
22714 this.resizeEl = Roo.get(this.resizeEl);
22716 if(this.positionEl){
22717 this.positionEl = Roo.get(this.positionEl);
22722 afterRender : function(){
22723 Roo.BoxComponent.superclass.afterRender.call(this);
22724 this.boxReady = true;
22725 this.setSize(this.width, this.height);
22726 if(this.x || this.y){
22727 this.setPosition(this.x, this.y);
22729 if(this.pageX || this.pageY){
22730 this.setPagePosition(this.pageX, this.pageY);
22735 * Force the component's size to recalculate based on the underlying element's current height and width.
22736 * @returns {Roo.BoxComponent} this
22738 syncSize : function(){
22739 delete this.lastSize;
22740 this.setSize(this.el.getWidth(), this.el.getHeight());
22745 * Called after the component is resized, this method is empty by default but can be implemented by any
22746 * subclass that needs to perform custom logic after a resize occurs.
22747 * @param {Number} adjWidth The box-adjusted width that was set
22748 * @param {Number} adjHeight The box-adjusted height that was set
22749 * @param {Number} rawWidth The width that was originally specified
22750 * @param {Number} rawHeight The height that was originally specified
22752 onResize : function(adjWidth, adjHeight, rawWidth, rawHeight){
22757 * Called after the component is moved, this method is empty by default but can be implemented by any
22758 * subclass that needs to perform custom logic after a move occurs.
22759 * @param {Number} x The new x position
22760 * @param {Number} y The new y position
22762 onPosition : function(x, y){
22767 adjustSize : function(w, h){
22768 if(this.autoWidth){
22771 if(this.autoHeight){
22774 return {width : w, height: h};
22778 adjustPosition : function(x, y){
22779 return {x : x, y: y};
22783 * Ext JS Library 1.1.1
22784 * Copyright(c) 2006-2007, Ext JS, LLC.
22786 * Originally Released Under LGPL - original licence link has changed is not relivant.
22789 * <script type="text/javascript">
22794 * @class Roo.SplitBar
22795 * @extends Roo.util.Observable
22796 * Creates draggable splitter bar functionality from two elements (element to be dragged and element to be resized).
22800 var split = new Roo.SplitBar("elementToDrag", "elementToSize",
22801 Roo.SplitBar.HORIZONTAL, Roo.SplitBar.LEFT);
22802 split.setAdapter(new Roo.SplitBar.AbsoluteLayoutAdapter("container"));
22803 split.minSize = 100;
22804 split.maxSize = 600;
22805 split.animate = true;
22806 split.on('moved', splitterMoved);
22809 * Create a new SplitBar
22810 * @param {String/HTMLElement/Roo.Element} dragElement The element to be dragged and act as the SplitBar.
22811 * @param {String/HTMLElement/Roo.Element} resizingElement The element to be resized based on where the SplitBar element is dragged
22812 * @param {Number} orientation (optional) Either Roo.SplitBar.HORIZONTAL or Roo.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
22813 * @param {Number} placement (optional) Either Roo.SplitBar.LEFT or Roo.SplitBar.RIGHT for horizontal or
22814 Roo.SplitBar.TOP or Roo.SplitBar.BOTTOM for vertical. (By default, this is determined automatically by the initial
22815 position of the SplitBar).
22817 Roo.SplitBar = function(dragElement, resizingElement, orientation, placement, existingProxy){
22820 this.el = Roo.get(dragElement, true);
22821 this.el.dom.unselectable = "on";
22823 this.resizingEl = Roo.get(resizingElement, true);
22827 * The orientation of the split. Either Roo.SplitBar.HORIZONTAL or Roo.SplitBar.VERTICAL. (Defaults to HORIZONTAL)
22828 * Note: If this is changed after creating the SplitBar, the placement property must be manually updated
22831 this.orientation = orientation || Roo.SplitBar.HORIZONTAL;
22834 * The minimum size of the resizing element. (Defaults to 0)
22840 * The maximum size of the resizing element. (Defaults to 2000)
22843 this.maxSize = 2000;
22846 * Whether to animate the transition to the new size
22849 this.animate = false;
22852 * Whether to create a transparent shim that overlays the page when dragging, enables dragging across iframes.
22855 this.useShim = false;
22860 if(!existingProxy){
22862 this.proxy = Roo.SplitBar.createProxy(this.orientation);
22864 this.proxy = Roo.get(existingProxy).dom;
22867 this.dd = new Roo.dd.DDProxy(this.el.dom.id, "XSplitBars", {dragElId : this.proxy.id});
22870 this.dd.b4StartDrag = this.onStartProxyDrag.createDelegate(this);
22873 this.dd.endDrag = this.onEndProxyDrag.createDelegate(this);
22876 this.dragSpecs = {};
22879 * @private The adapter to use to positon and resize elements
22881 this.adapter = new Roo.SplitBar.BasicLayoutAdapter();
22882 this.adapter.init(this);
22884 if(this.orientation == Roo.SplitBar.HORIZONTAL){
22886 this.placement = placement || (this.el.getX() > this.resizingEl.getX() ? Roo.SplitBar.LEFT : Roo.SplitBar.RIGHT);
22887 this.el.addClass("x-splitbar-h");
22890 this.placement = placement || (this.el.getY() > this.resizingEl.getY() ? Roo.SplitBar.TOP : Roo.SplitBar.BOTTOM);
22891 this.el.addClass("x-splitbar-v");
22897 * Fires when the splitter is moved (alias for {@link #event-moved})
22898 * @param {Roo.SplitBar} this
22899 * @param {Number} newSize the new width or height
22904 * Fires when the splitter is moved
22905 * @param {Roo.SplitBar} this
22906 * @param {Number} newSize the new width or height
22910 * @event beforeresize
22911 * Fires before the splitter is dragged
22912 * @param {Roo.SplitBar} this
22914 "beforeresize" : true,
22916 "beforeapply" : true
22919 Roo.util.Observable.call(this);
22922 Roo.extend(Roo.SplitBar, Roo.util.Observable, {
22923 onStartProxyDrag : function(x, y){
22924 this.fireEvent("beforeresize", this);
22926 var o = Roo.DomHelper.insertFirst(document.body, {cls: "x-drag-overlay", html: " "}, true);
22928 o.enableDisplayMode("block");
22929 // all splitbars share the same overlay
22930 Roo.SplitBar.prototype.overlay = o;
22932 this.overlay.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
22933 this.overlay.show();
22934 Roo.get(this.proxy).setDisplayed("block");
22935 var size = this.adapter.getElementSize(this);
22936 this.activeMinSize = this.getMinimumSize();;
22937 this.activeMaxSize = this.getMaximumSize();;
22938 var c1 = size - this.activeMinSize;
22939 var c2 = Math.max(this.activeMaxSize - size, 0);
22940 if(this.orientation == Roo.SplitBar.HORIZONTAL){
22941 this.dd.resetConstraints();
22942 this.dd.setXConstraint(
22943 this.placement == Roo.SplitBar.LEFT ? c1 : c2,
22944 this.placement == Roo.SplitBar.LEFT ? c2 : c1
22946 this.dd.setYConstraint(0, 0);
22948 this.dd.resetConstraints();
22949 this.dd.setXConstraint(0, 0);
22950 this.dd.setYConstraint(
22951 this.placement == Roo.SplitBar.TOP ? c1 : c2,
22952 this.placement == Roo.SplitBar.TOP ? c2 : c1
22955 this.dragSpecs.startSize = size;
22956 this.dragSpecs.startPoint = [x, y];
22957 Roo.dd.DDProxy.prototype.b4StartDrag.call(this.dd, x, y);
22961 * @private Called after the drag operation by the DDProxy
22963 onEndProxyDrag : function(e){
22964 Roo.get(this.proxy).setDisplayed(false);
22965 var endPoint = Roo.lib.Event.getXY(e);
22967 this.overlay.hide();
22970 if(this.orientation == Roo.SplitBar.HORIZONTAL){
22971 newSize = this.dragSpecs.startSize +
22972 (this.placement == Roo.SplitBar.LEFT ?
22973 endPoint[0] - this.dragSpecs.startPoint[0] :
22974 this.dragSpecs.startPoint[0] - endPoint[0]
22977 newSize = this.dragSpecs.startSize +
22978 (this.placement == Roo.SplitBar.TOP ?
22979 endPoint[1] - this.dragSpecs.startPoint[1] :
22980 this.dragSpecs.startPoint[1] - endPoint[1]
22983 newSize = Math.min(Math.max(newSize, this.activeMinSize), this.activeMaxSize);
22984 if(newSize != this.dragSpecs.startSize){
22985 if(this.fireEvent('beforeapply', this, newSize) !== false){
22986 this.adapter.setElementSize(this, newSize);
22987 this.fireEvent("moved", this, newSize);
22988 this.fireEvent("resize", this, newSize);
22994 * Get the adapter this SplitBar uses
22995 * @return The adapter object
22997 getAdapter : function(){
22998 return this.adapter;
23002 * Set the adapter this SplitBar uses
23003 * @param {Object} adapter A SplitBar adapter object
23005 setAdapter : function(adapter){
23006 this.adapter = adapter;
23007 this.adapter.init(this);
23011 * Gets the minimum size for the resizing element
23012 * @return {Number} The minimum size
23014 getMinimumSize : function(){
23015 return this.minSize;
23019 * Sets the minimum size for the resizing element
23020 * @param {Number} minSize The minimum size
23022 setMinimumSize : function(minSize){
23023 this.minSize = minSize;
23027 * Gets the maximum size for the resizing element
23028 * @return {Number} The maximum size
23030 getMaximumSize : function(){
23031 return this.maxSize;
23035 * Sets the maximum size for the resizing element
23036 * @param {Number} maxSize The maximum size
23038 setMaximumSize : function(maxSize){
23039 this.maxSize = maxSize;
23043 * Sets the initialize size for the resizing element
23044 * @param {Number} size The initial size
23046 setCurrentSize : function(size){
23047 var oldAnimate = this.animate;
23048 this.animate = false;
23049 this.adapter.setElementSize(this, size);
23050 this.animate = oldAnimate;
23054 * Destroy this splitbar.
23055 * @param {Boolean} removeEl True to remove the element
23057 destroy : function(removeEl){
23059 this.shim.remove();
23062 this.proxy.parentNode.removeChild(this.proxy);
23070 * @private static Create our own proxy element element. So it will be the same same size on all browsers, we won't use borders. Instead we use a background color.
23072 Roo.SplitBar.createProxy = function(dir){
23073 var proxy = new Roo.Element(document.createElement("div"));
23074 proxy.unselectable();
23075 var cls = 'x-splitbar-proxy';
23076 proxy.addClass(cls + ' ' + (dir == Roo.SplitBar.HORIZONTAL ? cls +'-h' : cls + '-v'));
23077 document.body.appendChild(proxy.dom);
23082 * @class Roo.SplitBar.BasicLayoutAdapter
23083 * Default Adapter. It assumes the splitter and resizing element are not positioned
23084 * elements and only gets/sets the width of the element. Generally used for table based layouts.
23086 Roo.SplitBar.BasicLayoutAdapter = function(){
23089 Roo.SplitBar.BasicLayoutAdapter.prototype = {
23090 // do nothing for now
23091 init : function(s){
23095 * Called before drag operations to get the current size of the resizing element.
23096 * @param {Roo.SplitBar} s The SplitBar using this adapter
23098 getElementSize : function(s){
23099 if(s.orientation == Roo.SplitBar.HORIZONTAL){
23100 return s.resizingEl.getWidth();
23102 return s.resizingEl.getHeight();
23107 * Called after drag operations to set the size of the resizing element.
23108 * @param {Roo.SplitBar} s The SplitBar using this adapter
23109 * @param {Number} newSize The new size to set
23110 * @param {Function} onComplete A function to be invoked when resizing is complete
23112 setElementSize : function(s, newSize, onComplete){
23113 if(s.orientation == Roo.SplitBar.HORIZONTAL){
23115 s.resizingEl.setWidth(newSize);
23117 onComplete(s, newSize);
23120 s.resizingEl.setWidth(newSize, true, .1, onComplete, 'easeOut');
23125 s.resizingEl.setHeight(newSize);
23127 onComplete(s, newSize);
23130 s.resizingEl.setHeight(newSize, true, .1, onComplete, 'easeOut');
23137 *@class Roo.SplitBar.AbsoluteLayoutAdapter
23138 * @extends Roo.SplitBar.BasicLayoutAdapter
23139 * Adapter that moves the splitter element to align with the resized sizing element.
23140 * Used with an absolute positioned SplitBar.
23141 * @param {String/HTMLElement/Roo.Element} container The container that wraps around the absolute positioned content. If it's
23142 * document.body, make sure you assign an id to the body element.
23144 Roo.SplitBar.AbsoluteLayoutAdapter = function(container){
23145 this.basic = new Roo.SplitBar.BasicLayoutAdapter();
23146 this.container = Roo.get(container);
23149 Roo.SplitBar.AbsoluteLayoutAdapter.prototype = {
23150 init : function(s){
23151 this.basic.init(s);
23154 getElementSize : function(s){
23155 return this.basic.getElementSize(s);
23158 setElementSize : function(s, newSize, onComplete){
23159 this.basic.setElementSize(s, newSize, this.moveSplitter.createDelegate(this, [s]));
23162 moveSplitter : function(s){
23163 var yes = Roo.SplitBar;
23164 switch(s.placement){
23166 s.el.setX(s.resizingEl.getRight());
23169 s.el.setStyle("right", (this.container.getWidth() - s.resizingEl.getLeft()) + "px");
23172 s.el.setY(s.resizingEl.getBottom());
23175 s.el.setY(s.resizingEl.getTop() - s.el.getHeight());
23182 * Orientation constant - Create a vertical SplitBar
23186 Roo.SplitBar.VERTICAL = 1;
23189 * Orientation constant - Create a horizontal SplitBar
23193 Roo.SplitBar.HORIZONTAL = 2;
23196 * Placement constant - The resizing element is to the left of the splitter element
23200 Roo.SplitBar.LEFT = 1;
23203 * Placement constant - The resizing element is to the right of the splitter element
23207 Roo.SplitBar.RIGHT = 2;
23210 * Placement constant - The resizing element is positioned above the splitter element
23214 Roo.SplitBar.TOP = 3;
23217 * Placement constant - The resizing element is positioned under splitter element
23221 Roo.SplitBar.BOTTOM = 4;
23224 * Ext JS Library 1.1.1
23225 * Copyright(c) 2006-2007, Ext JS, LLC.
23227 * Originally Released Under LGPL - original licence link has changed is not relivant.
23230 * <script type="text/javascript">
23235 * @extends Roo.util.Observable
23236 * Create a "View" for an element based on a data model or UpdateManager and the supplied DomHelper template.
23237 * This class also supports single and multi selection modes. <br>
23238 * Create a data model bound view:
23240 var store = new Roo.data.Store(...);
23242 var view = new Roo.View({
23244 template : '<div id="{0}">{2} - {1}</div>', // auto create template
23246 singleSelect: true,
23247 selectedClass: "ydataview-selected",
23251 // listen for node click?
23252 view.on("click", function(vw, index, node, e){
23253 alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
23257 dataModel.load("foobar.xml");
23259 For an example of creating a JSON/UpdateManager view, see {@link Roo.JsonView}.
23261 * <b>Note: The root of your template must be a single node. Table/row implementations may work but are not supported due to
23262 * IE"s limited insertion support with tables and Opera"s faulty event bubbling.</b>
23264 * Note: old style constructor is still suported (container, template, config)
23267 * Create a new View
23268 * @param {Object} config The config object
23271 Roo.View = function(config, depreciated_tpl, depreciated_config){
23273 if (typeof(depreciated_tpl) == 'undefined') {
23274 // new way.. - universal constructor.
23275 Roo.apply(this, config);
23276 this.el = Roo.get(this.el);
23279 this.el = Roo.get(config);
23280 this.tpl = depreciated_tpl;
23281 Roo.apply(this, depreciated_config);
23285 if(typeof(this.tpl) == "string"){
23286 this.tpl = new Roo.Template(this.tpl);
23290 this.tpl.compile();
23297 * @event beforeclick
23298 * Fires before a click is processed. Returns false to cancel the default action.
23299 * @param {Roo.View} this
23300 * @param {Number} index The index of the target node
23301 * @param {HTMLElement} node The target node
23302 * @param {Roo.EventObject} e The raw event object
23304 "beforeclick" : true,
23307 * Fires when a template node is clicked.
23308 * @param {Roo.View} this
23309 * @param {Number} index The index of the target node
23310 * @param {HTMLElement} node The target node
23311 * @param {Roo.EventObject} e The raw event object
23316 * Fires when a template node is double clicked.
23317 * @param {Roo.View} this
23318 * @param {Number} index The index of the target node
23319 * @param {HTMLElement} node The target node
23320 * @param {Roo.EventObject} e The raw event object
23324 * @event contextmenu
23325 * Fires when a template node is right clicked.
23326 * @param {Roo.View} this
23327 * @param {Number} index The index of the target node
23328 * @param {HTMLElement} node The target node
23329 * @param {Roo.EventObject} e The raw event object
23331 "contextmenu" : true,
23333 * @event selectionchange
23334 * Fires when the selected nodes change.
23335 * @param {Roo.View} this
23336 * @param {Array} selections Array of the selected nodes
23338 "selectionchange" : true,
23341 * @event beforeselect
23342 * Fires before a selection is made. If any handlers return false, the selection is cancelled.
23343 * @param {Roo.View} this
23344 * @param {HTMLElement} node The node to be selected
23345 * @param {Array} selections Array of currently selected nodes
23347 "beforeselect" : true
23351 "click": this.onClick,
23352 "dblclick": this.onDblClick,
23353 "contextmenu": this.onContextMenu,
23357 this.selections = [];
23359 this.cmp = new Roo.CompositeElementLite([]);
23361 this.store = Roo.factory(this.store, Roo.data);
23362 this.setStore(this.store, true);
23364 Roo.View.superclass.constructor.call(this);
23367 Roo.extend(Roo.View, Roo.util.Observable, {
23370 * @cfg {Roo.data.Store} Data store to load data from.
23375 * @cfg {String|Roo.Element} The container element.
23380 * @cfg {String|Roo.DomHelper.Template} The template used by this View
23385 * @cfg {Roo.DomHelper.Template} The css class to add to selected nodes
23387 selectedClass : "x-view-selected",
23389 * @cfg {String} The empty text to show when nothing is loaded.
23393 * Returns the element this view is bound to.
23394 * @return {Roo.Element}
23396 getEl : function(){
23401 * Refreshes the view.
23403 refresh : function(){
23405 this.clearSelections();
23406 this.el.update("");
23408 var records = this.store.getRange();
23409 if(records.length < 1){
23410 this.el.update(this.emptyText);
23413 for(var i = 0, len = records.length; i < len; i++){
23414 var data = this.prepareData(records[i].data, i, records[i]);
23415 html[html.length] = t.apply(data);
23417 this.el.update(html.join(""));
23418 this.nodes = this.el.dom.childNodes;
23419 this.updateIndexes(0);
23423 * Function to override to reformat the data that is sent to
23424 * the template for each node.
23425 * @param {Array/Object} data The raw data (array of colData for a data model bound view or
23426 * a JSON object for an UpdateManager bound view).
23428 prepareData : function(data){
23432 onUpdate : function(ds, record){
23433 this.clearSelections();
23434 var index = this.store.indexOf(record);
23435 var n = this.nodes[index];
23436 this.tpl.insertBefore(n, this.prepareData(record.data));
23437 n.parentNode.removeChild(n);
23438 this.updateIndexes(index, index);
23441 onAdd : function(ds, records, index){
23442 this.clearSelections();
23443 if(this.nodes.length == 0){
23447 var n = this.nodes[index];
23448 for(var i = 0, len = records.length; i < len; i++){
23449 var d = this.prepareData(records[i].data);
23451 this.tpl.insertBefore(n, d);
23453 this.tpl.append(this.el, d);
23456 this.updateIndexes(index);
23459 onRemove : function(ds, record, index){
23460 this.clearSelections();
23461 this.el.dom.removeChild(this.nodes[index]);
23462 this.updateIndexes(index);
23466 * Refresh an individual node.
23467 * @param {Number} index
23469 refreshNode : function(index){
23470 this.onUpdate(this.store, this.store.getAt(index));
23473 updateIndexes : function(startIndex, endIndex){
23474 var ns = this.nodes;
23475 startIndex = startIndex || 0;
23476 endIndex = endIndex || ns.length - 1;
23477 for(var i = startIndex; i <= endIndex; i++){
23478 ns[i].nodeIndex = i;
23483 * Changes the data store this view uses and refresh the view.
23484 * @param {Store} store
23486 setStore : function(store, initial){
23487 if(!initial && this.store){
23488 this.store.un("datachanged", this.refresh);
23489 this.store.un("add", this.onAdd);
23490 this.store.un("remove", this.onRemove);
23491 this.store.un("update", this.onUpdate);
23492 this.store.un("clear", this.refresh);
23496 store.on("datachanged", this.refresh, this);
23497 store.on("add", this.onAdd, this);
23498 store.on("remove", this.onRemove, this);
23499 store.on("update", this.onUpdate, this);
23500 store.on("clear", this.refresh, this);
23509 * Returns the template node the passed child belongs to or null if it doesn't belong to one.
23510 * @param {HTMLElement} node
23511 * @return {HTMLElement} The template node
23513 findItemFromChild : function(node){
23514 var el = this.el.dom;
23515 if(!node || node.parentNode == el){
23518 var p = node.parentNode;
23519 while(p && p != el){
23520 if(p.parentNode == el){
23529 onClick : function(e){
23530 var item = this.findItemFromChild(e.getTarget());
23532 var index = this.indexOf(item);
23533 if(this.onItemClick(item, index, e) !== false){
23534 this.fireEvent("click", this, index, item, e);
23537 this.clearSelections();
23542 onContextMenu : function(e){
23543 var item = this.findItemFromChild(e.getTarget());
23545 this.fireEvent("contextmenu", this, this.indexOf(item), item, e);
23550 onDblClick : function(e){
23551 var item = this.findItemFromChild(e.getTarget());
23553 this.fireEvent("dblclick", this, this.indexOf(item), item, e);
23557 onItemClick : function(item, index, e){
23558 if(this.fireEvent("beforeclick", this, index, item, e) === false){
23561 if(this.multiSelect || this.singleSelect){
23562 if(this.multiSelect && e.shiftKey && this.lastSelection){
23563 this.select(this.getNodes(this.indexOf(this.lastSelection), index), false);
23565 this.select(item, this.multiSelect && e.ctrlKey);
23566 this.lastSelection = item;
23568 e.preventDefault();
23574 * Get the number of selected nodes.
23577 getSelectionCount : function(){
23578 return this.selections.length;
23582 * Get the currently selected nodes.
23583 * @return {Array} An array of HTMLElements
23585 getSelectedNodes : function(){
23586 return this.selections;
23590 * Get the indexes of the selected nodes.
23593 getSelectedIndexes : function(){
23594 var indexes = [], s = this.selections;
23595 for(var i = 0, len = s.length; i < len; i++){
23596 indexes.push(s[i].nodeIndex);
23602 * Clear all selections
23603 * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange event
23605 clearSelections : function(suppressEvent){
23606 if(this.nodes && (this.multiSelect || this.singleSelect) && this.selections.length > 0){
23607 this.cmp.elements = this.selections;
23608 this.cmp.removeClass(this.selectedClass);
23609 this.selections = [];
23610 if(!suppressEvent){
23611 this.fireEvent("selectionchange", this, this.selections);
23617 * Returns true if the passed node is selected
23618 * @param {HTMLElement/Number} node The node or node index
23619 * @return {Boolean}
23621 isSelected : function(node){
23622 var s = this.selections;
23626 node = this.getNode(node);
23627 return s.indexOf(node) !== -1;
23632 * @param {Array/HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node, id of a template node or an array of any of those to select
23633 * @param {Boolean} keepExisting (optional) true to keep existing selections
23634 * @param {Boolean} suppressEvent (optional) true to skip firing of the selectionchange vent
23636 select : function(nodeInfo, keepExisting, suppressEvent){
23637 if(nodeInfo instanceof Array){
23639 this.clearSelections(true);
23641 for(var i = 0, len = nodeInfo.length; i < len; i++){
23642 this.select(nodeInfo[i], true, true);
23645 var node = this.getNode(nodeInfo);
23646 if(node && !this.isSelected(node)){
23648 this.clearSelections(true);
23650 if(this.fireEvent("beforeselect", this, node, this.selections) !== false){
23651 Roo.fly(node).addClass(this.selectedClass);
23652 this.selections.push(node);
23653 if(!suppressEvent){
23654 this.fireEvent("selectionchange", this, this.selections);
23662 * Gets a template node.
23663 * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
23664 * @return {HTMLElement} The node or null if it wasn't found
23666 getNode : function(nodeInfo){
23667 if(typeof nodeInfo == "string"){
23668 return document.getElementById(nodeInfo);
23669 }else if(typeof nodeInfo == "number"){
23670 return this.nodes[nodeInfo];
23676 * Gets a range template nodes.
23677 * @param {Number} startIndex
23678 * @param {Number} endIndex
23679 * @return {Array} An array of nodes
23681 getNodes : function(start, end){
23682 var ns = this.nodes;
23683 start = start || 0;
23684 end = typeof end == "undefined" ? ns.length - 1 : end;
23687 for(var i = start; i <= end; i++){
23691 for(var i = start; i >= end; i--){
23699 * Finds the index of the passed node
23700 * @param {HTMLElement/String/Number} nodeInfo An HTMLElement template node, index of a template node or the id of a template node
23701 * @return {Number} The index of the node or -1
23703 indexOf : function(node){
23704 node = this.getNode(node);
23705 if(typeof node.nodeIndex == "number"){
23706 return node.nodeIndex;
23708 var ns = this.nodes;
23709 for(var i = 0, len = ns.length; i < len; i++){
23719 * Ext JS Library 1.1.1
23720 * Copyright(c) 2006-2007, Ext JS, LLC.
23722 * Originally Released Under LGPL - original licence link has changed is not relivant.
23725 * <script type="text/javascript">
23729 * @class Roo.JsonView
23730 * @extends Roo.View
23731 * Shortcut class to create a JSON + {@link Roo.UpdateManager} template view. Usage:
23733 var view = new Roo.JsonView({
23734 container: "my-element",
23735 template: '<div id="{id}">{foo} - {bar}</div>', // auto create template
23740 // listen for node click?
23741 view.on("click", function(vw, index, node, e){
23742 alert('Node "' + node.id + '" at index: ' + index + " was clicked.");
23745 // direct load of JSON data
23746 view.load("foobar.php");
23748 // Example from my blog list
23749 var tpl = new Roo.Template(
23750 '<div class="entry">' +
23751 '<a class="entry-title" href="{link}">{title}</a>' +
23752 "<h4>{date} by {author} | {comments} Comments</h4>{description}" +
23753 "</div><hr />"
23756 var moreView = new Roo.JsonView({
23757 container : "entry-list",
23761 moreView.on("beforerender", this.sortEntries, this);
23763 url: "/blog/get-posts.php",
23764 params: "allposts=true",
23765 text: "Loading Blog Entries..."
23769 * Note: old code is supported with arguments : (container, template, config)
23773 * Create a new JsonView
23775 * @param {Object} config The config object
23778 Roo.JsonView = function(config, depreciated_tpl, depreciated_config){
23781 Roo.JsonView.superclass.constructor.call(this, config, depreciated_tpl, depreciated_config);
23783 var um = this.el.getUpdateManager();
23784 um.setRenderer(this);
23785 um.on("update", this.onLoad, this);
23786 um.on("failure", this.onLoadException, this);
23789 * @event beforerender
23790 * Fires before rendering of the downloaded JSON data.
23791 * @param {Roo.JsonView} this
23792 * @param {Object} data The JSON data loaded
23796 * Fires when data is loaded.
23797 * @param {Roo.JsonView} this
23798 * @param {Object} data The JSON data loaded
23799 * @param {Object} response The raw Connect response object
23802 * @event loadexception
23803 * Fires when loading fails.
23804 * @param {Roo.JsonView} this
23805 * @param {Object} response The raw Connect response object
23808 'beforerender' : true,
23810 'loadexception' : true
23813 Roo.extend(Roo.JsonView, Roo.View, {
23816 * @cfg {String} The root property in the loaded JSON object that contains the data
23821 * Refreshes the view.
23823 refresh : function(){
23824 this.clearSelections();
23825 this.el.update("");
23827 var o = this.jsonData;
23828 if(o && o.length > 0){
23829 for(var i = 0, len = o.length; i < len; i++){
23830 var data = this.prepareData(o[i], i, o);
23831 html[html.length] = this.tpl.apply(data);
23834 html.push(this.emptyText);
23836 this.el.update(html.join(""));
23837 this.nodes = this.el.dom.childNodes;
23838 this.updateIndexes(0);
23842 * Performs an async HTTP request, and loads the JSON from the response. If <i>params</i> are specified it uses POST, otherwise it uses GET.
23843 * @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:
23846 url: "your-url.php",
23847 params: {param1: "foo", param2: "bar"}, // or a URL encoded string
23848 callback: yourFunction,
23849 scope: yourObject, //(optional scope)
23852 text: "Loading...",
23857 * The only required property is <i>url</i>. The optional properties <i>nocache</i>, <i>text</i> and <i>scripts</i>
23858 * are respectively shorthand for <i>disableCaching</i>, <i>indicatorText</i>, and <i>loadScripts</i> and are used to set their associated property on this UpdateManager instance.
23859 * @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}
23860 * @param {Function} callback (optional) Callback when transaction is complete - called with signature (oElement, bSuccess)
23861 * @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.
23864 var um = this.el.getUpdateManager();
23865 um.update.apply(um, arguments);
23868 render : function(el, response){
23869 this.clearSelections();
23870 this.el.update("");
23873 o = Roo.util.JSON.decode(response.responseText);
23876 o = /** eval:var:o */ eval("o." + this.jsonRoot);
23881 * The current JSON data or null
23884 this.beforeRender();
23889 * Get the number of records in the current JSON dataset
23892 getCount : function(){
23893 return this.jsonData ? this.jsonData.length : 0;
23897 * Returns the JSON object for the specified node(s)
23898 * @param {HTMLElement/Array} node The node or an array of nodes
23899 * @return {Object/Array} If you pass in an array, you get an array back, otherwise
23900 * you get the JSON object for the node
23902 getNodeData : function(node){
23903 if(node instanceof Array){
23905 for(var i = 0, len = node.length; i < len; i++){
23906 data.push(this.getNodeData(node[i]));
23910 return this.jsonData[this.indexOf(node)] || null;
23913 beforeRender : function(){
23914 this.snapshot = this.jsonData;
23916 this.sort.apply(this, this.sortInfo);
23918 this.fireEvent("beforerender", this, this.jsonData);
23921 onLoad : function(el, o){
23922 this.fireEvent("load", this, this.jsonData, o);
23925 onLoadException : function(el, o){
23926 this.fireEvent("loadexception", this, o);
23930 * Filter the data by a specific property.
23931 * @param {String} property A property on your JSON objects
23932 * @param {String/RegExp} value Either string that the property values
23933 * should start with, or a RegExp to test against the property
23935 filter : function(property, value){
23938 var ss = this.snapshot;
23939 if(typeof value == "string"){
23940 var vlen = value.length;
23942 this.clearFilter();
23945 value = value.toLowerCase();
23946 for(var i = 0, len = ss.length; i < len; i++){
23948 if(o[property].substr(0, vlen).toLowerCase() == value){
23952 } else if(value.exec){ // regex?
23953 for(var i = 0, len = ss.length; i < len; i++){
23955 if(value.test(o[property])){
23962 this.jsonData = data;
23968 * Filter by a function. The passed function will be called with each
23969 * object in the current dataset. If the function returns true the value is kept,
23970 * otherwise it is filtered.
23971 * @param {Function} fn
23972 * @param {Object} scope (optional) The scope of the function (defaults to this JsonView)
23974 filterBy : function(fn, scope){
23977 var ss = this.snapshot;
23978 for(var i = 0, len = ss.length; i < len; i++){
23980 if(fn.call(scope || this, o)){
23984 this.jsonData = data;
23990 * Clears the current filter.
23992 clearFilter : function(){
23993 if(this.snapshot && this.jsonData != this.snapshot){
23994 this.jsonData = this.snapshot;
24001 * Sorts the data for this view and refreshes it.
24002 * @param {String} property A property on your JSON objects to sort on
24003 * @param {String} direction (optional) "desc" or "asc" (defaults to "asc")
24004 * @param {Function} sortType (optional) A function to call to convert the data to a sortable value.
24006 sort : function(property, dir, sortType){
24007 this.sortInfo = Array.prototype.slice.call(arguments, 0);
24010 var dsc = dir && dir.toLowerCase() == "desc";
24011 var f = function(o1, o2){
24012 var v1 = sortType ? sortType(o1[p]) : o1[p];
24013 var v2 = sortType ? sortType(o2[p]) : o2[p];
24016 return dsc ? +1 : -1;
24017 } else if(v1 > v2){
24018 return dsc ? -1 : +1;
24023 this.jsonData.sort(f);
24025 if(this.jsonData != this.snapshot){
24026 this.snapshot.sort(f);
24032 * Ext JS Library 1.1.1
24033 * Copyright(c) 2006-2007, Ext JS, LLC.
24035 * Originally Released Under LGPL - original licence link has changed is not relivant.
24038 * <script type="text/javascript">
24043 * @class Roo.ColorPalette
24044 * @extends Roo.Component
24045 * Simple color palette class for choosing colors. The palette can be rendered to any container.<br />
24046 * Here's an example of typical usage:
24048 var cp = new Roo.ColorPalette({value:'993300'}); // initial selected color
24049 cp.render('my-div');
24051 cp.on('select', function(palette, selColor){
24052 // do something with selColor
24056 * Create a new ColorPalette
24057 * @param {Object} config The config object
24059 Roo.ColorPalette = function(config){
24060 Roo.ColorPalette.superclass.constructor.call(this, config);
24064 * Fires when a color is selected
24065 * @param {ColorPalette} this
24066 * @param {String} color The 6-digit color hex code (without the # symbol)
24072 this.on("select", this.handler, this.scope, true);
24075 Roo.extend(Roo.ColorPalette, Roo.Component, {
24077 * @cfg {String} itemCls
24078 * The CSS class to apply to the containing element (defaults to "x-color-palette")
24080 itemCls : "x-color-palette",
24082 * @cfg {String} value
24083 * The initial color to highlight (should be a valid 6-digit color hex code without the # symbol). Note that
24084 * the hex codes are case-sensitive.
24087 clickEvent:'click',
24089 ctype: "Roo.ColorPalette",
24092 * @cfg {Boolean} allowReselect If set to true then reselecting a color that is already selected fires the selection event
24094 allowReselect : false,
24097 * <p>An array of 6-digit color hex code strings (without the # symbol). This array can contain any number
24098 * of colors, and each hex code should be unique. The width of the palette is controlled via CSS by adjusting
24099 * the width property of the 'x-color-palette' class (or assigning a custom class), so you can balance the number
24100 * of colors with the width setting until the box is symmetrical.</p>
24101 * <p>You can override individual colors if needed:</p>
24103 var cp = new Roo.ColorPalette();
24104 cp.colors[0] = "FF0000"; // change the first box to red
24107 Or you can provide a custom array of your own for complete control:
24109 var cp = new Roo.ColorPalette();
24110 cp.colors = ["000000", "993300", "333300"];
24115 "000000", "993300", "333300", "003300", "003366", "000080", "333399", "333333",
24116 "800000", "FF6600", "808000", "008000", "008080", "0000FF", "666699", "808080",
24117 "FF0000", "FF9900", "99CC00", "339966", "33CCCC", "3366FF", "800080", "969696",
24118 "FF00FF", "FFCC00", "FFFF00", "00FF00", "00FFFF", "00CCFF", "993366", "C0C0C0",
24119 "FF99CC", "FFCC99", "FFFF99", "CCFFCC", "CCFFFF", "99CCFF", "CC99FF", "FFFFFF"
24123 onRender : function(container, position){
24124 var t = new Roo.MasterTemplate(
24125 '<tpl><a href="#" class="color-{0}" hidefocus="on"><em><span style="background:#{0}" unselectable="on"> </span></em></a></tpl>'
24127 var c = this.colors;
24128 for(var i = 0, len = c.length; i < len; i++){
24131 var el = document.createElement("div");
24132 el.className = this.itemCls;
24134 container.dom.insertBefore(el, position);
24135 this.el = Roo.get(el);
24136 this.el.on(this.clickEvent, this.handleClick, this, {delegate: "a"});
24137 if(this.clickEvent != 'click'){
24138 this.el.on('click', Roo.emptyFn, this, {delegate: "a", preventDefault:true});
24143 afterRender : function(){
24144 Roo.ColorPalette.superclass.afterRender.call(this);
24146 var s = this.value;
24153 handleClick : function(e, t){
24154 e.preventDefault();
24155 if(!this.disabled){
24156 var c = t.className.match(/(?:^|\s)color-(.{6})(?:\s|$)/)[1];
24157 this.select(c.toUpperCase());
24162 * Selects the specified color in the palette (fires the select event)
24163 * @param {String} color A valid 6-digit color hex code (# will be stripped if included)
24165 select : function(color){
24166 color = color.replace("#", "");
24167 if(color != this.value || this.allowReselect){
24170 el.child("a.color-"+this.value).removeClass("x-color-palette-sel");
24172 el.child("a.color-"+color).addClass("x-color-palette-sel");
24173 this.value = color;
24174 this.fireEvent("select", this, color);
24179 * Ext JS Library 1.1.1
24180 * Copyright(c) 2006-2007, Ext JS, LLC.
24182 * Originally Released Under LGPL - original licence link has changed is not relivant.
24185 * <script type="text/javascript">
24189 * @class Roo.DatePicker
24190 * @extends Roo.Component
24191 * Simple date picker class.
24193 * Create a new DatePicker
24194 * @param {Object} config The config object
24196 Roo.DatePicker = function(config){
24197 Roo.DatePicker.superclass.constructor.call(this, config);
24199 this.value = config && config.value ?
24200 config.value.clearTime() : new Date().clearTime();
24205 * Fires when a date is selected
24206 * @param {DatePicker} this
24207 * @param {Date} date The selected date
24213 this.on("select", this.handler, this.scope || this);
24215 // build the disabledDatesRE
24216 if(!this.disabledDatesRE && this.disabledDates){
24217 var dd = this.disabledDates;
24219 for(var i = 0; i < dd.length; i++){
24221 if(i != dd.length-1) re += "|";
24223 this.disabledDatesRE = new RegExp(re + ")");
24227 Roo.extend(Roo.DatePicker, Roo.Component, {
24229 * @cfg {String} todayText
24230 * The text to display on the button that selects the current date (defaults to "Today")
24232 todayText : "Today",
24234 * @cfg {String} okText
24235 * The text to display on the ok button
24237 okText : " OK ", //   to give the user extra clicking room
24239 * @cfg {String} cancelText
24240 * The text to display on the cancel button
24242 cancelText : "Cancel",
24244 * @cfg {String} todayTip
24245 * The tooltip to display for the button that selects the current date (defaults to "{current date} (Spacebar)")
24247 todayTip : "{0} (Spacebar)",
24249 * @cfg {Date} minDate
24250 * Minimum allowable date (JavaScript date object, defaults to null)
24254 * @cfg {Date} maxDate
24255 * Maximum allowable date (JavaScript date object, defaults to null)
24259 * @cfg {String} minText
24260 * The error text to display if the minDate validation fails (defaults to "This date is before the minimum date")
24262 minText : "This date is before the minimum date",
24264 * @cfg {String} maxText
24265 * The error text to display if the maxDate validation fails (defaults to "This date is after the maximum date")
24267 maxText : "This date is after the maximum date",
24269 * @cfg {String} format
24270 * The default date format string which can be overriden for localization support. The format must be
24271 * valid according to {@link Date#parseDate} (defaults to 'm/d/y').
24275 * @cfg {Array} disabledDays
24276 * An array of days to disable, 0-based. For example, [0, 6] disables Sunday and Saturday (defaults to null).
24278 disabledDays : null,
24280 * @cfg {String} disabledDaysText
24281 * The tooltip to display when the date falls on a disabled day (defaults to "")
24283 disabledDaysText : "",
24285 * @cfg {RegExp} disabledDatesRE
24286 * JavaScript regular expression used to disable a pattern of dates (defaults to null)
24288 disabledDatesRE : null,
24290 * @cfg {String} disabledDatesText
24291 * The tooltip text to display when the date falls on a disabled date (defaults to "")
24293 disabledDatesText : "",
24295 * @cfg {Boolean} constrainToViewport
24296 * True to constrain the date picker to the viewport (defaults to true)
24298 constrainToViewport : true,
24300 * @cfg {Array} monthNames
24301 * An array of textual month names which can be overriden for localization support (defaults to Date.monthNames)
24303 monthNames : Date.monthNames,
24305 * @cfg {Array} dayNames
24306 * An array of textual day names which can be overriden for localization support (defaults to Date.dayNames)
24308 dayNames : Date.dayNames,
24310 * @cfg {String} nextText
24311 * The next month navigation button tooltip (defaults to 'Next Month (Control+Right)')
24313 nextText: 'Next Month (Control+Right)',
24315 * @cfg {String} prevText
24316 * The previous month navigation button tooltip (defaults to 'Previous Month (Control+Left)')
24318 prevText: 'Previous Month (Control+Left)',
24320 * @cfg {String} monthYearText
24321 * The header month selector tooltip (defaults to 'Choose a month (Control+Up/Down to move years)')
24323 monthYearText: 'Choose a month (Control+Up/Down to move years)',
24325 * @cfg {Number} startDay
24326 * Day index at which the week should begin, 0-based (defaults to 0, which is Sunday)
24330 * @cfg {Bool} showClear
24331 * Show a clear button (usefull for date form elements that can be blank.)
24337 * Sets the value of the date field
24338 * @param {Date} value The date to set
24340 setValue : function(value){
24341 var old = this.value;
24342 this.value = value.clearTime(true);
24344 this.update(this.value);
24349 * Gets the current selected value of the date field
24350 * @return {Date} The selected date
24352 getValue : function(){
24357 focus : function(){
24359 this.update(this.activeDate);
24364 onRender : function(container, position){
24366 '<table cellspacing="0">',
24367 '<tr><td class="x-date-left"><a href="#" title="', this.prevText ,'"> </a></td><td class="x-date-middle" align="center"></td><td class="x-date-right"><a href="#" title="', this.nextText ,'"> </a></td></tr>',
24368 '<tr><td colspan="3"><table class="x-date-inner" cellspacing="0"><thead><tr>'];
24369 var dn = this.dayNames;
24370 for(var i = 0; i < 7; i++){
24371 var d = this.startDay+i;
24375 m.push("<th><span>", dn[d].substr(0,1), "</span></th>");
24377 m[m.length] = "</tr></thead><tbody><tr>";
24378 for(var i = 0; i < 42; i++) {
24379 if(i % 7 == 0 && i != 0){
24380 m[m.length] = "</tr><tr>";
24382 m[m.length] = '<td><a href="#" hidefocus="on" class="x-date-date" tabIndex="1"><em><span></span></em></a></td>';
24384 m[m.length] = '</tr></tbody></table></td></tr><tr>'+
24385 '<td colspan="3" class="x-date-bottom" align="center"></td></tr></table><div class="x-date-mp"></div>';
24387 var el = document.createElement("div");
24388 el.className = "x-date-picker";
24389 el.innerHTML = m.join("");
24391 container.dom.insertBefore(el, position);
24393 this.el = Roo.get(el);
24394 this.eventEl = Roo.get(el.firstChild);
24396 new Roo.util.ClickRepeater(this.el.child("td.x-date-left a"), {
24397 handler: this.showPrevMonth,
24399 preventDefault:true,
24403 new Roo.util.ClickRepeater(this.el.child("td.x-date-right a"), {
24404 handler: this.showNextMonth,
24406 preventDefault:true,
24410 this.eventEl.on("mousewheel", this.handleMouseWheel, this);
24412 this.monthPicker = this.el.down('div.x-date-mp');
24413 this.monthPicker.enableDisplayMode('block');
24415 var kn = new Roo.KeyNav(this.eventEl, {
24416 "left" : function(e){
24418 this.showPrevMonth() :
24419 this.update(this.activeDate.add("d", -1));
24422 "right" : function(e){
24424 this.showNextMonth() :
24425 this.update(this.activeDate.add("d", 1));
24428 "up" : function(e){
24430 this.showNextYear() :
24431 this.update(this.activeDate.add("d", -7));
24434 "down" : function(e){
24436 this.showPrevYear() :
24437 this.update(this.activeDate.add("d", 7));
24440 "pageUp" : function(e){
24441 this.showNextMonth();
24444 "pageDown" : function(e){
24445 this.showPrevMonth();
24448 "enter" : function(e){
24449 e.stopPropagation();
24456 this.eventEl.on("click", this.handleDateClick, this, {delegate: "a.x-date-date"});
24458 this.eventEl.addKeyListener(Roo.EventObject.SPACE, this.selectToday, this);
24460 this.el.unselectable();
24462 this.cells = this.el.select("table.x-date-inner tbody td");
24463 this.textNodes = this.el.query("table.x-date-inner tbody span");
24465 this.mbtn = new Roo.Button(this.el.child("td.x-date-middle", true), {
24467 tooltip: this.monthYearText
24470 this.mbtn.on('click', this.showMonthPicker, this);
24471 this.mbtn.el.child(this.mbtn.menuClassTarget).addClass("x-btn-with-menu");
24474 var today = (new Date()).dateFormat(this.format);
24476 var baseTb = new Roo.Toolbar(this.el.child("td.x-date-bottom", true));
24478 text: String.format(this.todayText, today),
24479 tooltip: String.format(this.todayTip, today),
24480 handler: this.selectToday,
24484 //var todayBtn = new Roo.Button(this.el.child("td.x-date-bottom", true), {
24487 if (this.showClear) {
24489 baseTb.add( new Roo.Toolbar.Fill());
24492 cls: 'x-btn-icon x-btn-clear',
24493 handler: function() {
24495 this.fireEvent("select", this, '');
24505 this.update(this.value);
24508 createMonthPicker : function(){
24509 if(!this.monthPicker.dom.firstChild){
24510 var buf = ['<table border="0" cellspacing="0">'];
24511 for(var i = 0; i < 6; i++){
24513 '<tr><td class="x-date-mp-month"><a href="#">', this.monthNames[i].substr(0, 3), '</a></td>',
24514 '<td class="x-date-mp-month x-date-mp-sep"><a href="#">', this.monthNames[i+6].substr(0, 3), '</a></td>',
24516 '<td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-prev"></a></td><td class="x-date-mp-ybtn" align="center"><a class="x-date-mp-next"></a></td></tr>' :
24517 '<td class="x-date-mp-year"><a href="#"></a></td><td class="x-date-mp-year"><a href="#"></a></td></tr>'
24521 '<tr class="x-date-mp-btns"><td colspan="4"><button type="button" class="x-date-mp-ok">',
24523 '</button><button type="button" class="x-date-mp-cancel">',
24525 '</button></td></tr>',
24528 this.monthPicker.update(buf.join(''));
24529 this.monthPicker.on('click', this.onMonthClick, this);
24530 this.monthPicker.on('dblclick', this.onMonthDblClick, this);
24532 this.mpMonths = this.monthPicker.select('td.x-date-mp-month');
24533 this.mpYears = this.monthPicker.select('td.x-date-mp-year');
24535 this.mpMonths.each(function(m, a, i){
24538 m.dom.xmonth = 5 + Math.round(i * .5);
24540 m.dom.xmonth = Math.round((i-1) * .5);
24546 showMonthPicker : function(){
24547 this.createMonthPicker();
24548 var size = this.el.getSize();
24549 this.monthPicker.setSize(size);
24550 this.monthPicker.child('table').setSize(size);
24552 this.mpSelMonth = (this.activeDate || this.value).getMonth();
24553 this.updateMPMonth(this.mpSelMonth);
24554 this.mpSelYear = (this.activeDate || this.value).getFullYear();
24555 this.updateMPYear(this.mpSelYear);
24557 this.monthPicker.slideIn('t', {duration:.2});
24560 updateMPYear : function(y){
24562 var ys = this.mpYears.elements;
24563 for(var i = 1; i <= 10; i++){
24564 var td = ys[i-1], y2;
24566 y2 = y + Math.round(i * .5);
24567 td.firstChild.innerHTML = y2;
24570 y2 = y - (5-Math.round(i * .5));
24571 td.firstChild.innerHTML = y2;
24574 this.mpYears.item(i-1)[y2 == this.mpSelYear ? 'addClass' : 'removeClass']('x-date-mp-sel');
24578 updateMPMonth : function(sm){
24579 this.mpMonths.each(function(m, a, i){
24580 m[m.dom.xmonth == sm ? 'addClass' : 'removeClass']('x-date-mp-sel');
24584 selectMPMonth: function(m){
24588 onMonthClick : function(e, t){
24590 var el = new Roo.Element(t), pn;
24591 if(el.is('button.x-date-mp-cancel')){
24592 this.hideMonthPicker();
24594 else if(el.is('button.x-date-mp-ok')){
24595 this.update(new Date(this.mpSelYear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
24596 this.hideMonthPicker();
24598 else if(pn = el.up('td.x-date-mp-month', 2)){
24599 this.mpMonths.removeClass('x-date-mp-sel');
24600 pn.addClass('x-date-mp-sel');
24601 this.mpSelMonth = pn.dom.xmonth;
24603 else if(pn = el.up('td.x-date-mp-year', 2)){
24604 this.mpYears.removeClass('x-date-mp-sel');
24605 pn.addClass('x-date-mp-sel');
24606 this.mpSelYear = pn.dom.xyear;
24608 else if(el.is('a.x-date-mp-prev')){
24609 this.updateMPYear(this.mpyear-10);
24611 else if(el.is('a.x-date-mp-next')){
24612 this.updateMPYear(this.mpyear+10);
24616 onMonthDblClick : function(e, t){
24618 var el = new Roo.Element(t), pn;
24619 if(pn = el.up('td.x-date-mp-month', 2)){
24620 this.update(new Date(this.mpSelYear, pn.dom.xmonth, (this.activeDate || this.value).getDate()));
24621 this.hideMonthPicker();
24623 else if(pn = el.up('td.x-date-mp-year', 2)){
24624 this.update(new Date(pn.dom.xyear, this.mpSelMonth, (this.activeDate || this.value).getDate()));
24625 this.hideMonthPicker();
24629 hideMonthPicker : function(disableAnim){
24630 if(this.monthPicker){
24631 if(disableAnim === true){
24632 this.monthPicker.hide();
24634 this.monthPicker.slideOut('t', {duration:.2});
24640 showPrevMonth : function(e){
24641 this.update(this.activeDate.add("mo", -1));
24645 showNextMonth : function(e){
24646 this.update(this.activeDate.add("mo", 1));
24650 showPrevYear : function(){
24651 this.update(this.activeDate.add("y", -1));
24655 showNextYear : function(){
24656 this.update(this.activeDate.add("y", 1));
24660 handleMouseWheel : function(e){
24661 var delta = e.getWheelDelta();
24663 this.showPrevMonth();
24665 } else if(delta < 0){
24666 this.showNextMonth();
24672 handleDateClick : function(e, t){
24674 if(t.dateValue && !Roo.fly(t.parentNode).hasClass("x-date-disabled")){
24675 this.setValue(new Date(t.dateValue));
24676 this.fireEvent("select", this, this.value);
24681 selectToday : function(){
24682 this.setValue(new Date().clearTime());
24683 this.fireEvent("select", this, this.value);
24687 update : function(date){
24688 var vd = this.activeDate;
24689 this.activeDate = date;
24691 var t = date.getTime();
24692 if(vd.getMonth() == date.getMonth() && vd.getFullYear() == date.getFullYear()){
24693 this.cells.removeClass("x-date-selected");
24694 this.cells.each(function(c){
24695 if(c.dom.firstChild.dateValue == t){
24696 c.addClass("x-date-selected");
24697 setTimeout(function(){
24698 try{c.dom.firstChild.focus();}catch(e){}
24706 var days = date.getDaysInMonth();
24707 var firstOfMonth = date.getFirstDateOfMonth();
24708 var startingPos = firstOfMonth.getDay()-this.startDay;
24710 if(startingPos <= this.startDay){
24714 var pm = date.add("mo", -1);
24715 var prevStart = pm.getDaysInMonth()-startingPos;
24717 var cells = this.cells.elements;
24718 var textEls = this.textNodes;
24719 days += startingPos;
24721 // convert everything to numbers so it's fast
24722 var day = 86400000;
24723 var d = (new Date(pm.getFullYear(), pm.getMonth(), prevStart)).clearTime();
24724 var today = new Date().clearTime().getTime();
24725 var sel = date.clearTime().getTime();
24726 var min = this.minDate ? this.minDate.clearTime() : Number.NEGATIVE_INFINITY;
24727 var max = this.maxDate ? this.maxDate.clearTime() : Number.POSITIVE_INFINITY;
24728 var ddMatch = this.disabledDatesRE;
24729 var ddText = this.disabledDatesText;
24730 var ddays = this.disabledDays ? this.disabledDays.join("") : false;
24731 var ddaysText = this.disabledDaysText;
24732 var format = this.format;
24734 var setCellClass = function(cal, cell){
24736 var t = d.getTime();
24737 cell.firstChild.dateValue = t;
24739 cell.className += " x-date-today";
24740 cell.title = cal.todayText;
24743 cell.className += " x-date-selected";
24744 setTimeout(function(){
24745 try{cell.firstChild.focus();}catch(e){}
24750 cell.className = " x-date-disabled";
24751 cell.title = cal.minText;
24755 cell.className = " x-date-disabled";
24756 cell.title = cal.maxText;
24760 if(ddays.indexOf(d.getDay()) != -1){
24761 cell.title = ddaysText;
24762 cell.className = " x-date-disabled";
24765 if(ddMatch && format){
24766 var fvalue = d.dateFormat(format);
24767 if(ddMatch.test(fvalue)){
24768 cell.title = ddText.replace("%0", fvalue);
24769 cell.className = " x-date-disabled";
24775 for(; i < startingPos; i++) {
24776 textEls[i].innerHTML = (++prevStart);
24777 d.setDate(d.getDate()+1);
24778 cells[i].className = "x-date-prevday";
24779 setCellClass(this, cells[i]);
24781 for(; i < days; i++){
24782 intDay = i - startingPos + 1;
24783 textEls[i].innerHTML = (intDay);
24784 d.setDate(d.getDate()+1);
24785 cells[i].className = "x-date-active";
24786 setCellClass(this, cells[i]);
24789 for(; i < 42; i++) {
24790 textEls[i].innerHTML = (++extraDays);
24791 d.setDate(d.getDate()+1);
24792 cells[i].className = "x-date-nextday";
24793 setCellClass(this, cells[i]);
24796 this.mbtn.setText(this.monthNames[date.getMonth()] + " " + date.getFullYear());
24798 if(!this.internalRender){
24799 var main = this.el.dom.firstChild;
24800 var w = main.offsetWidth;
24801 this.el.setWidth(w + this.el.getBorderWidth("lr"));
24802 Roo.fly(main).setWidth(w);
24803 this.internalRender = true;
24804 // opera does not respect the auto grow header center column
24805 // then, after it gets a width opera refuses to recalculate
24806 // without a second pass
24807 if(Roo.isOpera && !this.secondPass){
24808 main.rows[0].cells[1].style.width = (w - (main.rows[0].cells[0].offsetWidth+main.rows[0].cells[2].offsetWidth)) + "px";
24809 this.secondPass = true;
24810 this.update.defer(10, this, [date]);
24816 * Ext JS Library 1.1.1
24817 * Copyright(c) 2006-2007, Ext JS, LLC.
24819 * Originally Released Under LGPL - original licence link has changed is not relivant.
24822 * <script type="text/javascript">
24825 * @class Roo.TabPanel
24826 * @extends Roo.util.Observable
24827 * A lightweight tab container.
24831 // basic tabs 1, built from existing content
24832 var tabs = new Roo.TabPanel("tabs1");
24833 tabs.addTab("script", "View Script");
24834 tabs.addTab("markup", "View Markup");
24835 tabs.activate("script");
24837 // more advanced tabs, built from javascript
24838 var jtabs = new Roo.TabPanel("jtabs");
24839 jtabs.addTab("jtabs-1", "Normal Tab", "My content was added during construction.");
24841 // set up the UpdateManager
24842 var tab2 = jtabs.addTab("jtabs-2", "Ajax Tab 1");
24843 var updater = tab2.getUpdateManager();
24844 updater.setDefaultUrl("ajax1.htm");
24845 tab2.on('activate', updater.refresh, updater, true);
24847 // Use setUrl for Ajax loading
24848 var tab3 = jtabs.addTab("jtabs-3", "Ajax Tab 2");
24849 tab3.setUrl("ajax2.htm", null, true);
24852 var tab4 = jtabs.addTab("tabs1-5", "Disabled Tab", "Can't see me cause I'm disabled");
24855 jtabs.activate("jtabs-1");
24858 * Create a new TabPanel.
24859 * @param {String/HTMLElement/Roo.Element} container The id, DOM element or Roo.Element container where this TabPanel is to be rendered.
24860 * @param {Object/Boolean} config Config object to set any properties for this TabPanel, or true to render the tabs on the bottom.
24862 Roo.TabPanel = function(container, config){
24864 * The container element for this TabPanel.
24865 * @type Roo.Element
24867 this.el = Roo.get(container, true);
24869 if(typeof config == "boolean"){
24870 this.tabPosition = config ? "bottom" : "top";
24872 Roo.apply(this, config);
24875 if(this.tabPosition == "bottom"){
24876 this.bodyEl = Roo.get(this.createBody(this.el.dom));
24877 this.el.addClass("x-tabs-bottom");
24879 this.stripWrap = Roo.get(this.createStrip(this.el.dom), true);
24880 this.stripEl = Roo.get(this.createStripList(this.stripWrap.dom), true);
24881 this.stripBody = Roo.get(this.stripWrap.dom.firstChild.firstChild, true);
24883 Roo.fly(this.stripWrap.dom.firstChild).setStyle("overflow-x", "hidden");
24885 if(this.tabPosition != "bottom"){
24886 /** The body element that contains {@link Roo.TabPanelItem} bodies.
24887 * @type Roo.Element
24889 this.bodyEl = Roo.get(this.createBody(this.el.dom));
24890 this.el.addClass("x-tabs-top");
24894 this.bodyEl.setStyle("position", "relative");
24896 this.active = null;
24897 this.activateDelegate = this.activate.createDelegate(this);
24902 * Fires when the active tab changes
24903 * @param {Roo.TabPanel} this
24904 * @param {Roo.TabPanelItem} activePanel The new active tab
24908 * @event beforetabchange
24909 * Fires before the active tab changes, set cancel to true on the "e" parameter to cancel the change
24910 * @param {Roo.TabPanel} this
24911 * @param {Object} e Set cancel to true on this object to cancel the tab change
24912 * @param {Roo.TabPanelItem} tab The tab being changed to
24914 "beforetabchange" : true
24917 Roo.EventManager.onWindowResize(this.onResize, this);
24918 this.cpad = this.el.getPadding("lr");
24919 this.hiddenCount = 0;
24921 Roo.TabPanel.superclass.constructor.call(this);
24924 Roo.extend(Roo.TabPanel, Roo.util.Observable, {
24926 *@cfg {String} tabPosition "top" or "bottom" (defaults to "top")
24928 tabPosition : "top",
24930 *@cfg {Number} currentTabWidth The width of the current tab (defaults to 0)
24932 currentTabWidth : 0,
24934 *@cfg {Number} minTabWidth The minimum width of a tab (defaults to 40) (ignored if {@link #resizeTabs} is not true)
24938 *@cfg {Number} maxTabWidth The maximum width of a tab (defaults to 250) (ignored if {@link #resizeTabs} is not true)
24942 *@cfg {Number} preferredTabWidth The preferred (default) width of a tab (defaults to 175) (ignored if {@link #resizeTabs} is not true)
24944 preferredTabWidth : 175,
24946 *@cfg {Boolean} resizeTabs True to enable dynamic tab resizing (defaults to false)
24948 resizeTabs : false,
24950 *@cfg {Boolean} monitorResize Set this to true to turn on window resize monitoring (ignored if {@link #resizeTabs} is not true) (defaults to true)
24952 monitorResize : true,
24955 * Creates a new {@link Roo.TabPanelItem} by looking for an existing element with the provided id -- if it's not found it creates one.
24956 * @param {String} id The id of the div to use <b>or create</b>
24957 * @param {String} text The text for the tab
24958 * @param {String} content (optional) Content to put in the TabPanelItem body
24959 * @param {Boolean} closable (optional) True to create a close icon on the tab
24960 * @return {Roo.TabPanelItem} The created TabPanelItem
24962 addTab : function(id, text, content, closable){
24963 var item = new Roo.TabPanelItem(this, id, text, closable);
24964 this.addTabItem(item);
24966 item.setContent(content);
24972 * Returns the {@link Roo.TabPanelItem} with the specified id/index
24973 * @param {String/Number} id The id or index of the TabPanelItem to fetch.
24974 * @return {Roo.TabPanelItem}
24976 getTab : function(id){
24977 return this.items[id];
24981 * Hides the {@link Roo.TabPanelItem} with the specified id/index
24982 * @param {String/Number} id The id or index of the TabPanelItem to hide.
24984 hideTab : function(id){
24985 var t = this.items[id];
24988 this.hiddenCount++;
24989 this.autoSizeTabs();
24994 * "Unhides" the {@link Roo.TabPanelItem} with the specified id/index.
24995 * @param {String/Number} id The id or index of the TabPanelItem to unhide.
24997 unhideTab : function(id){
24998 var t = this.items[id];
25000 t.setHidden(false);
25001 this.hiddenCount--;
25002 this.autoSizeTabs();
25007 * Adds an existing {@link Roo.TabPanelItem}.
25008 * @param {Roo.TabPanelItem} item The TabPanelItem to add
25010 addTabItem : function(item){
25011 this.items[item.id] = item;
25012 this.items.push(item);
25013 if(this.resizeTabs){
25014 item.setWidth(this.currentTabWidth || this.preferredTabWidth);
25015 this.autoSizeTabs();
25022 * Removes a {@link Roo.TabPanelItem}.
25023 * @param {String/Number} id The id or index of the TabPanelItem to remove.
25025 removeTab : function(id){
25026 var items = this.items;
25027 var tab = items[id];
25029 var index = items.indexOf(tab);
25030 if(this.active == tab && items.length > 1){
25031 var newTab = this.getNextAvailable(index);
25032 if(newTab)newTab.activate();
25034 this.stripEl.dom.removeChild(tab.pnode.dom);
25035 if(tab.bodyEl.dom.parentNode == this.bodyEl.dom){ // if it was moved already prevent error
25036 this.bodyEl.dom.removeChild(tab.bodyEl.dom);
25038 items.splice(index, 1);
25039 delete this.items[tab.id];
25040 tab.fireEvent("close", tab);
25041 tab.purgeListeners();
25042 this.autoSizeTabs();
25045 getNextAvailable : function(start){
25046 var items = this.items;
25048 // look for a next tab that will slide over to
25049 // replace the one being removed
25050 while(index < items.length){
25051 var item = items[++index];
25052 if(item && !item.isHidden()){
25056 // if one isn't found select the previous tab (on the left)
25059 var item = items[--index];
25060 if(item && !item.isHidden()){
25068 * Disables a {@link Roo.TabPanelItem}. It cannot be the active tab, if it is this call is ignored.
25069 * @param {String/Number} id The id or index of the TabPanelItem to disable.
25071 disableTab : function(id){
25072 var tab = this.items[id];
25073 if(tab && this.active != tab){
25079 * Enables a {@link Roo.TabPanelItem} that is disabled.
25080 * @param {String/Number} id The id or index of the TabPanelItem to enable.
25082 enableTab : function(id){
25083 var tab = this.items[id];
25088 * Activates a {@link Roo.TabPanelItem}. The currently active one will be deactivated.
25089 * @param {String/Number} id The id or index of the TabPanelItem to activate.
25090 * @return {Roo.TabPanelItem} The TabPanelItem.
25092 activate : function(id){
25093 var tab = this.items[id];
25097 if(tab == this.active || tab.disabled){
25101 this.fireEvent("beforetabchange", this, e, tab);
25102 if(e.cancel !== true && !tab.disabled){
25104 this.active.hide();
25106 this.active = this.items[id];
25107 this.active.show();
25108 this.fireEvent("tabchange", this, this.active);
25114 * Gets the active {@link Roo.TabPanelItem}.
25115 * @return {Roo.TabPanelItem} The active TabPanelItem or null if none are active.
25117 getActiveTab : function(){
25118 return this.active;
25122 * Updates the tab body element to fit the height of the container element
25123 * for overflow scrolling
25124 * @param {Number} targetHeight (optional) Override the starting height from the elements height
25126 syncHeight : function(targetHeight){
25127 var height = (targetHeight || this.el.getHeight())-this.el.getBorderWidth("tb")-this.el.getPadding("tb");
25128 var bm = this.bodyEl.getMargins();
25129 var newHeight = height-(this.stripWrap.getHeight()||0)-(bm.top+bm.bottom);
25130 this.bodyEl.setHeight(newHeight);
25134 onResize : function(){
25135 if(this.monitorResize){
25136 this.autoSizeTabs();
25141 * Disables tab resizing while tabs are being added (if {@link #resizeTabs} is false this does nothing)
25143 beginUpdate : function(){
25144 this.updating = true;
25148 * Stops an update and resizes the tabs (if {@link #resizeTabs} is false this does nothing)
25150 endUpdate : function(){
25151 this.updating = false;
25152 this.autoSizeTabs();
25156 * Manual call to resize the tabs (if {@link #resizeTabs} is false this does nothing)
25158 autoSizeTabs : function(){
25159 var count = this.items.length;
25160 var vcount = count - this.hiddenCount;
25161 if(!this.resizeTabs || count < 1 || vcount < 1 || this.updating) return;
25162 var w = Math.max(this.el.getWidth() - this.cpad, 10);
25163 var availWidth = Math.floor(w / vcount);
25164 var b = this.stripBody;
25165 if(b.getWidth() > w){
25166 var tabs = this.items;
25167 this.setTabWidth(Math.max(availWidth, this.minTabWidth)-2);
25168 if(availWidth < this.minTabWidth){
25169 /*if(!this.sleft){ // incomplete scrolling code
25170 this.createScrollButtons();
25173 this.stripClip.setWidth(w - (this.sleft.getWidth()+this.sright.getWidth()));*/
25176 if(this.currentTabWidth < this.preferredTabWidth){
25177 this.setTabWidth(Math.min(availWidth, this.preferredTabWidth)-2);
25183 * Returns the number of tabs in this TabPanel.
25186 getCount : function(){
25187 return this.items.length;
25191 * Resizes all the tabs to the passed width
25192 * @param {Number} The new width
25194 setTabWidth : function(width){
25195 this.currentTabWidth = width;
25196 for(var i = 0, len = this.items.length; i < len; i++) {
25197 if(!this.items[i].isHidden())this.items[i].setWidth(width);
25202 * Destroys this TabPanel
25203 * @param {Boolean} removeEl (optional) True to remove the element from the DOM as well (defaults to undefined)
25205 destroy : function(removeEl){
25206 Roo.EventManager.removeResizeListener(this.onResize, this);
25207 for(var i = 0, len = this.items.length; i < len; i++){
25208 this.items[i].purgeListeners();
25210 if(removeEl === true){
25211 this.el.update("");
25218 * @class Roo.TabPanelItem
25219 * @extends Roo.util.Observable
25220 * Represents an individual item (tab plus body) in a TabPanel.
25221 * @param {Roo.TabPanel} tabPanel The {@link Roo.TabPanel} this TabPanelItem belongs to
25222 * @param {String} id The id of this TabPanelItem
25223 * @param {String} text The text for the tab of this TabPanelItem
25224 * @param {Boolean} closable True to allow this TabPanelItem to be closable (defaults to false)
25226 Roo.TabPanelItem = function(tabPanel, id, text, closable){
25228 * The {@link Roo.TabPanel} this TabPanelItem belongs to
25229 * @type Roo.TabPanel
25231 this.tabPanel = tabPanel;
25233 * The id for this TabPanelItem
25238 this.disabled = false;
25242 this.loaded = false;
25243 this.closable = closable;
25246 * The body element for this TabPanelItem.
25247 * @type Roo.Element
25249 this.bodyEl = Roo.get(tabPanel.createItemBody(tabPanel.bodyEl.dom, id));
25250 this.bodyEl.setVisibilityMode(Roo.Element.VISIBILITY);
25251 this.bodyEl.setStyle("display", "block");
25252 this.bodyEl.setStyle("zoom", "1");
25255 var els = tabPanel.createStripElements(tabPanel.stripEl.dom, text, closable);
25257 this.el = Roo.get(els.el, true);
25258 this.inner = Roo.get(els.inner, true);
25259 this.textEl = Roo.get(this.el.dom.firstChild.firstChild.firstChild, true);
25260 this.pnode = Roo.get(els.el.parentNode, true);
25261 this.el.on("mousedown", this.onTabMouseDown, this);
25262 this.el.on("click", this.onTabClick, this);
25265 var c = Roo.get(els.close, true);
25266 c.dom.title = this.closeText;
25267 c.addClassOnOver("close-over");
25268 c.on("click", this.closeClick, this);
25274 * Fires when this tab becomes the active tab.
25275 * @param {Roo.TabPanel} tabPanel The parent TabPanel
25276 * @param {Roo.TabPanelItem} this
25280 * @event beforeclose
25281 * Fires before this tab is closed. To cancel the close, set cancel to true on e (e.cancel = true).
25282 * @param {Roo.TabPanelItem} this
25283 * @param {Object} e Set cancel to true on this object to cancel the close.
25285 "beforeclose": true,
25288 * Fires when this tab is closed.
25289 * @param {Roo.TabPanelItem} this
25293 * @event deactivate
25294 * Fires when this tab is no longer the active tab.
25295 * @param {Roo.TabPanel} tabPanel The parent TabPanel
25296 * @param {Roo.TabPanelItem} this
25298 "deactivate" : true
25300 this.hidden = false;
25302 Roo.TabPanelItem.superclass.constructor.call(this);
25305 Roo.extend(Roo.TabPanelItem, Roo.util.Observable, {
25306 purgeListeners : function(){
25307 Roo.util.Observable.prototype.purgeListeners.call(this);
25308 this.el.removeAllListeners();
25311 * Shows this TabPanelItem -- this <b>does not</b> deactivate the currently active TabPanelItem.
25314 this.pnode.addClass("on");
25317 this.tabPanel.stripWrap.repaint();
25319 this.fireEvent("activate", this.tabPanel, this);
25323 * Returns true if this tab is the active tab.
25324 * @return {Boolean}
25326 isActive : function(){
25327 return this.tabPanel.getActiveTab() == this;
25331 * Hides this TabPanelItem -- if you don't activate another TabPanelItem this could look odd.
25334 this.pnode.removeClass("on");
25336 this.fireEvent("deactivate", this.tabPanel, this);
25339 hideAction : function(){
25340 this.bodyEl.hide();
25341 this.bodyEl.setStyle("position", "absolute");
25342 this.bodyEl.setLeft("-20000px");
25343 this.bodyEl.setTop("-20000px");
25346 showAction : function(){
25347 this.bodyEl.setStyle("position", "relative");
25348 this.bodyEl.setTop("");
25349 this.bodyEl.setLeft("");
25350 this.bodyEl.show();
25354 * Set the tooltip for the tab.
25355 * @param {String} tooltip The tab's tooltip
25357 setTooltip : function(text){
25358 if(Roo.QuickTips && Roo.QuickTips.isEnabled()){
25359 this.textEl.dom.qtip = text;
25360 this.textEl.dom.removeAttribute('title');
25362 this.textEl.dom.title = text;
25366 onTabClick : function(e){
25367 e.preventDefault();
25368 this.tabPanel.activate(this.id);
25371 onTabMouseDown : function(e){
25372 e.preventDefault();
25373 this.tabPanel.activate(this.id);
25376 getWidth : function(){
25377 return this.inner.getWidth();
25380 setWidth : function(width){
25381 var iwidth = width - this.pnode.getPadding("lr");
25382 this.inner.setWidth(iwidth);
25383 this.textEl.setWidth(iwidth-this.inner.getPadding("lr"));
25384 this.pnode.setWidth(width);
25388 * Show or hide the tab
25389 * @param {Boolean} hidden True to hide or false to show.
25391 setHidden : function(hidden){
25392 this.hidden = hidden;
25393 this.pnode.setStyle("display", hidden ? "none" : "");
25397 * Returns true if this tab is "hidden"
25398 * @return {Boolean}
25400 isHidden : function(){
25401 return this.hidden;
25405 * Returns the text for this tab
25408 getText : function(){
25412 autoSize : function(){
25413 //this.el.beginMeasure();
25414 this.textEl.setWidth(1);
25415 this.setWidth(this.textEl.dom.scrollWidth+this.pnode.getPadding("lr")+this.inner.getPadding("lr"));
25416 //this.el.endMeasure();
25420 * Sets the text for the tab (Note: this also sets the tooltip text)
25421 * @param {String} text The tab's text and tooltip
25423 setText : function(text){
25425 this.textEl.update(text);
25426 this.setTooltip(text);
25427 if(!this.tabPanel.resizeTabs){
25432 * Activates this TabPanelItem -- this <b>does</b> deactivate the currently active TabPanelItem.
25434 activate : function(){
25435 this.tabPanel.activate(this.id);
25439 * Disables this TabPanelItem -- this does nothing if this is the active TabPanelItem.
25441 disable : function(){
25442 if(this.tabPanel.active != this){
25443 this.disabled = true;
25444 this.pnode.addClass("disabled");
25449 * Enables this TabPanelItem if it was previously disabled.
25451 enable : function(){
25452 this.disabled = false;
25453 this.pnode.removeClass("disabled");
25457 * Sets the content for this TabPanelItem.
25458 * @param {String} content The content
25459 * @param {Boolean} loadScripts true to look for and load scripts
25461 setContent : function(content, loadScripts){
25462 this.bodyEl.update(content, loadScripts);
25466 * Gets the {@link Roo.UpdateManager} for the body of this TabPanelItem. Enables you to perform Ajax updates.
25467 * @return {Roo.UpdateManager} The UpdateManager
25469 getUpdateManager : function(){
25470 return this.bodyEl.getUpdateManager();
25474 * Set a URL to be used to load the content for this TabPanelItem.
25475 * @param {String/Function} url The URL to load the content from, or a function to call to get the URL
25476 * @param {String/Object} params (optional) The string params for the update call or an object of the params. See {@link Roo.UpdateManager#update} for more details. (Defaults to null)
25477 * @param {Boolean} loadOnce (optional) Whether to only load the content once. If this is false it makes the Ajax call every time this TabPanelItem is activated. (Defaults to false)
25478 * @return {Roo.UpdateManager} The UpdateManager
25480 setUrl : function(url, params, loadOnce){
25481 if(this.refreshDelegate){
25482 this.un('activate', this.refreshDelegate);
25484 this.refreshDelegate = this._handleRefresh.createDelegate(this, [url, params, loadOnce]);
25485 this.on("activate", this.refreshDelegate);
25486 return this.bodyEl.getUpdateManager();
25490 _handleRefresh : function(url, params, loadOnce){
25491 if(!loadOnce || !this.loaded){
25492 var updater = this.bodyEl.getUpdateManager();
25493 updater.update(url, params, this._setLoaded.createDelegate(this));
25498 * Forces a content refresh from the URL specified in the {@link #setUrl} method.
25499 * Will fail silently if the setUrl method has not been called.
25500 * This does not activate the panel, just updates its content.
25502 refresh : function(){
25503 if(this.refreshDelegate){
25504 this.loaded = false;
25505 this.refreshDelegate();
25510 _setLoaded : function(){
25511 this.loaded = true;
25515 closeClick : function(e){
25518 this.fireEvent("beforeclose", this, o);
25519 if(o.cancel !== true){
25520 this.tabPanel.removeTab(this.id);
25524 * The text displayed in the tooltip for the close icon.
25527 closeText : "Close this tab"
25531 Roo.TabPanel.prototype.createStrip = function(container){
25532 var strip = document.createElement("div");
25533 strip.className = "x-tabs-wrap";
25534 container.appendChild(strip);
25538 Roo.TabPanel.prototype.createStripList = function(strip){
25539 // div wrapper for retard IE
25540 strip.innerHTML = '<div class="x-tabs-strip-wrap"><table class="x-tabs-strip" cellspacing="0" cellpadding="0" border="0"><tbody><tr></tr></tbody></table></div>';
25541 return strip.firstChild.firstChild.firstChild.firstChild;
25544 Roo.TabPanel.prototype.createBody = function(container){
25545 var body = document.createElement("div");
25546 Roo.id(body, "tab-body");
25547 Roo.fly(body).addClass("x-tabs-body");
25548 container.appendChild(body);
25552 Roo.TabPanel.prototype.createItemBody = function(bodyEl, id){
25553 var body = Roo.getDom(id);
25555 body = document.createElement("div");
25558 Roo.fly(body).addClass("x-tabs-item-body");
25559 bodyEl.insertBefore(body, bodyEl.firstChild);
25563 Roo.TabPanel.prototype.createStripElements = function(stripEl, text, closable){
25564 var td = document.createElement("td");
25565 stripEl.appendChild(td);
25567 td.className = "x-tabs-closable";
25568 if(!this.closeTpl){
25569 this.closeTpl = new Roo.Template(
25570 '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
25571 '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span>' +
25572 '<div unselectable="on" class="close-icon"> </div></em></span></a>'
25575 var el = this.closeTpl.overwrite(td, {"text": text});
25576 var close = el.getElementsByTagName("div")[0];
25577 var inner = el.getElementsByTagName("em")[0];
25578 return {"el": el, "close": close, "inner": inner};
25581 this.tabTpl = new Roo.Template(
25582 '<a href="#" class="x-tabs-right"><span class="x-tabs-left"><em class="x-tabs-inner">' +
25583 '<span unselectable="on"' + (this.disableTooltips ? '' : ' title="{text}"') +' class="x-tabs-text">{text}</span></em></span></a>'
25586 var el = this.tabTpl.overwrite(td, {"text": text});
25587 var inner = el.getElementsByTagName("em")[0];
25588 return {"el": el, "inner": inner};
25592 * Ext JS Library 1.1.1
25593 * Copyright(c) 2006-2007, Ext JS, LLC.
25595 * Originally Released Under LGPL - original licence link has changed is not relivant.
25598 * <script type="text/javascript">
25602 * @class Roo.Button
25603 * @extends Roo.util.Observable
25604 * Simple Button class
25605 * @cfg {String} text The button text
25606 * @cfg {String} icon The path to an image to display in the button (the image will be set as the background-image
25607 * CSS property of the button by default, so if you want a mixed icon/text button, set cls:"x-btn-text-icon")
25608 * @cfg {Function} handler A function called when the button is clicked (can be used instead of click event)
25609 * @cfg {Object} scope The scope of the handler
25610 * @cfg {Number} minWidth The minimum width for this button (used to give a set of buttons a common width)
25611 * @cfg {String/Object} tooltip The tooltip for the button - can be a string or QuickTips config object
25612 * @cfg {Boolean} hidden True to start hidden (defaults to false)
25613 * @cfg {Boolean} disabled True to start disabled (defaults to false)
25614 * @cfg {Boolean} pressed True to start pressed (only if enableToggle = true)
25615 * @cfg {String} toggleGroup The group this toggle button is a member of (only 1 per group can be pressed, only
25616 applies if enableToggle = true)
25617 * @cfg {String/HTMLElement/Element} renderTo The element to append the button to
25618 * @cfg {Boolean/Object} repeat True to repeat fire the click event while the mouse is down. This can also be
25619 an {@link Roo.util.ClickRepeater} config object (defaults to false).
25621 * Create a new button
25622 * @param {Object} config The config object
25624 Roo.Button = function(renderTo, config)
25628 renderTo = config.renderTo || false;
25631 Roo.apply(this, config);
25635 * Fires when this button is clicked
25636 * @param {Button} this
25637 * @param {EventObject} e The click event
25642 * Fires when the "pressed" state of this button changes (only if enableToggle = true)
25643 * @param {Button} this
25644 * @param {Boolean} pressed
25649 * Fires when the mouse hovers over the button
25650 * @param {Button} this
25651 * @param {Event} e The event object
25653 'mouseover' : true,
25656 * Fires when the mouse exits the button
25657 * @param {Button} this
25658 * @param {Event} e The event object
25663 * Fires when the button is rendered
25664 * @param {Button} this
25669 this.menu = Roo.menu.MenuMgr.get(this.menu);
25672 this.render(renderTo);
25675 Roo.util.Observable.call(this);
25678 Roo.extend(Roo.Button, Roo.util.Observable, {
25684 * Read-only. True if this button is hidden
25689 * Read-only. True if this button is disabled
25694 * Read-only. True if this button is pressed (only if enableToggle = true)
25700 * @cfg {Number} tabIndex
25701 * The DOM tabIndex for this button (defaults to undefined)
25703 tabIndex : undefined,
25706 * @cfg {Boolean} enableToggle
25707 * True to enable pressed/not pressed toggling (defaults to false)
25709 enableToggle: false,
25711 * @cfg {Mixed} menu
25712 * Standard menu attribute consisting of a reference to a menu object, a menu id or a menu config blob (defaults to undefined).
25716 * @cfg {String} menuAlign
25717 * The position to align the menu to (see {@link Roo.Element#alignTo} for more details, defaults to 'tl-bl?').
25719 menuAlign : "tl-bl?",
25722 * @cfg {String} iconCls
25723 * A css class which sets a background image to be used as the icon for this button (defaults to undefined).
25725 iconCls : undefined,
25727 * @cfg {String} type
25728 * The button's type, corresponding to the DOM input element type attribute. Either "submit," "reset" or "button" (default).
25733 menuClassTarget: 'tr',
25736 * @cfg {String} clickEvent
25737 * The type of event to map to the button's event handler (defaults to 'click')
25739 clickEvent : 'click',
25742 * @cfg {Boolean} handleMouseEvents
25743 * False to disable visual cues on mouseover, mouseout and mousedown (defaults to true)
25745 handleMouseEvents : true,
25748 * @cfg {String} tooltipType
25749 * The type of tooltip to use. Either "qtip" (default) for QuickTips or "title" for title attribute.
25751 tooltipType : 'qtip',
25754 * @cfg {String} cls
25755 * A CSS class to apply to the button's main element.
25759 * @cfg {Roo.Template} template (Optional)
25760 * An {@link Roo.Template} with which to create the Button's main element. This Template must
25761 * contain numeric substitution parameter 0 if it is to display the tRoo property. Changing the template could
25762 * require code modifications if required elements (e.g. a button) aren't present.
25766 render : function(renderTo){
25768 if(this.hideParent){
25769 this.parentEl = Roo.get(renderTo);
25771 if(!this.dhconfig){
25772 if(!this.template){
25773 if(!Roo.Button.buttonTemplate){
25774 // hideous table template
25775 Roo.Button.buttonTemplate = new Roo.Template(
25776 '<table border="0" cellpadding="0" cellspacing="0" class="x-btn-wrap"><tbody><tr>',
25777 '<td class="x-btn-left"><i> </i></td><td class="x-btn-center"><em unselectable="on"><button class="x-btn-text" type="{1}">{0}</button></em></td><td class="x-btn-right"><i> </i></td>',
25778 "</tr></tbody></table>");
25780 this.template = Roo.Button.buttonTemplate;
25782 btn = this.template.append(renderTo, [this.text || ' ', this.type], true);
25783 var btnEl = btn.child("button:first");
25784 btnEl.on('focus', this.onFocus, this);
25785 btnEl.on('blur', this.onBlur, this);
25787 btn.addClass(this.cls);
25790 btnEl.setStyle('background-image', 'url(' +this.icon +')');
25793 btnEl.addClass(this.iconCls);
25795 btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
25798 if(this.tabIndex !== undefined){
25799 btnEl.dom.tabIndex = this.tabIndex;
25802 if(typeof this.tooltip == 'object'){
25803 Roo.QuickTips.tips(Roo.apply({
25807 btnEl.dom[this.tooltipType] = this.tooltip;
25811 btn = Roo.DomHelper.append(Roo.get(renderTo).dom, this.dhconfig, true);
25815 this.el.dom.id = this.el.id = this.id;
25818 this.el.child(this.menuClassTarget).addClass("x-btn-with-menu");
25819 this.menu.on("show", this.onMenuShow, this);
25820 this.menu.on("hide", this.onMenuHide, this);
25822 btn.addClass("x-btn");
25823 if(Roo.isIE && !Roo.isIE7){
25824 this.autoWidth.defer(1, this);
25828 if(this.handleMouseEvents){
25829 btn.on("mouseover", this.onMouseOver, this);
25830 btn.on("mouseout", this.onMouseOut, this);
25831 btn.on("mousedown", this.onMouseDown, this);
25833 btn.on(this.clickEvent, this.onClick, this);
25834 //btn.on("mouseup", this.onMouseUp, this);
25841 Roo.ButtonToggleMgr.register(this);
25843 this.el.addClass("x-btn-pressed");
25846 var repeater = new Roo.util.ClickRepeater(btn,
25847 typeof this.repeat == "object" ? this.repeat : {}
25849 repeater.on("click", this.onClick, this);
25851 this.fireEvent('render', this);
25855 * Returns the button's underlying element
25856 * @return {Roo.Element} The element
25858 getEl : function(){
25863 * Destroys this Button and removes any listeners.
25865 destroy : function(){
25866 Roo.ButtonToggleMgr.unregister(this);
25867 this.el.removeAllListeners();
25868 this.purgeListeners();
25873 autoWidth : function(){
25875 this.el.setWidth("auto");
25876 if(Roo.isIE7 && Roo.isStrict){
25877 var ib = this.el.child('button');
25878 if(ib && ib.getWidth() > 20){
25880 ib.setWidth(Roo.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
25885 this.el.beginMeasure();
25887 if(this.el.getWidth() < this.minWidth){
25888 this.el.setWidth(this.minWidth);
25891 this.el.endMeasure();
25898 * Assigns this button's click handler
25899 * @param {Function} handler The function to call when the button is clicked
25900 * @param {Object} scope (optional) Scope for the function passed in
25902 setHandler : function(handler, scope){
25903 this.handler = handler;
25904 this.scope = scope;
25908 * Sets this button's text
25909 * @param {String} text The button text
25911 setText : function(text){
25914 this.el.child("td.x-btn-center button.x-btn-text").update(text);
25920 * Gets the text for this button
25921 * @return {String} The button text
25923 getText : function(){
25931 this.hidden = false;
25933 this[this.hideParent? 'parentEl' : 'el'].setStyle("display", "");
25941 this.hidden = true;
25943 this[this.hideParent? 'parentEl' : 'el'].setStyle("display", "none");
25948 * Convenience function for boolean show/hide
25949 * @param {Boolean} visible True to show, false to hide
25951 setVisible: function(visible){
25960 * If a state it passed, it becomes the pressed state otherwise the current state is toggled.
25961 * @param {Boolean} state (optional) Force a particular state
25963 toggle : function(state){
25964 state = state === undefined ? !this.pressed : state;
25965 if(state != this.pressed){
25967 this.el.addClass("x-btn-pressed");
25968 this.pressed = true;
25969 this.fireEvent("toggle", this, true);
25971 this.el.removeClass("x-btn-pressed");
25972 this.pressed = false;
25973 this.fireEvent("toggle", this, false);
25975 if(this.toggleHandler){
25976 this.toggleHandler.call(this.scope || this, this, state);
25984 focus : function(){
25985 this.el.child('button:first').focus();
25989 * Disable this button
25991 disable : function(){
25993 this.el.addClass("x-btn-disabled");
25995 this.disabled = true;
25999 * Enable this button
26001 enable : function(){
26003 this.el.removeClass("x-btn-disabled");
26005 this.disabled = false;
26009 * Convenience function for boolean enable/disable
26010 * @param {Boolean} enabled True to enable, false to disable
26012 setDisabled : function(v){
26013 this[v !== true ? "enable" : "disable"]();
26017 onClick : function(e){
26019 e.preventDefault();
26024 if(!this.disabled){
26025 if(this.enableToggle){
26028 if(this.menu && !this.menu.isVisible()){
26029 this.menu.show(this.el, this.menuAlign);
26031 this.fireEvent("click", this, e);
26033 this.el.removeClass("x-btn-over");
26034 this.handler.call(this.scope || this, this, e);
26039 onMouseOver : function(e){
26040 if(!this.disabled){
26041 this.el.addClass("x-btn-over");
26042 this.fireEvent('mouseover', this, e);
26046 onMouseOut : function(e){
26047 if(!e.within(this.el, true)){
26048 this.el.removeClass("x-btn-over");
26049 this.fireEvent('mouseout', this, e);
26053 onFocus : function(e){
26054 if(!this.disabled){
26055 this.el.addClass("x-btn-focus");
26059 onBlur : function(e){
26060 this.el.removeClass("x-btn-focus");
26063 onMouseDown : function(e){
26064 if(!this.disabled && e.button == 0){
26065 this.el.addClass("x-btn-click");
26066 Roo.get(document).on('mouseup', this.onMouseUp, this);
26070 onMouseUp : function(e){
26072 this.el.removeClass("x-btn-click");
26073 Roo.get(document).un('mouseup', this.onMouseUp, this);
26077 onMenuShow : function(e){
26078 this.el.addClass("x-btn-menu-active");
26081 onMenuHide : function(e){
26082 this.el.removeClass("x-btn-menu-active");
26086 // Private utility class used by Button
26087 Roo.ButtonToggleMgr = function(){
26090 function toggleGroup(btn, state){
26092 var g = groups[btn.toggleGroup];
26093 for(var i = 0, l = g.length; i < l; i++){
26095 g[i].toggle(false);
26102 register : function(btn){
26103 if(!btn.toggleGroup){
26106 var g = groups[btn.toggleGroup];
26108 g = groups[btn.toggleGroup] = [];
26111 btn.on("toggle", toggleGroup);
26114 unregister : function(btn){
26115 if(!btn.toggleGroup){
26118 var g = groups[btn.toggleGroup];
26121 btn.un("toggle", toggleGroup);
26127 * Ext JS Library 1.1.1
26128 * Copyright(c) 2006-2007, Ext JS, LLC.
26130 * Originally Released Under LGPL - original licence link has changed is not relivant.
26133 * <script type="text/javascript">
26137 * @class Roo.SplitButton
26138 * @extends Roo.Button
26139 * A split button that provides a built-in dropdown arrow that can fire an event separately from the default
26140 * click event of the button. Typically this would be used to display a dropdown menu that provides additional
26141 * options to the primary button action, but any custom handler can provide the arrowclick implementation.
26142 * @cfg {Function} arrowHandler A function called when the arrow button is clicked (can be used instead of click event)
26143 * @cfg {String} arrowTooltip The title attribute of the arrow
26145 * Create a new menu button
26146 * @param {String/HTMLElement/Element} renderTo The element to append the button to
26147 * @param {Object} config The config object
26149 Roo.SplitButton = function(renderTo, config){
26150 Roo.SplitButton.superclass.constructor.call(this, renderTo, config);
26152 * @event arrowclick
26153 * Fires when this button's arrow is clicked
26154 * @param {SplitButton} this
26155 * @param {EventObject} e The click event
26157 this.addEvents({"arrowclick":true});
26160 Roo.extend(Roo.SplitButton, Roo.Button, {
26161 render : function(renderTo){
26162 // this is one sweet looking template!
26163 var tpl = new Roo.Template(
26164 '<table cellspacing="0" class="x-btn-menu-wrap x-btn"><tr><td>',
26165 '<table cellspacing="0" class="x-btn-wrap x-btn-menu-text-wrap"><tbody>',
26166 '<tr><td class="x-btn-left"><i> </i></td><td class="x-btn-center"><button class="x-btn-text" type="{1}">{0}</button></td></tr>',
26167 "</tbody></table></td><td>",
26168 '<table cellspacing="0" class="x-btn-wrap x-btn-menu-arrow-wrap"><tbody>',
26169 '<tr><td class="x-btn-center"><button class="x-btn-menu-arrow-el" type="button"> </button></td><td class="x-btn-right"><i> </i></td></tr>',
26170 "</tbody></table></td></tr></table>"
26172 var btn = tpl.append(renderTo, [this.text, this.type], true);
26173 var btnEl = btn.child("button");
26175 btn.addClass(this.cls);
26178 btnEl.setStyle('background-image', 'url(' +this.icon +')');
26181 btnEl.addClass(this.iconCls);
26183 btn.addClass(this.text ? 'x-btn-text-icon' : 'x-btn-icon');
26187 if(this.handleMouseEvents){
26188 btn.on("mouseover", this.onMouseOver, this);
26189 btn.on("mouseout", this.onMouseOut, this);
26190 btn.on("mousedown", this.onMouseDown, this);
26191 btn.on("mouseup", this.onMouseUp, this);
26193 btn.on(this.clickEvent, this.onClick, this);
26195 if(typeof this.tooltip == 'object'){
26196 Roo.QuickTips.tips(Roo.apply({
26200 btnEl.dom[this.tooltipType] = this.tooltip;
26203 if(this.arrowTooltip){
26204 btn.child("button:nth(2)").dom[this.tooltipType] = this.arrowTooltip;
26213 this.el.addClass("x-btn-pressed");
26215 if(Roo.isIE && !Roo.isIE7){
26216 this.autoWidth.defer(1, this);
26221 this.menu.on("show", this.onMenuShow, this);
26222 this.menu.on("hide", this.onMenuHide, this);
26224 this.fireEvent('render', this);
26228 autoWidth : function(){
26230 var tbl = this.el.child("table:first");
26231 var tbl2 = this.el.child("table:last");
26232 this.el.setWidth("auto");
26233 tbl.setWidth("auto");
26234 if(Roo.isIE7 && Roo.isStrict){
26235 var ib = this.el.child('button:first');
26236 if(ib && ib.getWidth() > 20){
26238 ib.setWidth(Roo.util.TextMetrics.measure(ib, this.text).width+ib.getFrameWidth('lr'));
26243 this.el.beginMeasure();
26245 if((tbl.getWidth()+tbl2.getWidth()) < this.minWidth){
26246 tbl.setWidth(this.minWidth-tbl2.getWidth());
26249 this.el.endMeasure();
26252 this.el.setWidth(tbl.getWidth()+tbl2.getWidth());
26256 * Sets this button's click handler
26257 * @param {Function} handler The function to call when the button is clicked
26258 * @param {Object} scope (optional) Scope for the function passed above
26260 setHandler : function(handler, scope){
26261 this.handler = handler;
26262 this.scope = scope;
26266 * Sets this button's arrow click handler
26267 * @param {Function} handler The function to call when the arrow is clicked
26268 * @param {Object} scope (optional) Scope for the function passed above
26270 setArrowHandler : function(handler, scope){
26271 this.arrowHandler = handler;
26272 this.scope = scope;
26278 focus : function(){
26280 this.el.child("button:first").focus();
26285 onClick : function(e){
26286 e.preventDefault();
26287 if(!this.disabled){
26288 if(e.getTarget(".x-btn-menu-arrow-wrap")){
26289 if(this.menu && !this.menu.isVisible()){
26290 this.menu.show(this.el, this.menuAlign);
26292 this.fireEvent("arrowclick", this, e);
26293 if(this.arrowHandler){
26294 this.arrowHandler.call(this.scope || this, this, e);
26297 this.fireEvent("click", this, e);
26299 this.handler.call(this.scope || this, this, e);
26305 onMouseDown : function(e){
26306 if(!this.disabled){
26307 Roo.fly(e.getTarget("table")).addClass("x-btn-click");
26311 onMouseUp : function(e){
26312 Roo.fly(e.getTarget("table")).removeClass("x-btn-click");
26317 // backwards compat
26318 Roo.MenuButton = Roo.SplitButton;/*
26320 * Ext JS Library 1.1.1
26321 * Copyright(c) 2006-2007, Ext JS, LLC.
26323 * Originally Released Under LGPL - original licence link has changed is not relivant.
26326 * <script type="text/javascript">
26330 * @class Roo.Toolbar
26331 * Basic Toolbar class.
26333 * Creates a new Toolbar
26334 * @param {Object} config The config object
26336 Roo.Toolbar = function(container, buttons, config)
26338 /// old consturctor format still supported..
26339 if(container instanceof Array){ // omit the container for later rendering
26340 buttons = container;
26344 if (typeof(container) == 'object' && container.xtype) {
26345 config = container;
26346 container = config.container;
26347 buttons = config.buttons; // not really - use items!!
26350 if (config && config.items) {
26351 xitems = config.items;
26352 delete config.items;
26354 Roo.apply(this, config);
26355 this.buttons = buttons;
26358 this.render(container);
26360 Roo.each(xitems, function(b) {
26366 Roo.Toolbar.prototype = {
26368 * @cfg {Roo.data.Store} items
26369 * array of button configs or elements to add
26373 * @cfg {String/HTMLElement/Element} container
26374 * The id or element that will contain the toolbar
26377 render : function(ct){
26378 this.el = Roo.get(ct);
26380 this.el.addClass(this.cls);
26382 // using a table allows for vertical alignment
26383 // 100% width is needed by Safari...
26384 this.el.update('<div class="x-toolbar x-small-editor"><table cellspacing="0"><tr></tr></table></div>');
26385 this.tr = this.el.child("tr", true);
26387 this.items = new Roo.util.MixedCollection(false, function(o){
26388 return o.id || ("item" + (++autoId));
26391 this.add.apply(this, this.buttons);
26392 delete this.buttons;
26397 * Adds element(s) to the toolbar -- this function takes a variable number of
26398 * arguments of mixed type and adds them to the toolbar.
26399 * @param {Mixed} arg1 The following types of arguments are all valid:<br />
26401 * <li>{@link Roo.Toolbar.Button} config: A valid button config object (equivalent to {@link #addButton})</li>
26402 * <li>HtmlElement: Any standard HTML element (equivalent to {@link #addElement})</li>
26403 * <li>Field: Any form field (equivalent to {@link #addField})</li>
26404 * <li>Item: Any subclass of {@link Roo.Toolbar.Item} (equivalent to {@link #addItem})</li>
26405 * <li>String: Any generic string (gets wrapped in a {@link Roo.Toolbar.TextItem}, equivalent to {@link #addText}).
26406 * Note that there are a few special strings that are treated differently as explained nRoo.</li>
26407 * <li>'separator' or '-': Creates a separator element (equivalent to {@link #addSeparator})</li>
26408 * <li>' ': Creates a spacer element (equivalent to {@link #addSpacer})</li>
26409 * <li>'->': Creates a fill element (equivalent to {@link #addFill})</li>
26411 * @param {Mixed} arg2
26412 * @param {Mixed} etc.
26415 var a = arguments, l = a.length;
26416 for(var i = 0; i < l; i++){
26421 _add : function(el) {
26424 el = Roo.factory(el, typeof(Roo.Toolbar[el.xtype]) == 'undefined' ? Roo.form : Roo.Toolbar);
26427 if (el.applyTo){ // some kind of form field
26428 return this.addField(el);
26430 if (el.render){ // some kind of Toolbar.Item
26431 return this.addItem(el);
26433 if (typeof el == "string"){ // string
26434 if(el == "separator" || el == "-"){
26435 return this.addSeparator();
26438 return this.addSpacer();
26441 return this.addFill();
26443 return this.addText(el);
26446 if(el.tagName){ // element
26447 return this.addElement(el);
26449 if(typeof el == "object"){ // must be button config?
26450 return this.addButton(el);
26452 // and now what?!?!
26458 * Add an Xtype element
26459 * @param {Object} xtype Xtype Object
26460 * @return {Object} created Object
26462 addxtype : function(e){
26463 return this.add(e);
26467 * Returns the Element for this toolbar.
26468 * @return {Roo.Element}
26470 getEl : function(){
26476 * @return {Roo.Toolbar.Item} The separator item
26478 addSeparator : function(){
26479 return this.addItem(new Roo.Toolbar.Separator());
26483 * Adds a spacer element
26484 * @return {Roo.Toolbar.Spacer} The spacer item
26486 addSpacer : function(){
26487 return this.addItem(new Roo.Toolbar.Spacer());
26491 * Adds a fill element that forces subsequent additions to the right side of the toolbar
26492 * @return {Roo.Toolbar.Fill} The fill item
26494 addFill : function(){
26495 return this.addItem(new Roo.Toolbar.Fill());
26499 * Adds any standard HTML element to the toolbar
26500 * @param {String/HTMLElement/Element} el The element or id of the element to add
26501 * @return {Roo.Toolbar.Item} The element's item
26503 addElement : function(el){
26504 return this.addItem(new Roo.Toolbar.Item(el));
26507 * Collection of items on the toolbar.. (only Toolbar Items, so use fields to retrieve fields)
26508 * @type Roo.util.MixedCollection
26513 * Adds any Toolbar.Item or subclass
26514 * @param {Roo.Toolbar.Item} item
26515 * @return {Roo.Toolbar.Item} The item
26517 addItem : function(item){
26518 var td = this.nextBlock();
26520 this.items.add(item);
26525 * Adds a button (or buttons). See {@link Roo.Toolbar.Button} for more info on the config.
26526 * @param {Object/Array} config A button config or array of configs
26527 * @return {Roo.Toolbar.Button/Array}
26529 addButton : function(config){
26530 if(config instanceof Array){
26532 for(var i = 0, len = config.length; i < len; i++) {
26533 buttons.push(this.addButton(config[i]));
26538 if(!(config instanceof Roo.Toolbar.Button)){
26540 new Roo.Toolbar.SplitButton(config) :
26541 new Roo.Toolbar.Button(config);
26543 var td = this.nextBlock();
26550 * Adds text to the toolbar
26551 * @param {String} text The text to add
26552 * @return {Roo.Toolbar.Item} The element's item
26554 addText : function(text){
26555 return this.addItem(new Roo.Toolbar.TextItem(text));
26559 * Inserts any {@link Roo.Toolbar.Item}/{@link Roo.Toolbar.Button} at the specified index.
26560 * @param {Number} index The index where the item is to be inserted
26561 * @param {Object/Roo.Toolbar.Item/Roo.Toolbar.Button (may be Array)} item The button, or button config object to be inserted.
26562 * @return {Roo.Toolbar.Button/Item}
26564 insertButton : function(index, item){
26565 if(item instanceof Array){
26567 for(var i = 0, len = item.length; i < len; i++) {
26568 buttons.push(this.insertButton(index + i, item[i]));
26572 if (!(item instanceof Roo.Toolbar.Button)){
26573 item = new Roo.Toolbar.Button(item);
26575 var td = document.createElement("td");
26576 this.tr.insertBefore(td, this.tr.childNodes[index]);
26578 this.items.insert(index, item);
26583 * Adds a new element to the toolbar from the passed {@link Roo.DomHelper} config.
26584 * @param {Object} config
26585 * @return {Roo.Toolbar.Item} The element's item
26587 addDom : function(config, returnEl){
26588 var td = this.nextBlock();
26589 Roo.DomHelper.overwrite(td, config);
26590 var ti = new Roo.Toolbar.Item(td.firstChild);
26592 this.items.add(ti);
26597 * Collection of fields on the toolbar.. usefull for quering (value is false if there are no fields)
26598 * @type Roo.util.MixedCollection
26603 * Adds a dynamically rendered Roo.form field (TextField, ComboBox, etc). Note: the field should not have
26604 * been rendered yet. For a field that has already been rendered, use {@link #addElement}.
26605 * @param {Roo.form.Field} field
26606 * @return {Roo.ToolbarItem}
26610 addField : function(field) {
26611 if (!this.fields) {
26613 this.fields = new Roo.util.MixedCollection(false, function(o){
26614 return o.id || ("item" + (++autoId));
26619 var td = this.nextBlock();
26621 var ti = new Roo.Toolbar.Item(td.firstChild);
26623 this.items.add(ti);
26624 this.fields.add(field);
26635 this.el.child('div').setVisibilityMode(Roo.Element.DISPLAY);
26636 this.el.child('div').hide();
26644 this.el.child('div').show();
26648 nextBlock : function(){
26649 var td = document.createElement("td");
26650 this.tr.appendChild(td);
26655 destroy : function(){
26656 if(this.items){ // rendered?
26657 Roo.destroy.apply(Roo, this.items.items);
26659 if(this.fields){ // rendered?
26660 Roo.destroy.apply(Roo, this.fields.items);
26662 Roo.Element.uncache(this.el, this.tr);
26667 * @class Roo.Toolbar.Item
26668 * The base class that other classes should extend in order to get some basic common toolbar item functionality.
26670 * Creates a new Item
26671 * @param {HTMLElement} el
26673 Roo.Toolbar.Item = function(el){
26674 this.el = Roo.getDom(el);
26675 this.id = Roo.id(this.el);
26676 this.hidden = false;
26679 Roo.Toolbar.Item.prototype = {
26682 * Get this item's HTML Element
26683 * @return {HTMLElement}
26685 getEl : function(){
26690 render : function(td){
26692 td.appendChild(this.el);
26696 * Removes and destroys this item.
26698 destroy : function(){
26699 this.td.parentNode.removeChild(this.td);
26706 this.hidden = false;
26707 this.td.style.display = "";
26714 this.hidden = true;
26715 this.td.style.display = "none";
26719 * Convenience function for boolean show/hide.
26720 * @param {Boolean} visible true to show/false to hide
26722 setVisible: function(visible){
26731 * Try to focus this item.
26733 focus : function(){
26734 Roo.fly(this.el).focus();
26738 * Disables this item.
26740 disable : function(){
26741 Roo.fly(this.td).addClass("x-item-disabled");
26742 this.disabled = true;
26743 this.el.disabled = true;
26747 * Enables this item.
26749 enable : function(){
26750 Roo.fly(this.td).removeClass("x-item-disabled");
26751 this.disabled = false;
26752 this.el.disabled = false;
26758 * @class Roo.Toolbar.Separator
26759 * @extends Roo.Toolbar.Item
26760 * A simple toolbar separator class
26762 * Creates a new Separator
26764 Roo.Toolbar.Separator = function(){
26765 var s = document.createElement("span");
26766 s.className = "ytb-sep";
26767 Roo.Toolbar.Separator.superclass.constructor.call(this, s);
26769 Roo.extend(Roo.Toolbar.Separator, Roo.Toolbar.Item, {
26770 enable:Roo.emptyFn,
26771 disable:Roo.emptyFn,
26776 * @class Roo.Toolbar.Spacer
26777 * @extends Roo.Toolbar.Item
26778 * A simple element that adds extra horizontal space to a toolbar.
26780 * Creates a new Spacer
26782 Roo.Toolbar.Spacer = function(){
26783 var s = document.createElement("div");
26784 s.className = "ytb-spacer";
26785 Roo.Toolbar.Spacer.superclass.constructor.call(this, s);
26787 Roo.extend(Roo.Toolbar.Spacer, Roo.Toolbar.Item, {
26788 enable:Roo.emptyFn,
26789 disable:Roo.emptyFn,
26794 * @class Roo.Toolbar.Fill
26795 * @extends Roo.Toolbar.Spacer
26796 * A simple element that adds a greedy (100% width) horizontal space to a toolbar.
26798 * Creates a new Spacer
26800 Roo.Toolbar.Fill = Roo.extend(Roo.Toolbar.Spacer, {
26802 render : function(td){
26803 td.style.width = '100%';
26804 Roo.Toolbar.Fill.superclass.render.call(this, td);
26809 * @class Roo.Toolbar.TextItem
26810 * @extends Roo.Toolbar.Item
26811 * A simple class that renders text directly into a toolbar.
26813 * Creates a new TextItem
26814 * @param {String} text
26816 Roo.Toolbar.TextItem = function(text){
26817 if (typeof(text) == 'object') {
26820 var s = document.createElement("span");
26821 s.className = "ytb-text";
26822 s.innerHTML = text;
26823 Roo.Toolbar.TextItem.superclass.constructor.call(this, s);
26825 Roo.extend(Roo.Toolbar.TextItem, Roo.Toolbar.Item, {
26826 enable:Roo.emptyFn,
26827 disable:Roo.emptyFn,
26832 * @class Roo.Toolbar.Button
26833 * @extends Roo.Button
26834 * A button that renders into a toolbar.
26836 * Creates a new Button
26837 * @param {Object} config A standard {@link Roo.Button} config object
26839 Roo.Toolbar.Button = function(config){
26840 Roo.Toolbar.Button.superclass.constructor.call(this, null, config);
26842 Roo.extend(Roo.Toolbar.Button, Roo.Button, {
26843 render : function(td){
26845 Roo.Toolbar.Button.superclass.render.call(this, td);
26849 * Removes and destroys this button
26851 destroy : function(){
26852 Roo.Toolbar.Button.superclass.destroy.call(this);
26853 this.td.parentNode.removeChild(this.td);
26857 * Shows this button
26860 this.hidden = false;
26861 this.td.style.display = "";
26865 * Hides this button
26868 this.hidden = true;
26869 this.td.style.display = "none";
26873 * Disables this item
26875 disable : function(){
26876 Roo.fly(this.td).addClass("x-item-disabled");
26877 this.disabled = true;
26881 * Enables this item
26883 enable : function(){
26884 Roo.fly(this.td).removeClass("x-item-disabled");
26885 this.disabled = false;
26888 // backwards compat
26889 Roo.ToolbarButton = Roo.Toolbar.Button;
26892 * @class Roo.Toolbar.SplitButton
26893 * @extends Roo.SplitButton
26894 * A menu button that renders into a toolbar.
26896 * Creates a new SplitButton
26897 * @param {Object} config A standard {@link Roo.SplitButton} config object
26899 Roo.Toolbar.SplitButton = function(config){
26900 Roo.Toolbar.SplitButton.superclass.constructor.call(this, null, config);
26902 Roo.extend(Roo.Toolbar.SplitButton, Roo.SplitButton, {
26903 render : function(td){
26905 Roo.Toolbar.SplitButton.superclass.render.call(this, td);
26909 * Removes and destroys this button
26911 destroy : function(){
26912 Roo.Toolbar.SplitButton.superclass.destroy.call(this);
26913 this.td.parentNode.removeChild(this.td);
26917 * Shows this button
26920 this.hidden = false;
26921 this.td.style.display = "";
26925 * Hides this button
26928 this.hidden = true;
26929 this.td.style.display = "none";
26933 // backwards compat
26934 Roo.Toolbar.MenuButton = Roo.Toolbar.SplitButton;/*
26936 * Ext JS Library 1.1.1
26937 * Copyright(c) 2006-2007, Ext JS, LLC.
26939 * Originally Released Under LGPL - original licence link has changed is not relivant.
26942 * <script type="text/javascript">
26946 * @class Roo.PagingToolbar
26947 * @extends Roo.Toolbar
26948 * A specialized toolbar that is bound to a {@link Roo.data.Store} and provides automatic paging controls.
26950 * Create a new PagingToolbar
26951 * @param {Object} config The config object
26953 Roo.PagingToolbar = function(el, ds, config)
26955 // old args format still supported... - xtype is prefered..
26956 if (typeof(el) == 'object' && el.xtype) {
26957 // created from xtype...
26959 ds = el.dataSource;
26960 el = config.container;
26964 Roo.PagingToolbar.superclass.constructor.call(this, el, null, config);
26967 this.renderButtons(this.el);
26971 Roo.extend(Roo.PagingToolbar, Roo.Toolbar, {
26973 * @cfg {Roo.data.Store} dataSource
26974 * The underlying data store providing the paged data
26977 * @cfg {String/HTMLElement/Element} container
26978 * container The id or element that will contain the toolbar
26981 * @cfg {Boolean} displayInfo
26982 * True to display the displayMsg (defaults to false)
26985 * @cfg {Number} pageSize
26986 * The number of records to display per page (defaults to 20)
26990 * @cfg {String} displayMsg
26991 * The paging status message to display (defaults to "Displaying {start} - {end} of {total}")
26993 displayMsg : 'Displaying {0} - {1} of {2}',
26995 * @cfg {String} emptyMsg
26996 * The message to display when no records are found (defaults to "No data to display")
26998 emptyMsg : 'No data to display',
27000 * Customizable piece of the default paging text (defaults to "Page")
27003 beforePageText : "Page",
27005 * Customizable piece of the default paging text (defaults to "of %0")
27008 afterPageText : "of {0}",
27010 * Customizable piece of the default paging text (defaults to "First Page")
27013 firstText : "First Page",
27015 * Customizable piece of the default paging text (defaults to "Previous Page")
27018 prevText : "Previous Page",
27020 * Customizable piece of the default paging text (defaults to "Next Page")
27023 nextText : "Next Page",
27025 * Customizable piece of the default paging text (defaults to "Last Page")
27028 lastText : "Last Page",
27030 * Customizable piece of the default paging text (defaults to "Refresh")
27033 refreshText : "Refresh",
27036 renderButtons : function(el){
27037 Roo.PagingToolbar.superclass.render.call(this, el);
27038 this.first = this.addButton({
27039 tooltip: this.firstText,
27040 cls: "x-btn-icon x-grid-page-first",
27042 handler: this.onClick.createDelegate(this, ["first"])
27044 this.prev = this.addButton({
27045 tooltip: this.prevText,
27046 cls: "x-btn-icon x-grid-page-prev",
27048 handler: this.onClick.createDelegate(this, ["prev"])
27050 this.addSeparator();
27051 this.add(this.beforePageText);
27052 this.field = Roo.get(this.addDom({
27057 cls: "x-grid-page-number"
27059 this.field.on("keydown", this.onPagingKeydown, this);
27060 this.field.on("focus", function(){this.dom.select();});
27061 this.afterTextEl = this.addText(String.format(this.afterPageText, 1));
27062 this.field.setHeight(18);
27063 this.addSeparator();
27064 this.next = this.addButton({
27065 tooltip: this.nextText,
27066 cls: "x-btn-icon x-grid-page-next",
27068 handler: this.onClick.createDelegate(this, ["next"])
27070 this.last = this.addButton({
27071 tooltip: this.lastText,
27072 cls: "x-btn-icon x-grid-page-last",
27074 handler: this.onClick.createDelegate(this, ["last"])
27076 this.addSeparator();
27077 this.loading = this.addButton({
27078 tooltip: this.refreshText,
27079 cls: "x-btn-icon x-grid-loading",
27080 handler: this.onClick.createDelegate(this, ["refresh"])
27083 if(this.displayInfo){
27084 this.displayEl = Roo.fly(this.el.dom.firstChild).createChild({cls:'x-paging-info'});
27089 updateInfo : function(){
27090 if(this.displayEl){
27091 var count = this.ds.getCount();
27092 var msg = count == 0 ?
27096 this.cursor+1, this.cursor+count, this.ds.getTotalCount()
27098 this.displayEl.update(msg);
27103 onLoad : function(ds, r, o){
27104 this.cursor = o.params ? o.params.start : 0;
27105 var d = this.getPageData(), ap = d.activePage, ps = d.pages;
27107 this.afterTextEl.el.innerHTML = String.format(this.afterPageText, d.pages);
27108 this.field.dom.value = ap;
27109 this.first.setDisabled(ap == 1);
27110 this.prev.setDisabled(ap == 1);
27111 this.next.setDisabled(ap == ps);
27112 this.last.setDisabled(ap == ps);
27113 this.loading.enable();
27118 getPageData : function(){
27119 var total = this.ds.getTotalCount();
27122 activePage : Math.ceil((this.cursor+this.pageSize)/this.pageSize),
27123 pages : total < this.pageSize ? 1 : Math.ceil(total/this.pageSize)
27128 onLoadError : function(){
27129 this.loading.enable();
27133 onPagingKeydown : function(e){
27134 var k = e.getKey();
27135 var d = this.getPageData();
27137 var v = this.field.dom.value, pageNum;
27138 if(!v || isNaN(pageNum = parseInt(v, 10))){
27139 this.field.dom.value = d.activePage;
27142 pageNum = Math.min(Math.max(1, pageNum), d.pages) - 1;
27143 this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
27146 else if(k == e.HOME || (k == e.UP && e.ctrlKey) || (k == e.PAGEUP && e.ctrlKey) || (k == e.RIGHT && e.ctrlKey) || k == e.END || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey))
27148 var pageNum = (k == e.HOME || (k == e.DOWN && e.ctrlKey) || (k == e.LEFT && e.ctrlKey) || (k == e.PAGEDOWN && e.ctrlKey)) ? 1 : d.pages;
27149 this.field.dom.value = pageNum;
27150 this.ds.load({params:{start: (pageNum - 1) * this.pageSize, limit: this.pageSize}});
27153 else if(k == e.UP || k == e.RIGHT || k == e.PAGEUP || k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
27155 var v = this.field.dom.value, pageNum;
27156 var increment = (e.shiftKey) ? 10 : 1;
27157 if(k == e.DOWN || k == e.LEFT || k == e.PAGEDOWN)
27159 if(!v || isNaN(pageNum = parseInt(v, 10))) {
27160 this.field.dom.value = d.activePage;
27163 else if(parseInt(v, 10) + increment >= 1 & parseInt(v, 10) + increment <= d.pages)
27165 this.field.dom.value = parseInt(v, 10) + increment;
27166 pageNum = Math.min(Math.max(1, pageNum + increment), d.pages) - 1;
27167 this.ds.load({params:{start: pageNum * this.pageSize, limit: this.pageSize}});
27174 beforeLoad : function(){
27176 this.loading.disable();
27181 onClick : function(which){
27185 ds.load({params:{start: 0, limit: this.pageSize}});
27188 ds.load({params:{start: Math.max(0, this.cursor-this.pageSize), limit: this.pageSize}});
27191 ds.load({params:{start: this.cursor+this.pageSize, limit: this.pageSize}});
27194 var total = ds.getTotalCount();
27195 var extra = total % this.pageSize;
27196 var lastStart = extra ? (total - extra) : total-this.pageSize;
27197 ds.load({params:{start: lastStart, limit: this.pageSize}});
27200 ds.load({params:{start: this.cursor, limit: this.pageSize}});
27206 * Unbinds the paging toolbar from the specified {@link Roo.data.Store}
27207 * @param {Roo.data.Store} store The data store to unbind
27209 unbind : function(ds){
27210 ds.un("beforeload", this.beforeLoad, this);
27211 ds.un("load", this.onLoad, this);
27212 ds.un("loadexception", this.onLoadError, this);
27213 ds.un("remove", this.updateInfo, this);
27214 ds.un("add", this.updateInfo, this);
27215 this.ds = undefined;
27219 * Binds the paging toolbar to the specified {@link Roo.data.Store}
27220 * @param {Roo.data.Store} store The data store to bind
27222 bind : function(ds){
27223 ds.on("beforeload", this.beforeLoad, this);
27224 ds.on("load", this.onLoad, this);
27225 ds.on("loadexception", this.onLoadError, this);
27226 ds.on("remove", this.updateInfo, this);
27227 ds.on("add", this.updateInfo, this);
27232 * Ext JS Library 1.1.1
27233 * Copyright(c) 2006-2007, Ext JS, LLC.
27235 * Originally Released Under LGPL - original licence link has changed is not relivant.
27238 * <script type="text/javascript">
27242 * @class Roo.Resizable
27243 * @extends Roo.util.Observable
27244 * <p>Applies drag handles to an element to make it resizable. The drag handles are inserted into the element
27245 * and positioned absolute. Some elements, such as a textarea or image, don't support this. To overcome that, you can wrap
27246 * the textarea in a div and set "resizeChild" to true (or to the id of the element), <b>or</b> set wrap:true in your config and
27247 * the element will be wrapped for you automatically.</p>
27248 * <p>Here is the list of valid resize handles:</p>
27251 ------ -------------------
27262 * <p>Here's an example showing the creation of a typical Resizable:</p>
27264 var resizer = new Roo.Resizable("element-id", {
27272 resizer.on("resize", myHandler);
27274 * <p>To hide a particular handle, set its display to none in CSS, or through script:<br>
27275 * resizer.east.setDisplayed(false);</p>
27276 * @cfg {Boolean/String/Element} resizeChild True to resize the first child, or id/element to resize (defaults to false)
27277 * @cfg {Array/String} adjustments String "auto" or an array [width, height] with values to be <b>added</b> to the
27278 * resize operation's new size (defaults to [0, 0])
27279 * @cfg {Number} minWidth The minimum width for the element (defaults to 5)
27280 * @cfg {Number} minHeight The minimum height for the element (defaults to 5)
27281 * @cfg {Number} maxWidth The maximum width for the element (defaults to 10000)
27282 * @cfg {Number} maxHeight The maximum height for the element (defaults to 10000)
27283 * @cfg {Boolean} enabled False to disable resizing (defaults to true)
27284 * @cfg {Boolean} wrap True to wrap an element with a div if needed (required for textareas and images, defaults to false)
27285 * @cfg {Number} width The width of the element in pixels (defaults to null)
27286 * @cfg {Number} height The height of the element in pixels (defaults to null)
27287 * @cfg {Boolean} animate True to animate the resize (not compatible with dynamic sizing, defaults to false)
27288 * @cfg {Number} duration Animation duration if animate = true (defaults to .35)
27289 * @cfg {Boolean} dynamic True to resize the element while dragging instead of using a proxy (defaults to false)
27290 * @cfg {String} handles String consisting of the resize handles to display (defaults to undefined)
27291 * @cfg {Boolean} multiDirectional <b>Deprecated</b>. The old style of adding multi-direction resize handles, deprecated
27292 * in favor of the handles config option (defaults to false)
27293 * @cfg {Boolean} disableTrackOver True to disable mouse tracking. This is only applied at config time. (defaults to false)
27294 * @cfg {String} easing Animation easing if animate = true (defaults to 'easingOutStrong')
27295 * @cfg {Number} widthIncrement The increment to snap the width resize in pixels (dynamic must be true, defaults to 0)
27296 * @cfg {Number} heightIncrement The increment to snap the height resize in pixels (dynamic must be true, defaults to 0)
27297 * @cfg {Boolean} pinned True to ensure that the resize handles are always visible, false to display them only when the
27298 * user mouses over the resizable borders. This is only applied at config time. (defaults to false)
27299 * @cfg {Boolean} preserveRatio True to preserve the original ratio between height and width during resize (defaults to false)
27300 * @cfg {Boolean} transparent True for transparent handles. This is only applied at config time. (defaults to false)
27301 * @cfg {Number} minX The minimum allowed page X for the element (only used for west resizing, defaults to 0)
27302 * @cfg {Number} minY The minimum allowed page Y for the element (only used for north resizing, defaults to 0)
27303 * @cfg {Boolean} draggable Convenience to initialize drag drop (defaults to false)
27305 * Create a new resizable component
27306 * @param {String/HTMLElement/Roo.Element} el The id or element to resize
27307 * @param {Object} config configuration options
27309 Roo.Resizable = function(el, config){
27310 this.el = Roo.get(el);
27312 if(config && config.wrap){
27313 config.resizeChild = this.el;
27314 this.el = this.el.wrap(typeof config.wrap == "object" ? config.wrap : {cls:"xresizable-wrap"});
27315 this.el.id = this.el.dom.id = config.resizeChild.id + "-rzwrap";
27316 this.el.setStyle("overflow", "hidden");
27317 this.el.setPositioning(config.resizeChild.getPositioning());
27318 config.resizeChild.clearPositioning();
27319 if(!config.width || !config.height){
27320 var csize = config.resizeChild.getSize();
27321 this.el.setSize(csize.width, csize.height);
27323 if(config.pinned && !config.adjustments){
27324 config.adjustments = "auto";
27328 this.proxy = this.el.createProxy({tag: "div", cls: "x-resizable-proxy", id: this.el.id + "-rzproxy"});
27329 this.proxy.unselectable();
27330 this.proxy.enableDisplayMode('block');
27332 Roo.apply(this, config);
27335 this.disableTrackOver = true;
27336 this.el.addClass("x-resizable-pinned");
27338 // if the element isn't positioned, make it relative
27339 var position = this.el.getStyle("position");
27340 if(position != "absolute" && position != "fixed"){
27341 this.el.setStyle("position", "relative");
27343 if(!this.handles){ // no handles passed, must be legacy style
27344 this.handles = 's,e,se';
27345 if(this.multiDirectional){
27346 this.handles += ',n,w';
27349 if(this.handles == "all"){
27350 this.handles = "n s e w ne nw se sw";
27352 var hs = this.handles.split(/\s*?[,;]\s*?| /);
27353 var ps = Roo.Resizable.positions;
27354 for(var i = 0, len = hs.length; i < len; i++){
27355 if(hs[i] && ps[hs[i]]){
27356 var pos = ps[hs[i]];
27357 this[pos] = new Roo.Resizable.Handle(this, pos, this.disableTrackOver, this.transparent);
27361 this.corner = this.southeast;
27363 if(this.handles.indexOf("n") != -1 || this.handles.indexOf("w") != -1){
27364 this.updateBox = true;
27367 this.activeHandle = null;
27369 if(this.resizeChild){
27370 if(typeof this.resizeChild == "boolean"){
27371 this.resizeChild = Roo.get(this.el.dom.firstChild, true);
27373 this.resizeChild = Roo.get(this.resizeChild, true);
27377 if(this.adjustments == "auto"){
27378 var rc = this.resizeChild;
27379 var hw = this.west, he = this.east, hn = this.north, hs = this.south;
27380 if(rc && (hw || hn)){
27381 rc.position("relative");
27382 rc.setLeft(hw ? hw.el.getWidth() : 0);
27383 rc.setTop(hn ? hn.el.getHeight() : 0);
27385 this.adjustments = [
27386 (he ? -he.el.getWidth() : 0) + (hw ? -hw.el.getWidth() : 0),
27387 (hn ? -hn.el.getHeight() : 0) + (hs ? -hs.el.getHeight() : 0) -1
27391 if(this.draggable){
27392 this.dd = this.dynamic ?
27393 this.el.initDD(null) : this.el.initDDProxy(null, {dragElId: this.proxy.id});
27394 this.dd.setHandleElId(this.resizeChild ? this.resizeChild.id : this.el.id);
27400 * @event beforeresize
27401 * Fired before resize is allowed. Set enabled to false to cancel resize.
27402 * @param {Roo.Resizable} this
27403 * @param {Roo.EventObject} e The mousedown event
27405 "beforeresize" : true,
27408 * Fired after a resize.
27409 * @param {Roo.Resizable} this
27410 * @param {Number} width The new width
27411 * @param {Number} height The new height
27412 * @param {Roo.EventObject} e The mouseup event
27417 if(this.width !== null && this.height !== null){
27418 this.resizeTo(this.width, this.height);
27420 this.updateChildSize();
27423 this.el.dom.style.zoom = 1;
27425 Roo.Resizable.superclass.constructor.call(this);
27428 Roo.extend(Roo.Resizable, Roo.util.Observable, {
27429 resizeChild : false,
27430 adjustments : [0, 0],
27440 multiDirectional : false,
27441 disableTrackOver : false,
27442 easing : 'easeOutStrong',
27443 widthIncrement : 0,
27444 heightIncrement : 0,
27448 preserveRatio : false,
27449 transparent: false,
27455 * @cfg {String/HTMLElement/Element} constrainTo Constrain the resize to a particular element
27457 constrainTo: undefined,
27459 * @cfg {Roo.lib.Region} resizeRegion Constrain the resize to a particular region
27461 resizeRegion: undefined,
27465 * Perform a manual resize
27466 * @param {Number} width
27467 * @param {Number} height
27469 resizeTo : function(width, height){
27470 this.el.setSize(width, height);
27471 this.updateChildSize();
27472 this.fireEvent("resize", this, width, height, null);
27476 startSizing : function(e, handle){
27477 this.fireEvent("beforeresize", this, e);
27478 if(this.enabled){ // 2nd enabled check in case disabled before beforeresize handler
27481 this.overlay = this.el.createProxy({tag: "div", cls: "x-resizable-overlay", html: " "});
27482 this.overlay.unselectable();
27483 this.overlay.enableDisplayMode("block");
27484 this.overlay.on("mousemove", this.onMouseMove, this);
27485 this.overlay.on("mouseup", this.onMouseUp, this);
27487 this.overlay.setStyle("cursor", handle.el.getStyle("cursor"));
27489 this.resizing = true;
27490 this.startBox = this.el.getBox();
27491 this.startPoint = e.getXY();
27492 this.offsets = [(this.startBox.x + this.startBox.width) - this.startPoint[0],
27493 (this.startBox.y + this.startBox.height) - this.startPoint[1]];
27495 this.overlay.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
27496 this.overlay.show();
27498 if(this.constrainTo) {
27499 var ct = Roo.get(this.constrainTo);
27500 this.resizeRegion = ct.getRegion().adjust(
27501 ct.getFrameWidth('t'),
27502 ct.getFrameWidth('l'),
27503 -ct.getFrameWidth('b'),
27504 -ct.getFrameWidth('r')
27508 this.proxy.setStyle('visibility', 'hidden'); // workaround display none
27510 this.proxy.setBox(this.startBox);
27512 this.proxy.setStyle('visibility', 'visible');
27518 onMouseDown : function(handle, e){
27521 this.activeHandle = handle;
27522 this.startSizing(e, handle);
27527 onMouseUp : function(e){
27528 var size = this.resizeElement();
27529 this.resizing = false;
27531 this.overlay.hide();
27533 this.fireEvent("resize", this, size.width, size.height, e);
27537 updateChildSize : function(){
27538 if(this.resizeChild){
27540 var child = this.resizeChild;
27541 var adj = this.adjustments;
27542 if(el.dom.offsetWidth){
27543 var b = el.getSize(true);
27544 child.setSize(b.width+adj[0], b.height+adj[1]);
27546 // Second call here for IE
27547 // The first call enables instant resizing and
27548 // the second call corrects scroll bars if they
27551 setTimeout(function(){
27552 if(el.dom.offsetWidth){
27553 var b = el.getSize(true);
27554 child.setSize(b.width+adj[0], b.height+adj[1]);
27562 snap : function(value, inc, min){
27563 if(!inc || !value) return value;
27564 var newValue = value;
27565 var m = value % inc;
27568 newValue = value + (inc-m);
27570 newValue = value - m;
27573 return Math.max(min, newValue);
27577 resizeElement : function(){
27578 var box = this.proxy.getBox();
27579 if(this.updateBox){
27580 this.el.setBox(box, false, this.animate, this.duration, null, this.easing);
27582 this.el.setSize(box.width, box.height, this.animate, this.duration, null, this.easing);
27584 this.updateChildSize();
27592 constrain : function(v, diff, m, mx){
27595 }else if(v - diff > mx){
27602 onMouseMove : function(e){
27604 try{// try catch so if something goes wrong the user doesn't get hung
27606 if(this.resizeRegion && !this.resizeRegion.contains(e.getPoint())) {
27610 //var curXY = this.startPoint;
27611 var curSize = this.curSize || this.startBox;
27612 var x = this.startBox.x, y = this.startBox.y;
27613 var ox = x, oy = y;
27614 var w = curSize.width, h = curSize.height;
27615 var ow = w, oh = h;
27616 var mw = this.minWidth, mh = this.minHeight;
27617 var mxw = this.maxWidth, mxh = this.maxHeight;
27618 var wi = this.widthIncrement;
27619 var hi = this.heightIncrement;
27621 var eventXY = e.getXY();
27622 var diffX = -(this.startPoint[0] - Math.max(this.minX, eventXY[0]));
27623 var diffY = -(this.startPoint[1] - Math.max(this.minY, eventXY[1]));
27625 var pos = this.activeHandle.position;
27630 w = Math.min(Math.max(mw, w), mxw);
27634 h = Math.min(Math.max(mh, h), mxh);
27639 w = Math.min(Math.max(mw, w), mxw);
27640 h = Math.min(Math.max(mh, h), mxh);
27643 diffY = this.constrain(h, diffY, mh, mxh);
27648 diffX = this.constrain(w, diffX, mw, mxw);
27654 w = Math.min(Math.max(mw, w), mxw);
27655 diffY = this.constrain(h, diffY, mh, mxh);
27660 diffX = this.constrain(w, diffX, mw, mxw);
27661 diffY = this.constrain(h, diffY, mh, mxh);
27668 diffX = this.constrain(w, diffX, mw, mxw);
27670 h = Math.min(Math.max(mh, h), mxh);
27676 var sw = this.snap(w, wi, mw);
27677 var sh = this.snap(h, hi, mh);
27678 if(sw != w || sh != h){
27701 if(this.preserveRatio){
27706 h = Math.min(Math.max(mh, h), mxh);
27711 w = Math.min(Math.max(mw, w), mxw);
27716 w = Math.min(Math.max(mw, w), mxw);
27722 w = Math.min(Math.max(mw, w), mxw);
27728 h = Math.min(Math.max(mh, h), mxh);
27736 h = Math.min(Math.max(mh, h), mxh);
27746 h = Math.min(Math.max(mh, h), mxh);
27754 this.proxy.setBounds(x, y, w, h);
27756 this.resizeElement();
27763 handleOver : function(){
27765 this.el.addClass("x-resizable-over");
27770 handleOut : function(){
27771 if(!this.resizing){
27772 this.el.removeClass("x-resizable-over");
27777 * Returns the element this component is bound to.
27778 * @return {Roo.Element}
27780 getEl : function(){
27785 * Returns the resizeChild element (or null).
27786 * @return {Roo.Element}
27788 getResizeChild : function(){
27789 return this.resizeChild;
27793 * Destroys this resizable. If the element was wrapped and
27794 * removeEl is not true then the element remains.
27795 * @param {Boolean} removeEl (optional) true to remove the element from the DOM
27797 destroy : function(removeEl){
27798 this.proxy.remove();
27800 this.overlay.removeAllListeners();
27801 this.overlay.remove();
27803 var ps = Roo.Resizable.positions;
27805 if(typeof ps[k] != "function" && this[ps[k]]){
27806 var h = this[ps[k]];
27807 h.el.removeAllListeners();
27812 this.el.update("");
27819 // hash to map config positions to true positions
27820 Roo.Resizable.positions = {
27821 n: "north", s: "south", e: "east", w: "west", se: "southeast", sw: "southwest", nw: "northwest", ne: "northeast"
27825 Roo.Resizable.Handle = function(rz, pos, disableTrackOver, transparent){
27827 // only initialize the template if resizable is used
27828 var tpl = Roo.DomHelper.createTemplate(
27829 {tag: "div", cls: "x-resizable-handle x-resizable-handle-{0}"}
27832 Roo.Resizable.Handle.prototype.tpl = tpl;
27834 this.position = pos;
27836 this.el = this.tpl.append(rz.el.dom, [this.position], true);
27837 this.el.unselectable();
27839 this.el.setOpacity(0);
27841 this.el.on("mousedown", this.onMouseDown, this);
27842 if(!disableTrackOver){
27843 this.el.on("mouseover", this.onMouseOver, this);
27844 this.el.on("mouseout", this.onMouseOut, this);
27849 Roo.Resizable.Handle.prototype = {
27850 afterResize : function(rz){
27854 onMouseDown : function(e){
27855 this.rz.onMouseDown(this, e);
27858 onMouseOver : function(e){
27859 this.rz.handleOver(this, e);
27862 onMouseOut : function(e){
27863 this.rz.handleOut(this, e);
27867 * Ext JS Library 1.1.1
27868 * Copyright(c) 2006-2007, Ext JS, LLC.
27870 * Originally Released Under LGPL - original licence link has changed is not relivant.
27873 * <script type="text/javascript">
27877 * @class Roo.Editor
27878 * @extends Roo.Component
27879 * A base editor field that handles displaying/hiding on demand and has some built-in sizing and event handling logic.
27881 * Create a new Editor
27882 * @param {Roo.form.Field} field The Field object (or descendant)
27883 * @param {Object} config The config object
27885 Roo.Editor = function(field, config){
27886 Roo.Editor.superclass.constructor.call(this, config);
27887 this.field = field;
27890 * @event beforestartedit
27891 * Fires when editing is initiated, but before the value changes. Editing can be canceled by returning
27892 * false from the handler of this event.
27893 * @param {Editor} this
27894 * @param {Roo.Element} boundEl The underlying element bound to this editor
27895 * @param {Mixed} value The field value being set
27897 "beforestartedit" : true,
27900 * Fires when this editor is displayed
27901 * @param {Roo.Element} boundEl The underlying element bound to this editor
27902 * @param {Mixed} value The starting field value
27904 "startedit" : true,
27906 * @event beforecomplete
27907 * Fires after a change has been made to the field, but before the change is reflected in the underlying
27908 * field. Saving the change to the field can be canceled by returning false from the handler of this event.
27909 * Note that if the value has not changed and ignoreNoChange = true, the editing will still end but this
27910 * event will not fire since no edit actually occurred.
27911 * @param {Editor} this
27912 * @param {Mixed} value The current field value
27913 * @param {Mixed} startValue The original field value
27915 "beforecomplete" : true,
27918 * Fires after editing is complete and any changed value has been written to the underlying field.
27919 * @param {Editor} this
27920 * @param {Mixed} value The current field value
27921 * @param {Mixed} startValue The original field value
27925 * @event specialkey
27926 * Fires when any key related to navigation (arrows, tab, enter, esc, etc.) is pressed. You can check
27927 * {@link Roo.EventObject#getKey} to determine which key was pressed.
27928 * @param {Roo.form.Field} this
27929 * @param {Roo.EventObject} e The event object
27931 "specialkey" : true
27935 Roo.extend(Roo.Editor, Roo.Component, {
27937 * @cfg {Boolean/String} autosize
27938 * True for the editor to automatically adopt the size of the underlying field, "width" to adopt the width only,
27939 * or "height" to adopt the height only (defaults to false)
27942 * @cfg {Boolean} revertInvalid
27943 * True to automatically revert the field value and cancel the edit when the user completes an edit and the field
27944 * validation fails (defaults to true)
27947 * @cfg {Boolean} ignoreNoChange
27948 * True to skip the the edit completion process (no save, no events fired) if the user completes an edit and
27949 * the value has not changed (defaults to false). Applies only to string values - edits for other data types
27950 * will never be ignored.
27953 * @cfg {Boolean} hideEl
27954 * False to keep the bound element visible while the editor is displayed (defaults to true)
27957 * @cfg {Mixed} value
27958 * The data value of the underlying field (defaults to "")
27962 * @cfg {String} alignment
27963 * The position to align to (see {@link Roo.Element#alignTo} for more details, defaults to "c-c?").
27967 * @cfg {Boolean/String} shadow "sides" for sides/bottom only, "frame" for 4-way shadow, and "drop"
27968 * for bottom-right shadow (defaults to "frame")
27972 * @cfg {Boolean} constrain True to constrain the editor to the viewport
27976 * @cfg {Boolean} completeOnEnter True to complete the edit when the enter key is pressed (defaults to false)
27978 completeOnEnter : false,
27980 * @cfg {Boolean} cancelOnEsc True to cancel the edit when the escape key is pressed (defaults to false)
27982 cancelOnEsc : false,
27984 * @cfg {Boolean} updateEl True to update the innerHTML of the bound element when the update completes (defaults to false)
27989 onRender : function(ct, position){
27990 this.el = new Roo.Layer({
27991 shadow: this.shadow,
27997 constrain: this.constrain
27999 this.el.setStyle("overflow", Roo.isGecko ? "auto" : "hidden");
28000 if(this.field.msgTarget != 'title'){
28001 this.field.msgTarget = 'qtip';
28003 this.field.render(this.el);
28005 this.field.el.dom.setAttribute('autocomplete', 'off');
28007 this.field.on("specialkey", this.onSpecialKey, this);
28008 if(this.swallowKeys){
28009 this.field.el.swallowEvent(['keydown','keypress']);
28012 this.field.on("blur", this.onBlur, this);
28013 if(this.field.grow){
28014 this.field.on("autosize", this.el.sync, this.el, {delay:1});
28018 onSpecialKey : function(field, e){
28019 if(this.completeOnEnter && e.getKey() == e.ENTER){
28021 this.completeEdit();
28022 }else if(this.cancelOnEsc && e.getKey() == e.ESC){
28025 this.fireEvent('specialkey', field, e);
28030 * Starts the editing process and shows the editor.
28031 * @param {String/HTMLElement/Element} el The element to edit
28032 * @param {String} value (optional) A value to initialize the editor with. If a value is not provided, it defaults
28033 * to the innerHTML of el.
28035 startEdit : function(el, value){
28037 this.completeEdit();
28039 this.boundEl = Roo.get(el);
28040 var v = value !== undefined ? value : this.boundEl.dom.innerHTML;
28041 if(!this.rendered){
28042 this.render(this.parentEl || document.body);
28044 if(this.fireEvent("beforestartedit", this, this.boundEl, v) === false){
28047 this.startValue = v;
28048 this.field.setValue(v);
28050 var sz = this.boundEl.getSize();
28051 switch(this.autoSize){
28053 this.setSize(sz.width, "");
28056 this.setSize("", sz.height);
28059 this.setSize(sz.width, sz.height);
28062 this.el.alignTo(this.boundEl, this.alignment);
28063 this.editing = true;
28065 Roo.QuickTips.disable();
28071 * Sets the height and width of this editor.
28072 * @param {Number} width The new width
28073 * @param {Number} height The new height
28075 setSize : function(w, h){
28076 this.field.setSize(w, h);
28083 * Realigns the editor to the bound field based on the current alignment config value.
28085 realign : function(){
28086 this.el.alignTo(this.boundEl, this.alignment);
28090 * Ends the editing process, persists the changed value to the underlying field, and hides the editor.
28091 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after edit (defaults to false)
28093 completeEdit : function(remainVisible){
28097 var v = this.getValue();
28098 if(this.revertInvalid !== false && !this.field.isValid()){
28099 v = this.startValue;
28100 this.cancelEdit(true);
28102 if(String(v) === String(this.startValue) && this.ignoreNoChange){
28103 this.editing = false;
28107 if(this.fireEvent("beforecomplete", this, v, this.startValue) !== false){
28108 this.editing = false;
28109 if(this.updateEl && this.boundEl){
28110 this.boundEl.update(v);
28112 if(remainVisible !== true){
28115 this.fireEvent("complete", this, v, this.startValue);
28120 onShow : function(){
28122 if(this.hideEl !== false){
28123 this.boundEl.hide();
28126 if(Roo.isIE && !this.fixIEFocus){ // IE has problems with focusing the first time
28127 this.fixIEFocus = true;
28128 this.deferredFocus.defer(50, this);
28130 this.field.focus();
28132 this.fireEvent("startedit", this.boundEl, this.startValue);
28135 deferredFocus : function(){
28137 this.field.focus();
28142 * Cancels the editing process and hides the editor without persisting any changes. The field value will be
28143 * reverted to the original starting value.
28144 * @param {Boolean} remainVisible Override the default behavior and keep the editor visible after
28145 * cancel (defaults to false)
28147 cancelEdit : function(remainVisible){
28149 this.setValue(this.startValue);
28150 if(remainVisible !== true){
28157 onBlur : function(){
28158 if(this.allowBlur !== true && this.editing){
28159 this.completeEdit();
28164 onHide : function(){
28166 this.completeEdit();
28170 if(this.field.collapse){
28171 this.field.collapse();
28174 if(this.hideEl !== false){
28175 this.boundEl.show();
28178 Roo.QuickTips.enable();
28183 * Sets the data value of the editor
28184 * @param {Mixed} value Any valid value supported by the underlying field
28186 setValue : function(v){
28187 this.field.setValue(v);
28191 * Gets the data value of the editor
28192 * @return {Mixed} The data value
28194 getValue : function(){
28195 return this.field.getValue();
28199 * Ext JS Library 1.1.1
28200 * Copyright(c) 2006-2007, Ext JS, LLC.
28202 * Originally Released Under LGPL - original licence link has changed is not relivant.
28205 * <script type="text/javascript">
28209 * @class Roo.BasicDialog
28210 * @extends Roo.util.Observable
28211 * Lightweight Dialog Class. The code below shows the creation of a typical dialog using existing HTML markup:
28213 var dlg = new Roo.BasicDialog("my-dlg", {
28222 dlg.addKeyListener(27, dlg.hide, dlg); // ESC can also close the dialog
28223 dlg.addButton('OK', dlg.hide, dlg); // Could call a save function instead of hiding
28224 dlg.addButton('Cancel', dlg.hide, dlg);
28227 <b>A Dialog should always be a direct child of the body element.</b>
28228 * @cfg {Boolean/DomHelper} autoCreate True to auto create from scratch, or using a DomHelper Object (defaults to false)
28229 * @cfg {String} title Default text to display in the title bar (defaults to null)
28230 * @cfg {Number} width Width of the dialog in pixels (can also be set via CSS). Determined by browser if unspecified.
28231 * @cfg {Number} height Height of the dialog in pixels (can also be set via CSS). Determined by browser if unspecified.
28232 * @cfg {Number} x The default left page coordinate of the dialog (defaults to center screen)
28233 * @cfg {Number} y The default top page coordinate of the dialog (defaults to center screen)
28234 * @cfg {String/Element} animateTarget Id or element from which the dialog should animate while opening
28235 * (defaults to null with no animation)
28236 * @cfg {Boolean} resizable False to disable manual dialog resizing (defaults to true)
28237 * @cfg {String} resizeHandles Which resize handles to display - see the {@link Roo.Resizable} handles config
28238 * property for valid values (defaults to 'all')
28239 * @cfg {Number} minHeight The minimum allowable height for a resizable dialog (defaults to 80)
28240 * @cfg {Number} minWidth The minimum allowable width for a resizable dialog (defaults to 200)
28241 * @cfg {Boolean} modal True to show the dialog modally, preventing user interaction with the rest of the page (defaults to false)
28242 * @cfg {Boolean} autoScroll True to allow the dialog body contents to overflow and display scrollbars (defaults to false)
28243 * @cfg {Boolean} closable False to remove the built-in top-right corner close button (defaults to true)
28244 * @cfg {Boolean} collapsible False to remove the built-in top-right corner collapse button (defaults to true)
28245 * @cfg {Boolean} constraintoviewport True to keep the dialog constrained within the visible viewport boundaries (defaults to true)
28246 * @cfg {Boolean} syncHeightBeforeShow True to cause the dimensions to be recalculated before the dialog is shown (defaults to false)
28247 * @cfg {Boolean} draggable False to disable dragging of the dialog within the viewport (defaults to true)
28248 * @cfg {Boolean} autoTabs If true, all elements with class 'x-dlg-tab' will get automatically converted to tabs (defaults to false)
28249 * @cfg {String} tabTag The tag name of tab elements, used when autoTabs = true (defaults to 'div')
28250 * @cfg {Boolean} proxyDrag True to drag a lightweight proxy element rather than the dialog itself, used when
28251 * draggable = true (defaults to false)
28252 * @cfg {Boolean} fixedcenter True to ensure that anytime the dialog is shown or resized it gets centered (defaults to false)
28253 * @cfg {Boolean/String} shadow True or "sides" for the default effect, "frame" for 4-way shadow, and "drop" for bottom-right
28254 * shadow (defaults to false)
28255 * @cfg {Number} shadowOffset The number of pixels to offset the shadow if displayed (defaults to 5)
28256 * @cfg {String} buttonAlign Valid values are "left," "center" and "right" (defaults to "right")
28257 * @cfg {Number} minButtonWidth Minimum width of all dialog buttons (defaults to 75)
28258 * @cfg {Array} buttons Array of buttons
28259 * @cfg {Boolean} shim True to create an iframe shim that prevents selects from showing through (defaults to false)
28261 * Create a new BasicDialog.
28262 * @param {String/HTMLElement/Roo.Element} el The container element or DOM node, or its id
28263 * @param {Object} config Configuration options
28265 Roo.BasicDialog = function(el, config){
28266 this.el = Roo.get(el);
28267 var dh = Roo.DomHelper;
28268 if(!this.el && config && config.autoCreate){
28269 if(typeof config.autoCreate == "object"){
28270 if(!config.autoCreate.id){
28271 config.autoCreate.id = el;
28273 this.el = dh.append(document.body,
28274 config.autoCreate, true);
28276 this.el = dh.append(document.body,
28277 {tag: "div", id: el, style:'visibility:hidden;'}, true);
28281 el.setDisplayed(true);
28282 el.hide = this.hideAction;
28284 el.addClass("x-dlg");
28286 Roo.apply(this, config);
28288 this.proxy = el.createProxy("x-dlg-proxy");
28289 this.proxy.hide = this.hideAction;
28290 this.proxy.setOpacity(.5);
28294 el.setWidth(config.width);
28297 el.setHeight(config.height);
28299 this.size = el.getSize();
28300 if(typeof config.x != "undefined" && typeof config.y != "undefined"){
28301 this.xy = [config.x,config.y];
28303 this.xy = el.getCenterXY(true);
28305 /** The header element @type Roo.Element */
28306 this.header = el.child("> .x-dlg-hd");
28307 /** The body element @type Roo.Element */
28308 this.body = el.child("> .x-dlg-bd");
28309 /** The footer element @type Roo.Element */
28310 this.footer = el.child("> .x-dlg-ft");
28313 this.header = el.createChild({tag: "div", cls:"x-dlg-hd", html: " "}, this.body ? this.body.dom : null);
28316 this.body = el.createChild({tag: "div", cls:"x-dlg-bd"});
28319 this.header.unselectable();
28321 this.header.update(this.title);
28323 // this element allows the dialog to be focused for keyboard event
28324 this.focusEl = el.createChild({tag: "a", href:"#", cls:"x-dlg-focus", tabIndex:"-1"});
28325 this.focusEl.swallowEvent("click", true);
28327 this.header.wrap({cls:"x-dlg-hd-right"}).wrap({cls:"x-dlg-hd-left"}, true);
28329 // wrap the body and footer for special rendering
28330 this.bwrap = this.body.wrap({tag: "div", cls:"x-dlg-dlg-body"});
28332 this.bwrap.dom.appendChild(this.footer.dom);
28335 this.bg = this.el.createChild({
28336 tag: "div", cls:"x-dlg-bg",
28337 html: '<div class="x-dlg-bg-left"><div class="x-dlg-bg-right"><div class="x-dlg-bg-center"> </div></div></div>'
28339 this.centerBg = this.bg.child("div.x-dlg-bg-center");
28342 if(this.autoScroll !== false && !this.autoTabs){
28343 this.body.setStyle("overflow", "auto");
28346 this.toolbox = this.el.createChild({cls: "x-dlg-toolbox"});
28348 if(this.closable !== false){
28349 this.el.addClass("x-dlg-closable");
28350 this.close = this.toolbox.createChild({cls:"x-dlg-close"});
28351 this.close.on("click", this.closeClick, this);
28352 this.close.addClassOnOver("x-dlg-close-over");
28354 if(this.collapsible !== false){
28355 this.collapseBtn = this.toolbox.createChild({cls:"x-dlg-collapse"});
28356 this.collapseBtn.on("click", this.collapseClick, this);
28357 this.collapseBtn.addClassOnOver("x-dlg-collapse-over");
28358 this.header.on("dblclick", this.collapseClick, this);
28360 if(this.resizable !== false){
28361 this.el.addClass("x-dlg-resizable");
28362 this.resizer = new Roo.Resizable(el, {
28363 minWidth: this.minWidth || 80,
28364 minHeight:this.minHeight || 80,
28365 handles: this.resizeHandles || "all",
28368 this.resizer.on("beforeresize", this.beforeResize, this);
28369 this.resizer.on("resize", this.onResize, this);
28371 if(this.draggable !== false){
28372 el.addClass("x-dlg-draggable");
28373 if (!this.proxyDrag) {
28374 var dd = new Roo.dd.DD(el.dom.id, "WindowDrag");
28377 var dd = new Roo.dd.DDProxy(el.dom.id, "WindowDrag", {dragElId: this.proxy.id});
28379 dd.setHandleElId(this.header.id);
28380 dd.endDrag = this.endMove.createDelegate(this);
28381 dd.startDrag = this.startMove.createDelegate(this);
28382 dd.onDrag = this.onDrag.createDelegate(this);
28387 this.mask = dh.append(document.body, {tag: "div", cls:"x-dlg-mask"}, true);
28388 this.mask.enableDisplayMode("block");
28390 this.el.addClass("x-dlg-modal");
28393 this.shadow = new Roo.Shadow({
28394 mode : typeof this.shadow == "string" ? this.shadow : "sides",
28395 offset : this.shadowOffset
28398 this.shadowOffset = 0;
28400 if(Roo.useShims && this.shim !== false){
28401 this.shim = this.el.createShim();
28402 this.shim.hide = this.hideAction;
28410 if (this.buttons) {
28411 var bts= this.buttons;
28413 Roo.each(bts, function(b) {
28422 * Fires when a key is pressed
28423 * @param {Roo.BasicDialog} this
28424 * @param {Roo.EventObject} e
28429 * Fires when this dialog is moved by the user.
28430 * @param {Roo.BasicDialog} this
28431 * @param {Number} x The new page X
28432 * @param {Number} y The new page Y
28437 * Fires when this dialog is resized by the user.
28438 * @param {Roo.BasicDialog} this
28439 * @param {Number} width The new width
28440 * @param {Number} height The new height
28444 * @event beforehide
28445 * Fires before this dialog is hidden.
28446 * @param {Roo.BasicDialog} this
28448 "beforehide" : true,
28451 * Fires when this dialog is hidden.
28452 * @param {Roo.BasicDialog} this
28456 * @event beforeshow
28457 * Fires before this dialog is shown.
28458 * @param {Roo.BasicDialog} this
28460 "beforeshow" : true,
28463 * Fires when this dialog is shown.
28464 * @param {Roo.BasicDialog} this
28468 el.on("keydown", this.onKeyDown, this);
28469 el.on("mousedown", this.toFront, this);
28470 Roo.EventManager.onWindowResize(this.adjustViewport, this, true);
28472 Roo.DialogManager.register(this);
28473 Roo.BasicDialog.superclass.constructor.call(this);
28476 Roo.extend(Roo.BasicDialog, Roo.util.Observable, {
28477 shadowOffset: Roo.isIE ? 6 : 5,
28480 minButtonWidth: 75,
28481 defaultButton: null,
28482 buttonAlign: "right",
28487 * Sets the dialog title text
28488 * @param {String} text The title text to display
28489 * @return {Roo.BasicDialog} this
28491 setTitle : function(text){
28492 this.header.update(text);
28497 closeClick : function(){
28502 collapseClick : function(){
28503 this[this.collapsed ? "expand" : "collapse"]();
28507 * Collapses the dialog to its minimized state (only the title bar is visible).
28508 * Equivalent to the user clicking the collapse dialog button.
28510 collapse : function(){
28511 if(!this.collapsed){
28512 this.collapsed = true;
28513 this.el.addClass("x-dlg-collapsed");
28514 this.restoreHeight = this.el.getHeight();
28515 this.resizeTo(this.el.getWidth(), this.header.getHeight());
28520 * Expands a collapsed dialog back to its normal state. Equivalent to the user
28521 * clicking the expand dialog button.
28523 expand : function(){
28524 if(this.collapsed){
28525 this.collapsed = false;
28526 this.el.removeClass("x-dlg-collapsed");
28527 this.resizeTo(this.el.getWidth(), this.restoreHeight);
28532 * Reinitializes the tabs component, clearing out old tabs and finding new ones.
28533 * @return {Roo.TabPanel} The tabs component
28535 initTabs : function(){
28536 var tabs = this.getTabs();
28537 while(tabs.getTab(0)){
28540 this.el.select(this.tabTag+'.x-dlg-tab').each(function(el){
28542 tabs.addTab(Roo.id(dom), dom.title);
28550 beforeResize : function(){
28551 this.resizer.minHeight = Math.max(this.minHeight, this.getHeaderFooterHeight(true)+40);
28555 onResize : function(){
28556 this.refreshSize();
28557 this.syncBodyHeight();
28558 this.adjustAssets();
28560 this.fireEvent("resize", this, this.size.width, this.size.height);
28564 onKeyDown : function(e){
28565 if(this.isVisible()){
28566 this.fireEvent("keydown", this, e);
28571 * Resizes the dialog.
28572 * @param {Number} width
28573 * @param {Number} height
28574 * @return {Roo.BasicDialog} this
28576 resizeTo : function(width, height){
28577 this.el.setSize(width, height);
28578 this.size = {width: width, height: height};
28579 this.syncBodyHeight();
28580 if(this.fixedcenter){
28583 if(this.isVisible()){
28584 this.constrainXY();
28585 this.adjustAssets();
28587 this.fireEvent("resize", this, width, height);
28593 * Resizes the dialog to fit the specified content size.
28594 * @param {Number} width
28595 * @param {Number} height
28596 * @return {Roo.BasicDialog} this
28598 setContentSize : function(w, h){
28599 h += this.getHeaderFooterHeight() + this.body.getMargins("tb");
28600 w += this.body.getMargins("lr") + this.bwrap.getMargins("lr") + this.centerBg.getPadding("lr");
28601 //if(!this.el.isBorderBox()){
28602 h += this.body.getPadding("tb") + this.bwrap.getBorderWidth("tb") + this.body.getBorderWidth("tb") + this.el.getBorderWidth("tb");
28603 w += this.body.getPadding("lr") + this.bwrap.getBorderWidth("lr") + this.body.getBorderWidth("lr") + this.bwrap.getPadding("lr") + this.el.getBorderWidth("lr");
28606 h += this.tabs.stripWrap.getHeight() + this.tabs.bodyEl.getMargins("tb") + this.tabs.bodyEl.getPadding("tb");
28607 w += this.tabs.bodyEl.getMargins("lr") + this.tabs.bodyEl.getPadding("lr");
28609 this.resizeTo(w, h);
28614 * Adds a key listener for when this dialog is displayed. This allows you to hook in a function that will be
28615 * executed in response to a particular key being pressed while the dialog is active.
28616 * @param {Number/Array/Object} key Either the numeric key code, array of key codes or an object with the following options:
28617 * {key: (number or array), shift: (true/false), ctrl: (true/false), alt: (true/false)}
28618 * @param {Function} fn The function to call
28619 * @param {Object} scope (optional) The scope of the function
28620 * @return {Roo.BasicDialog} this
28622 addKeyListener : function(key, fn, scope){
28623 var keyCode, shift, ctrl, alt;
28624 if(typeof key == "object" && !(key instanceof Array)){
28625 keyCode = key["key"];
28626 shift = key["shift"];
28627 ctrl = key["ctrl"];
28632 var handler = function(dlg, e){
28633 if((!shift || e.shiftKey) && (!ctrl || e.ctrlKey) && (!alt || e.altKey)){
28634 var k = e.getKey();
28635 if(keyCode instanceof Array){
28636 for(var i = 0, len = keyCode.length; i < len; i++){
28637 if(keyCode[i] == k){
28638 fn.call(scope || window, dlg, k, e);
28644 fn.call(scope || window, dlg, k, e);
28649 this.on("keydown", handler);
28654 * Returns the TabPanel component (creates it if it doesn't exist).
28655 * Note: If you wish to simply check for the existence of tabs without creating them,
28656 * check for a null 'tabs' property.
28657 * @return {Roo.TabPanel} The tabs component
28659 getTabs : function(){
28661 this.el.addClass("x-dlg-auto-tabs");
28662 this.body.addClass(this.tabPosition == "bottom" ? "x-tabs-bottom" : "x-tabs-top");
28663 this.tabs = new Roo.TabPanel(this.body.dom, this.tabPosition == "bottom");
28669 * Adds a button to the footer section of the dialog.
28670 * @param {String/Object} config A string becomes the button text, an object can either be a Button config
28671 * object or a valid Roo.DomHelper element config
28672 * @param {Function} handler The function called when the button is clicked
28673 * @param {Object} scope (optional) The scope of the handler function (accepts position as a property)
28674 * @return {Roo.Button} The new button
28676 addButton : function(config, handler, scope){
28677 var dh = Roo.DomHelper;
28679 this.footer = dh.append(this.bwrap, {tag: "div", cls:"x-dlg-ft"}, true);
28681 if(!this.btnContainer){
28682 var tb = this.footer.createChild({
28684 cls:"x-dlg-btns x-dlg-btns-"+this.buttonAlign,
28685 html:'<table cellspacing="0"><tbody><tr></tr></tbody></table><div class="x-clear"></div>'
28687 this.btnContainer = tb.firstChild.firstChild.firstChild;
28692 minWidth: this.minButtonWidth,
28695 if(typeof config == "string"){
28696 bconfig.text = config;
28699 bconfig.dhconfig = config;
28701 Roo.apply(bconfig, config);
28705 if ((typeof(bconfig.position) != 'undefined') && bconfig.position < this.btnContainer.childNodes.length-1) {
28706 bconfig.position = Math.max(0, bconfig.position);
28707 fc = this.btnContainer.childNodes[bconfig.position];
28710 var btn = new Roo.Button(
28712 this.btnContainer.insertBefore(document.createElement("td"),fc)
28713 : this.btnContainer.appendChild(document.createElement("td")),
28714 //Roo.get(this.btnContainer).createChild( { tag: 'td'}, fc ),
28717 this.syncBodyHeight();
28720 * Array of all the buttons that have been added to this dialog via addButton
28725 this.buttons.push(btn);
28730 * Sets the default button to be focused when the dialog is displayed.
28731 * @param {Roo.BasicDialog.Button} btn The button object returned by {@link #addButton}
28732 * @return {Roo.BasicDialog} this
28734 setDefaultButton : function(btn){
28735 this.defaultButton = btn;
28740 getHeaderFooterHeight : function(safe){
28743 height += this.header.getHeight();
28746 var fm = this.footer.getMargins();
28747 height += (this.footer.getHeight()+fm.top+fm.bottom);
28749 height += this.bwrap.getPadding("tb")+this.bwrap.getBorderWidth("tb");
28750 height += this.centerBg.getPadding("tb");
28755 syncBodyHeight : function(){
28756 var bd = this.body, cb = this.centerBg, bw = this.bwrap;
28757 var height = this.size.height - this.getHeaderFooterHeight(false);
28758 bd.setHeight(height-bd.getMargins("tb"));
28759 var hh = this.header.getHeight();
28760 var h = this.size.height-hh;
28762 bw.setLeftTop(cb.getPadding("l"), hh+cb.getPadding("t"));
28763 bw.setHeight(h-cb.getPadding("tb"));
28764 bw.setWidth(this.el.getWidth(true)-cb.getPadding("lr"));
28765 bd.setWidth(bw.getWidth(true));
28767 this.tabs.syncHeight();
28769 this.tabs.el.repaint();
28775 * Restores the previous state of the dialog if Roo.state is configured.
28776 * @return {Roo.BasicDialog} this
28778 restoreState : function(){
28779 var box = Roo.state.Manager.get(this.stateId || (this.el.id + "-state"));
28780 if(box && box.width){
28781 this.xy = [box.x, box.y];
28782 this.resizeTo(box.width, box.height);
28788 beforeShow : function(){
28790 if(this.fixedcenter){
28791 this.xy = this.el.getCenterXY(true);
28794 Roo.get(document.body).addClass("x-body-masked");
28795 this.mask.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
28798 this.constrainXY();
28802 animShow : function(){
28803 var b = Roo.get(this.animateTarget, true).getBox();
28804 this.proxy.setSize(b.width, b.height);
28805 this.proxy.setLocation(b.x, b.y);
28807 this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height,
28808 true, .35, this.showEl.createDelegate(this));
28812 * Shows the dialog.
28813 * @param {String/HTMLElement/Roo.Element} animateTarget (optional) Reset the animation target
28814 * @return {Roo.BasicDialog} this
28816 show : function(animateTarget){
28817 if (this.fireEvent("beforeshow", this) === false){
28820 if(this.syncHeightBeforeShow){
28821 this.syncBodyHeight();
28822 }else if(this.firstShow){
28823 this.firstShow = false;
28824 this.syncBodyHeight(); // sync the height on the first show instead of in the constructor
28826 this.animateTarget = animateTarget || this.animateTarget;
28827 if(!this.el.isVisible()){
28829 if(this.animateTarget){
28839 showEl : function(){
28841 this.el.setXY(this.xy);
28843 this.adjustAssets(true);
28846 // IE peekaboo bug - fix found by Dave Fenwick
28850 this.fireEvent("show", this);
28854 * Focuses the dialog. If a defaultButton is set, it will receive focus, otherwise the
28855 * dialog itself will receive focus.
28857 focus : function(){
28858 if(this.defaultButton){
28859 this.defaultButton.focus();
28861 this.focusEl.focus();
28866 constrainXY : function(){
28867 if(this.constraintoviewport !== false){
28868 if(!this.viewSize){
28869 if(this.container){
28870 var s = this.container.getSize();
28871 this.viewSize = [s.width, s.height];
28873 this.viewSize = [Roo.lib.Dom.getViewWidth(),Roo.lib.Dom.getViewHeight()];
28876 var s = Roo.get(this.container||document).getScroll();
28878 var x = this.xy[0], y = this.xy[1];
28879 var w = this.size.width, h = this.size.height;
28880 var vw = this.viewSize[0], vh = this.viewSize[1];
28881 // only move it if it needs it
28883 // first validate right/bottom
28884 if(x + w > vw+s.left){
28888 if(y + h > vh+s.top){
28892 // then make sure top/left isn't negative
28904 if(this.isVisible()){
28905 this.el.setLocation(x, y);
28906 this.adjustAssets();
28913 onDrag : function(){
28914 if(!this.proxyDrag){
28915 this.xy = this.el.getXY();
28916 this.adjustAssets();
28921 adjustAssets : function(doShow){
28922 var x = this.xy[0], y = this.xy[1];
28923 var w = this.size.width, h = this.size.height;
28924 if(doShow === true){
28926 this.shadow.show(this.el);
28932 if(this.shadow && this.shadow.isVisible()){
28933 this.shadow.show(this.el);
28935 if(this.shim && this.shim.isVisible()){
28936 this.shim.setBounds(x, y, w, h);
28941 adjustViewport : function(w, h){
28943 w = Roo.lib.Dom.getViewWidth();
28944 h = Roo.lib.Dom.getViewHeight();
28947 this.viewSize = [w, h];
28948 if(this.modal && this.mask.isVisible()){
28949 this.mask.setSize(w, h); // first make sure the mask isn't causing overflow
28950 this.mask.setSize(Roo.lib.Dom.getViewWidth(true), Roo.lib.Dom.getViewHeight(true));
28952 if(this.isVisible()){
28953 this.constrainXY();
28958 * Destroys this dialog and all its supporting elements (including any tabs, shim,
28959 * shadow, proxy, mask, etc.) Also removes all event listeners.
28960 * @param {Boolean} removeEl (optional) true to remove the element from the DOM
28962 destroy : function(removeEl){
28963 if(this.isVisible()){
28964 this.animateTarget = null;
28967 Roo.EventManager.removeResizeListener(this.adjustViewport, this);
28969 this.tabs.destroy(removeEl);
28982 for(var i = 0, len = this.buttons.length; i < len; i++){
28983 this.buttons[i].destroy();
28986 this.el.removeAllListeners();
28987 if(removeEl === true){
28988 this.el.update("");
28991 Roo.DialogManager.unregister(this);
28995 startMove : function(){
28996 if(this.proxyDrag){
28999 if(this.constraintoviewport !== false){
29000 this.dd.constrainTo(document.body, {right: this.shadowOffset, bottom: this.shadowOffset});
29005 endMove : function(){
29006 if(!this.proxyDrag){
29007 Roo.dd.DD.prototype.endDrag.apply(this.dd, arguments);
29009 Roo.dd.DDProxy.prototype.endDrag.apply(this.dd, arguments);
29012 this.refreshSize();
29013 this.adjustAssets();
29015 this.fireEvent("move", this, this.xy[0], this.xy[1]);
29019 * Brings this dialog to the front of any other visible dialogs
29020 * @return {Roo.BasicDialog} this
29022 toFront : function(){
29023 Roo.DialogManager.bringToFront(this);
29028 * Sends this dialog to the back (under) of any other visible dialogs
29029 * @return {Roo.BasicDialog} this
29031 toBack : function(){
29032 Roo.DialogManager.sendToBack(this);
29037 * Centers this dialog in the viewport
29038 * @return {Roo.BasicDialog} this
29040 center : function(){
29041 var xy = this.el.getCenterXY(true);
29042 this.moveTo(xy[0], xy[1]);
29047 * Moves the dialog's top-left corner to the specified point
29048 * @param {Number} x
29049 * @param {Number} y
29050 * @return {Roo.BasicDialog} this
29052 moveTo : function(x, y){
29054 if(this.isVisible()){
29055 this.el.setXY(this.xy);
29056 this.adjustAssets();
29062 * Aligns the dialog to the specified element
29063 * @param {String/HTMLElement/Roo.Element} element The element to align to.
29064 * @param {String} position The position to align to (see {@link Roo.Element#alignTo} for more details).
29065 * @param {Array} offsets (optional) Offset the positioning by [x, y]
29066 * @return {Roo.BasicDialog} this
29068 alignTo : function(element, position, offsets){
29069 this.xy = this.el.getAlignToXY(element, position, offsets);
29070 if(this.isVisible()){
29071 this.el.setXY(this.xy);
29072 this.adjustAssets();
29078 * Anchors an element to another element and realigns it when the window is resized.
29079 * @param {String/HTMLElement/Roo.Element} element The element to align to.
29080 * @param {String} position The position to align to (see {@link Roo.Element#alignTo} for more details)
29081 * @param {Array} offsets (optional) Offset the positioning by [x, y]
29082 * @param {Boolean/Number} monitorScroll (optional) true to monitor body scroll and reposition. If this parameter
29083 * is a number, it is used as the buffer delay (defaults to 50ms).
29084 * @return {Roo.BasicDialog} this
29086 anchorTo : function(el, alignment, offsets, monitorScroll){
29087 var action = function(){
29088 this.alignTo(el, alignment, offsets);
29090 Roo.EventManager.onWindowResize(action, this);
29091 var tm = typeof monitorScroll;
29092 if(tm != 'undefined'){
29093 Roo.EventManager.on(window, 'scroll', action, this,
29094 {buffer: tm == 'number' ? monitorScroll : 50});
29101 * Returns true if the dialog is visible
29102 * @return {Boolean}
29104 isVisible : function(){
29105 return this.el.isVisible();
29109 animHide : function(callback){
29110 var b = Roo.get(this.animateTarget).getBox();
29112 this.proxy.setBounds(this.xy[0], this.xy[1], this.size.width, this.size.height);
29114 this.proxy.setBounds(b.x, b.y, b.width, b.height, true, .35,
29115 this.hideEl.createDelegate(this, [callback]));
29119 * Hides the dialog.
29120 * @param {Function} callback (optional) Function to call when the dialog is hidden
29121 * @return {Roo.BasicDialog} this
29123 hide : function(callback){
29124 if (this.fireEvent("beforehide", this) === false){
29128 this.shadow.hide();
29133 if(this.animateTarget){
29134 this.animHide(callback);
29137 this.hideEl(callback);
29143 hideEl : function(callback){
29147 Roo.get(document.body).removeClass("x-body-masked");
29149 this.fireEvent("hide", this);
29150 if(typeof callback == "function"){
29156 hideAction : function(){
29157 this.setLeft("-10000px");
29158 this.setTop("-10000px");
29159 this.setStyle("visibility", "hidden");
29163 refreshSize : function(){
29164 this.size = this.el.getSize();
29165 this.xy = this.el.getXY();
29166 Roo.state.Manager.set(this.stateId || this.el.id + "-state", this.el.getBox());
29170 // z-index is managed by the DialogManager and may be overwritten at any time
29171 setZIndex : function(index){
29173 this.mask.setStyle("z-index", index);
29176 this.shim.setStyle("z-index", ++index);
29179 this.shadow.setZIndex(++index);
29181 this.el.setStyle("z-index", ++index);
29183 this.proxy.setStyle("z-index", ++index);
29186 this.resizer.proxy.setStyle("z-index", ++index);
29189 this.lastZIndex = index;
29193 * Returns the element for this dialog
29194 * @return {Roo.Element} The underlying dialog Element
29196 getEl : function(){
29202 * @class Roo.DialogManager
29203 * Provides global access to BasicDialogs that have been created and
29204 * support for z-indexing (layering) multiple open dialogs.
29206 Roo.DialogManager = function(){
29208 var accessList = [];
29212 var sortDialogs = function(d1, d2){
29213 return (!d1._lastAccess || d1._lastAccess < d2._lastAccess) ? -1 : 1;
29217 var orderDialogs = function(){
29218 accessList.sort(sortDialogs);
29219 var seed = Roo.DialogManager.zseed;
29220 for(var i = 0, len = accessList.length; i < len; i++){
29221 var dlg = accessList[i];
29223 dlg.setZIndex(seed + (i*10));
29230 * The starting z-index for BasicDialogs (defaults to 9000)
29231 * @type Number The z-index value
29236 register : function(dlg){
29237 list[dlg.id] = dlg;
29238 accessList.push(dlg);
29242 unregister : function(dlg){
29243 delete list[dlg.id];
29246 if(!accessList.indexOf){
29247 for( i = 0, len = accessList.length; i < len; i++){
29248 if(accessList[i] == dlg){
29249 accessList.splice(i, 1);
29254 i = accessList.indexOf(dlg);
29256 accessList.splice(i, 1);
29262 * Gets a registered dialog by id
29263 * @param {String/Object} id The id of the dialog or a dialog
29264 * @return {Roo.BasicDialog} this
29266 get : function(id){
29267 return typeof id == "object" ? id : list[id];
29271 * Brings the specified dialog to the front
29272 * @param {String/Object} dlg The id of the dialog or a dialog
29273 * @return {Roo.BasicDialog} this
29275 bringToFront : function(dlg){
29276 dlg = this.get(dlg);
29279 dlg._lastAccess = new Date().getTime();
29286 * Sends the specified dialog to the back
29287 * @param {String/Object} dlg The id of the dialog or a dialog
29288 * @return {Roo.BasicDialog} this
29290 sendToBack : function(dlg){
29291 dlg = this.get(dlg);
29292 dlg._lastAccess = -(new Date().getTime());
29298 * Hides all dialogs
29300 hideAll : function(){
29301 for(var id in list){
29302 if(list[id] && typeof list[id] != "function" && list[id].isVisible()){
29311 * @class Roo.LayoutDialog
29312 * @extends Roo.BasicDialog
29313 * Dialog which provides adjustments for working with a layout in a Dialog.
29314 * Add your necessary layout config options to the dialog's config.<br>
29315 * Example usage (including a nested layout):
29318 dialog = new Roo.LayoutDialog("download-dlg", {
29327 // layout config merges with the dialog config
29329 tabPosition: "top",
29330 alwaysShowTabs: true
29333 dialog.addKeyListener(27, dialog.hide, dialog);
29334 dialog.setDefaultButton(dialog.addButton("Close", dialog.hide, dialog));
29335 dialog.addButton("Build It!", this.getDownload, this);
29337 // we can even add nested layouts
29338 var innerLayout = new Roo.BorderLayout("dl-inner", {
29348 innerLayout.beginUpdate();
29349 innerLayout.add("east", new Roo.ContentPanel("dl-details"));
29350 innerLayout.add("center", new Roo.ContentPanel("selection-panel"));
29351 innerLayout.endUpdate(true);
29353 var layout = dialog.getLayout();
29354 layout.beginUpdate();
29355 layout.add("center", new Roo.ContentPanel("standard-panel",
29356 {title: "Download the Source", fitToFrame:true}));
29357 layout.add("center", new Roo.NestedLayoutPanel(innerLayout,
29358 {title: "Build your own roo.js"}));
29359 layout.getRegion("center").showPanel(sp);
29360 layout.endUpdate();
29364 * @param {String/HTMLElement/Roo.Element} el The id of or container element, or config
29365 * @param {Object} config configuration options
29367 Roo.LayoutDialog = function(el, cfg){
29370 if (typeof(cfg) == 'undefined') {
29371 config = Roo.apply({}, el);
29372 el = Roo.get( document.documentElement || document.body).createChild();
29373 //config.autoCreate = true;
29377 config.autoTabs = false;
29378 Roo.LayoutDialog.superclass.constructor.call(this, el, config);
29379 this.body.setStyle({overflow:"hidden", position:"relative"});
29380 this.layout = new Roo.BorderLayout(this.body.dom, config);
29381 this.layout.monitorWindowResize = false;
29382 this.el.addClass("x-dlg-auto-layout");
29383 // fix case when center region overwrites center function
29384 this.center = Roo.BasicDialog.prototype.center;
29385 this.on("show", this.layout.layout, this.layout, true);
29386 if (config.items) {
29387 var xitems = config.items;
29388 delete config.items;
29389 Roo.each(xitems, this.addxtype, this);
29394 Roo.extend(Roo.LayoutDialog, Roo.BasicDialog, {
29396 * Ends update of the layout <strike>and resets display to none</strike>. Use standard beginUpdate/endUpdate on the layout.
29399 endUpdate : function(){
29400 this.layout.endUpdate();
29404 * Begins an update of the layout <strike>and sets display to block and visibility to hidden</strike>. Use standard beginUpdate/endUpdate on the layout.
29407 beginUpdate : function(){
29408 this.layout.beginUpdate();
29412 * Get the BorderLayout for this dialog
29413 * @return {Roo.BorderLayout}
29415 getLayout : function(){
29416 return this.layout;
29419 showEl : function(){
29420 Roo.LayoutDialog.superclass.showEl.apply(this, arguments);
29422 this.layout.layout();
29427 // Use the syncHeightBeforeShow config option to control this automatically
29428 syncBodyHeight : function(){
29429 Roo.LayoutDialog.superclass.syncBodyHeight.call(this);
29430 if(this.layout){this.layout.layout();}
29434 * Add an xtype element (actually adds to the layout.)
29435 * @return {Object} xdata xtype object data.
29438 addxtype : function(c) {
29439 return this.layout.addxtype(c);